mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-23 10:51:30 +00:00
Compare commits
22 Commits
eslint/fix
...
resolve_Co
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9780ff3ad | ||
|
|
aff7133095 | ||
|
|
bfd4948fb9 | ||
|
|
1c54459708 | ||
|
|
df3b18d585 | ||
|
|
882f0e1554 | ||
|
|
b67b76cc87 | ||
|
|
734ee1e436 | ||
|
|
ff498b51e2 | ||
|
|
ed1ffb692f | ||
|
|
f7fa3f7c09 | ||
|
|
6ebf19c0c9 | ||
|
|
deb18e5aa1 | ||
|
|
6da226fedb | ||
|
|
d301294eb5 | ||
|
|
9fd50ee9dd | ||
|
|
413472045d | ||
|
|
989f7b9cd2 | ||
|
|
00ccf4e525 | ||
|
|
afccd262a9 | ||
|
|
e9ad009f79 | ||
|
|
fc1067137b |
@@ -6,7 +6,7 @@ src/Api/Apis.ts
|
|||||||
src/AuthType.ts
|
src/AuthType.ts
|
||||||
src/Bindings/BindingHandlersRegisterer.ts
|
src/Bindings/BindingHandlersRegisterer.ts
|
||||||
src/Bindings/ReactBindingHandler.ts
|
src/Bindings/ReactBindingHandler.ts
|
||||||
src/Common/Constants.ts
|
src/Common/Constants/index.ts
|
||||||
src/Common/CosmosClient.test.ts
|
src/Common/CosmosClient.test.ts
|
||||||
src/Common/CosmosClient.ts
|
src/Common/CosmosClient.ts
|
||||||
src/Common/DataAccessUtilityBase.test.ts
|
src/Common/DataAccessUtilityBase.test.ts
|
||||||
@@ -44,6 +44,8 @@ src/Explorer/DataSamples/ContainerSampleGenerator.test.ts
|
|||||||
src/Explorer/DataSamples/ContainerSampleGenerator.ts
|
src/Explorer/DataSamples/ContainerSampleGenerator.ts
|
||||||
src/Explorer/DataSamples/DataSamplesUtil.test.ts
|
src/Explorer/DataSamples/DataSamplesUtil.test.ts
|
||||||
src/Explorer/DataSamples/DataSamplesUtil.ts
|
src/Explorer/DataSamples/DataSamplesUtil.ts
|
||||||
|
src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.test.ts
|
||||||
|
src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.ts
|
||||||
src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.test.ts
|
src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.test.ts
|
||||||
src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts
|
src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.ts
|
||||||
src/Explorer/Graph/GraphExplorerComponent/EdgeInfoCache.ts
|
src/Explorer/Graph/GraphExplorerComponent/EdgeInfoCache.ts
|
||||||
@@ -79,17 +81,13 @@ 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/DataTableOperations.ts
|
||||||
src/Explorer/Tables/DataTable/DataTableViewModel.ts
|
src/Explorer/Tables/DataTable/DataTableViewModel.ts
|
||||||
src/Explorer/Tables/DataTable/TableCommands.ts
|
# src/Explorer/Tables/DataTable/TableCommands.ts
|
||||||
src/Explorer/Tables/DataTable/TableEntityCache.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/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
|
||||||
@@ -113,15 +111,10 @@ 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/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/ReactDevTools.ts
|
||||||
src/Shared/Constants.ts
|
src/Shared/Constants.ts
|
||||||
@@ -141,7 +134,7 @@ 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/GraphExplorer.tsx
|
||||||
src/Explorer/Graph/GraphExplorerComponent/GraphVizComponent.tsx
|
src/Explorer/Graph/GraphExplorerComponent/GraphVizComponent.tsx
|
||||||
src/Explorer/Graph/GraphExplorerComponent/LeftPaneComponent.tsx
|
src/Explorer/Graph/GraphExplorerComponent/LeftPaneComponent.tsx
|
||||||
src/Explorer/Graph/GraphExplorerComponent/MiddlePaneComponent.tsx
|
src/Explorer/Graph/GraphExplorerComponent/MiddlePaneComponent.tsx
|
||||||
@@ -151,10 +144,10 @@ src/Explorer/Graph/GraphExplorerComponent/ReadOnlyNodePropertiesComponent.test.t
|
|||||||
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/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/NotebookReadOnlyRenderer.tsx
|
; src/Explorer/Notebook/NotebookRenderer/NotebookReadOnlyRenderer.tsx
|
||||||
src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.tsx
|
src/Explorer/Notebook/NotebookRenderer/NotebookRenderer.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
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ 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",
|
||||||
|
|||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -22,5 +22,6 @@
|
|||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": true,
|
"source.fixAll.eslint": true,
|
||||||
"source.organizeImports": true
|
"source.organizeImports": true
|
||||||
}
|
},
|
||||||
|
"typescript.preferences.importModuleSpecifier": "non-relative"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ module.exports = {
|
|||||||
global: {
|
global: {
|
||||||
branches: 25,
|
branches: 25,
|
||||||
functions: 25,
|
functions: 25,
|
||||||
lines: 29.5,
|
lines: 29,
|
||||||
statements: 29.5,
|
statements: 29,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -129,6 +129,8 @@ 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: {},
|
||||||
|
|
||||||
|
|||||||
@@ -1,403 +0,0 @@
|
|||||||
export class CodeOfConductEndpoints {
|
|
||||||
public static privacyStatement: string = "https://aka.ms/ms-privacy-policy";
|
|
||||||
public static codeOfConduct: string = "https://aka.ms/cosmos-code-of-conduct";
|
|
||||||
public static termsOfUse: string = "https://aka.ms/ms-terms-of-use";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EndpointsRegex {
|
|
||||||
public static readonly cassandra = [
|
|
||||||
"AccountEndpoint=(.*).cassandra.cosmosdb.azure.com",
|
|
||||||
"HostName=(.*).cassandra.cosmos.azure.com",
|
|
||||||
];
|
|
||||||
public static readonly mongo = "mongodb://.*:(.*)@(.*).documents.azure.com";
|
|
||||||
public static readonly mongoCompute = "mongodb://.*:(.*)@(.*).mongo.cosmos.azure.com";
|
|
||||||
public static readonly sql = "AccountEndpoint=https://(.*).documents.azure.com";
|
|
||||||
public static readonly table = "TableEndpoint=https://(.*).table.cosmosdb.azure.com";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ApiEndpoints {
|
|
||||||
public static runtimeProxy: string = "/api/RuntimeProxy";
|
|
||||||
public static guestRuntimeProxy: string = "/api/guest/RuntimeProxy";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ServerIds {
|
|
||||||
public static localhost: string = "localhost";
|
|
||||||
public static blackforest: string = "blackforest";
|
|
||||||
public static fairfax: string = "fairfax";
|
|
||||||
public static mooncake: string = "mooncake";
|
|
||||||
public static productionPortal: string = "prod";
|
|
||||||
public static dev: string = "dev";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ArmApiVersions {
|
|
||||||
public static readonly documentDB: string = "2015-11-06";
|
|
||||||
public static readonly arcadia: string = "2019-06-01-preview";
|
|
||||||
public static readonly arcadiaLivy: string = "2019-11-01-preview";
|
|
||||||
public static readonly arm: string = "2015-11-01";
|
|
||||||
public static readonly armFeatures: string = "2014-08-01-preview";
|
|
||||||
public static readonly publicVersion = "2020-04-01";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ArmResourceTypes {
|
|
||||||
public static readonly notebookWorkspaces = "Microsoft.DocumentDB/databaseAccounts/notebookWorkspaces";
|
|
||||||
public static readonly synapseWorkspaces = "Microsoft.Synapse/workspaces";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class BackendDefaults {
|
|
||||||
public static partitionKeyKind = "Hash";
|
|
||||||
public static singlePartitionStorageInGb: string = "10";
|
|
||||||
public static multiPartitionStorageInGb: string = "100";
|
|
||||||
public static maxChangeFeedRetentionDuration: number = 10;
|
|
||||||
public static partitionKeyVersion = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ClientDefaults {
|
|
||||||
public static requestTimeoutMs: number = 60000;
|
|
||||||
public static portalCacheTimeoutMs: number = 10000;
|
|
||||||
public static errorNotificationTimeoutMs: number = 5000;
|
|
||||||
public static copyHelperTimeoutMs: number = 2000;
|
|
||||||
public static waitForDOMElementMs: number = 500;
|
|
||||||
public static cacheBustingTimeoutMs: number =
|
|
||||||
10 /** minutes **/ * 60 /** to seconds **/ * 1000 /** to milliseconds **/;
|
|
||||||
public static databaseThroughputIncreaseFactor: number = 100;
|
|
||||||
public static readonly arcadiaTokenRefreshInterval: number =
|
|
||||||
20 /** minutes **/ * 60 /** to seconds **/ * 1000 /** to milliseconds **/;
|
|
||||||
public static readonly arcadiaTokenRefreshIntervalPaddingMs: number = 2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum AccountKind {
|
|
||||||
DocumentDB = "DocumentDB",
|
|
||||||
MongoDB = "MongoDB",
|
|
||||||
Parse = "Parse",
|
|
||||||
GlobalDocumentDB = "GlobalDocumentDB",
|
|
||||||
Default = "DocumentDB",
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CorrelationBackend {
|
|
||||||
public static Url: string = "https://aka.ms/cosmosdbanalytics";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CapabilityNames {
|
|
||||||
public static EnableTable: string = "EnableTable";
|
|
||||||
public static EnableGremlin: string = "EnableGremlin";
|
|
||||||
public static EnableCassandra: string = "EnableCassandra";
|
|
||||||
public static EnableAutoScale: string = "EnableAutoScale";
|
|
||||||
public static readonly EnableNotebooks: string = "EnableNotebooks";
|
|
||||||
public static readonly EnableStorageAnalytics: string = "EnableStorageAnalytics";
|
|
||||||
public static readonly EnableMongo: string = "EnableMongo";
|
|
||||||
public static readonly EnableServerless: string = "EnableServerless";
|
|
||||||
}
|
|
||||||
|
|
||||||
// flight names returned from the portal are always lowercase
|
|
||||||
export class Flights {
|
|
||||||
public static readonly SettingsV2 = "settingsv2";
|
|
||||||
public static readonly MongoIndexEditor = "mongoindexeditor";
|
|
||||||
public static readonly MongoIndexing = "mongoindexing";
|
|
||||||
public static readonly AutoscaleTest = "autoscaletest";
|
|
||||||
public static readonly PartitionKeyTest = "partitionkeytest";
|
|
||||||
public static readonly PKPartitionKeyTest = "pkpartitionkeytest";
|
|
||||||
public static readonly Phoenix = "phoenix";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AfecFeatures {
|
|
||||||
public static readonly Spark = "spark-public-preview";
|
|
||||||
public static readonly Notebooks = "sparknotebooks-public-preview";
|
|
||||||
public static readonly StorageAnalytics = "storageanalytics-public-preview";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TagNames {
|
|
||||||
public static defaultExperience: string = "defaultExperience";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class MongoDBAccounts {
|
|
||||||
public static protocol: string = "https";
|
|
||||||
public static defaultPort: string = "10255";
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum MongoBackendEndpointType {
|
|
||||||
local,
|
|
||||||
remote,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 435619 Add default endpoints per cloud and use regional only when available
|
|
||||||
export class CassandraBackend {
|
|
||||||
public static readonly createOrDeleteApi: string = "api/cassandra/createordelete";
|
|
||||||
public static readonly guestCreateOrDeleteApi: string = "api/guest/cassandra/createordelete";
|
|
||||||
public static readonly queryApi: string = "api/cassandra";
|
|
||||||
public static readonly guestQueryApi: string = "api/guest/cassandra";
|
|
||||||
public static readonly keysApi: string = "api/cassandra/keys";
|
|
||||||
public static readonly guestKeysApi: string = "api/guest/cassandra/keys";
|
|
||||||
public static readonly schemaApi: string = "api/cassandra/schema";
|
|
||||||
public static readonly guestSchemaApi: string = "api/guest/cassandra/schema";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Queries {
|
|
||||||
public static CustomPageOption: string = "custom";
|
|
||||||
public static UnlimitedPageOption: string = "unlimited";
|
|
||||||
public static itemsPerPage: number = 100;
|
|
||||||
public static unlimitedItemsPerPage: number = 100; // TODO: Figure out appropriate value so it works for accounts with a large number of partitions
|
|
||||||
|
|
||||||
public static QueryEditorMinHeightRatio: number = 0.1;
|
|
||||||
public static QueryEditorMaxHeightRatio: number = 0.4;
|
|
||||||
public static readonly DefaultMaxDegreeOfParallelism = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SavedQueries {
|
|
||||||
public static readonly CollectionName: string = "___Query";
|
|
||||||
public static readonly DatabaseName: string = "___Cosmos";
|
|
||||||
public static readonly OfferThroughput: number = 400;
|
|
||||||
public static readonly PartitionKeyProperty: string = "id";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DocumentsGridMetrics {
|
|
||||||
public static DocumentsPerPage: number = 100;
|
|
||||||
public static IndividualRowHeight: number = 34;
|
|
||||||
public static BufferHeight: number = 28;
|
|
||||||
public static SplitterMinWidth: number = 200;
|
|
||||||
public static SplitterMaxWidth: number = 360;
|
|
||||||
|
|
||||||
public static DocumentEditorMinWidthRatio: number = 0.2;
|
|
||||||
public static DocumentEditorMaxWidthRatio: number = 0.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Areas {
|
|
||||||
public static ResourceTree: string = "Resource Tree";
|
|
||||||
public static ContextualPane: string = "Contextual Pane";
|
|
||||||
public static Tab: string = "Tab";
|
|
||||||
public static ShareDialog: string = "Share Access Dialog";
|
|
||||||
public static Notebook: string = "Notebook";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class HttpHeaders {
|
|
||||||
public static activityId: string = "x-ms-activity-id";
|
|
||||||
public static apiType: string = "x-ms-cosmos-apitype";
|
|
||||||
public static authorization: string = "authorization";
|
|
||||||
public static collectionIndexTransformationProgress: string =
|
|
||||||
"x-ms-documentdb-collection-index-transformation-progress";
|
|
||||||
public static continuation: string = "x-ms-continuation";
|
|
||||||
public static correlationRequestId: string = "x-ms-correlation-request-id";
|
|
||||||
public static enableScriptLogging: string = "x-ms-documentdb-script-enable-logging";
|
|
||||||
public static guestAccessToken: string = "x-ms-encrypted-auth-token";
|
|
||||||
public static getReadOnlyKey: string = "x-ms-get-read-only-key";
|
|
||||||
public static connectionString: string = "x-ms-connection-string";
|
|
||||||
public static msDate: string = "x-ms-date";
|
|
||||||
public static location: string = "Location";
|
|
||||||
public static contentType: string = "Content-Type";
|
|
||||||
public static offerReplacePending: string = "x-ms-offer-replace-pending";
|
|
||||||
public static user: string = "x-ms-user";
|
|
||||||
public static populatePartitionStatistics: string = "x-ms-documentdb-populatepartitionstatistics";
|
|
||||||
public static queryMetrics: string = "x-ms-documentdb-query-metrics";
|
|
||||||
public static requestCharge: string = "x-ms-request-charge";
|
|
||||||
public static resourceQuota: string = "x-ms-resource-quota";
|
|
||||||
public static resourceUsage: string = "x-ms-resource-usage";
|
|
||||||
public static retryAfterMs: string = "x-ms-retry-after-ms";
|
|
||||||
public static scriptLogResults: string = "x-ms-documentdb-script-log-results";
|
|
||||||
public static populateCollectionThroughputInfo = "x-ms-documentdb-populatecollectionthroughputinfo";
|
|
||||||
public static supportSpatialLegacyCoordinates = "x-ms-documentdb-supportspatiallegacycoordinates";
|
|
||||||
public static usePolygonsSmallerThanAHemisphere = "x-ms-documentdb-usepolygonssmallerthanahemisphere";
|
|
||||||
public static autoPilotThroughput = "autoscaleSettings";
|
|
||||||
public static autoPilotThroughputSDK = "x-ms-cosmos-offer-autopilot-settings";
|
|
||||||
public static partitionKey: string = "x-ms-documentdb-partitionkey";
|
|
||||||
public static migrateOfferToManualThroughput: string = "x-ms-cosmos-migrate-offer-to-manual-throughput";
|
|
||||||
public static migrateOfferToAutopilot: string = "x-ms-cosmos-migrate-offer-to-autopilot";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ApiType {
|
|
||||||
// Mapped to hexadecimal values in the backend
|
|
||||||
public static readonly MongoDB: number = 1;
|
|
||||||
public static readonly Gremlin: number = 2;
|
|
||||||
public static readonly Cassandra: number = 4;
|
|
||||||
public static readonly Table: number = 8;
|
|
||||||
public static readonly SQL: number = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class HttpStatusCodes {
|
|
||||||
public static readonly OK: number = 200;
|
|
||||||
public static readonly Created: number = 201;
|
|
||||||
public static readonly Accepted: number = 202;
|
|
||||||
public static readonly NoContent: number = 204;
|
|
||||||
public static readonly NotModified: number = 304;
|
|
||||||
public static readonly Unauthorized: number = 401;
|
|
||||||
public static readonly Forbidden: number = 403;
|
|
||||||
public static readonly NotFound: number = 404;
|
|
||||||
public static readonly TooManyRequests: number = 429;
|
|
||||||
public static readonly Conflict: number = 409;
|
|
||||||
|
|
||||||
public static readonly InternalServerError: number = 500;
|
|
||||||
public static readonly BadGateway: number = 502;
|
|
||||||
public static readonly ServiceUnavailable: number = 503;
|
|
||||||
public static readonly GatewayTimeout: number = 504;
|
|
||||||
|
|
||||||
public static readonly RetryableStatusCodes: number[] = [
|
|
||||||
HttpStatusCodes.TooManyRequests,
|
|
||||||
HttpStatusCodes.InternalServerError, // TODO: Handle all 500s on Portal backend and remove from retries list
|
|
||||||
HttpStatusCodes.BadGateway,
|
|
||||||
HttpStatusCodes.ServiceUnavailable,
|
|
||||||
HttpStatusCodes.GatewayTimeout,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Urls {
|
|
||||||
public static feedbackEmail = "https://aka.ms/cosmosdbfeedback?subject=Cosmos%20DB%20Data%20Explorer%20Feedback";
|
|
||||||
public static autoscaleMigration = "https://aka.ms/cosmos-autoscale-migration";
|
|
||||||
public static freeTierInformation = "https://aka.ms/cosmos-free-tier";
|
|
||||||
public static cosmosPricing = "https://aka.ms/azure-cosmos-db-pricing";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class HashRoutePrefixes {
|
|
||||||
public static databases: string = "/dbs/{db_id}";
|
|
||||||
public static collections: string = "/dbs/{db_id}/colls/{coll_id}";
|
|
||||||
public static sprocHash: string = "/sprocs/";
|
|
||||||
public static sprocs: string = HashRoutePrefixes.collections + HashRoutePrefixes.sprocHash + "{sproc_id}";
|
|
||||||
public static docs: string = HashRoutePrefixes.collections + "/docs/{doc_id}/";
|
|
||||||
public static conflicts: string = HashRoutePrefixes.collections + "/conflicts";
|
|
||||||
|
|
||||||
public static databasesWithId(databaseId: string): string {
|
|
||||||
return this.databases.replace("{db_id}", databaseId).replace("/", ""); // strip the first slash since hasher adds it
|
|
||||||
}
|
|
||||||
|
|
||||||
public static collectionsWithIds(databaseId: string, collectionId: string): string {
|
|
||||||
const transformedDatabasePrefix: string = this.collections.replace("{db_id}", databaseId);
|
|
||||||
|
|
||||||
return transformedDatabasePrefix.replace("{coll_id}", collectionId).replace("/", ""); // strip the first slash since hasher adds it
|
|
||||||
}
|
|
||||||
|
|
||||||
public static sprocWithIds(
|
|
||||||
databaseId: string,
|
|
||||||
collectionId: string,
|
|
||||||
sprocId: string,
|
|
||||||
stripFirstSlash: boolean = true
|
|
||||||
): string {
|
|
||||||
const transformedDatabasePrefix: string = this.sprocs.replace("{db_id}", databaseId);
|
|
||||||
|
|
||||||
const transformedSprocRoute: string = transformedDatabasePrefix
|
|
||||||
.replace("{coll_id}", collectionId)
|
|
||||||
.replace("{sproc_id}", sprocId);
|
|
||||||
if (!!stripFirstSlash) {
|
|
||||||
return transformedSprocRoute.replace("/", ""); // strip the first slash since hasher adds it
|
|
||||||
}
|
|
||||||
|
|
||||||
return transformedSprocRoute;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static conflictsWithIds(databaseId: string, collectionId: string) {
|
|
||||||
const transformedDatabasePrefix: string = this.conflicts.replace("{db_id}", databaseId);
|
|
||||||
|
|
||||||
return transformedDatabasePrefix.replace("{coll_id}", collectionId).replace("/", ""); // strip the first slash since hasher adds it;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static docsWithIds(databaseId: string, collectionId: string, docId: string) {
|
|
||||||
const transformedDatabasePrefix: string = this.docs.replace("{db_id}", databaseId);
|
|
||||||
|
|
||||||
return transformedDatabasePrefix.replace("{coll_id}", collectionId).replace("{doc_id}", docId).replace("/", ""); // strip the first slash since hasher adds it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ConfigurationOverridesValues {
|
|
||||||
public static IsBsonSchemaV2: string = "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class KeyCodes {
|
|
||||||
public static Space: number = 32;
|
|
||||||
public static Enter: number = 13;
|
|
||||||
public static Escape: number = 27;
|
|
||||||
public static UpArrow: number = 38;
|
|
||||||
public static DownArrow: number = 40;
|
|
||||||
public static LeftArrow: number = 37;
|
|
||||||
public static RightArrow: number = 39;
|
|
||||||
public static Tab: number = 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalized per: https://www.w3.org/TR/uievents-key/#named-key-attribute-values
|
|
||||||
export class NormalizedEventKey {
|
|
||||||
public static readonly Space = " ";
|
|
||||||
public static readonly Enter = "Enter";
|
|
||||||
public static readonly Escape = "Escape";
|
|
||||||
public static readonly UpArrow = "ArrowUp";
|
|
||||||
public static readonly DownArrow = "ArrowDown";
|
|
||||||
public static readonly LeftArrow = "ArrowLeft";
|
|
||||||
public static readonly RightArrow = "ArrowRight";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TryCosmosExperience {
|
|
||||||
public static extendUrl: string = "https://trycosmosdb.azure.com/api/resource/extendportal?userId={0}";
|
|
||||||
public static deleteUrl: string = "https://trycosmosdb.azure.com/api/resource/deleteportal?userId={0}";
|
|
||||||
public static collectionsPerAccount: number = 3;
|
|
||||||
public static maxRU: number = 5000;
|
|
||||||
public static defaultRU: number = 3000;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class OfferVersions {
|
|
||||||
public static V1: string = "V1";
|
|
||||||
public static V2: string = "V2";
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ConflictOperationType {
|
|
||||||
Replace = "replace",
|
|
||||||
Create = "create",
|
|
||||||
Delete = "delete",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ConnectionStatusType {
|
|
||||||
Connect = "Connect",
|
|
||||||
Connecting = "Connecting",
|
|
||||||
Connected = "Connected",
|
|
||||||
Failed = "Connection Failed",
|
|
||||||
ReConnect = "Reconnect",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EmulatorMasterKey =
|
|
||||||
//[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Well known public masterKey for emulator")]
|
|
||||||
"C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
|
|
||||||
|
|
||||||
// A variable @MyVariable defined in Constants.less is accessible as StyleConstants.MyVariable
|
|
||||||
export const StyleConstants = require("less-vars-loader!../../less/Common/Constants.less");
|
|
||||||
|
|
||||||
export class Notebook {
|
|
||||||
public static readonly defaultBasePath = "./notebooks";
|
|
||||||
public static readonly heartbeatDelayMs = 60000;
|
|
||||||
public static readonly kernelRestartInitialDelayMs = 1000;
|
|
||||||
public static readonly kernelRestartMaxDelayMs = 20000;
|
|
||||||
public static readonly autoSaveIntervalMs = 120000;
|
|
||||||
public static readonly memoryGuageToGB = 1048576;
|
|
||||||
public static readonly temporarilyDownMsg = "Notebooks is currently not available. We are working on it.";
|
|
||||||
public static readonly mongoShellTemporarilyDownMsg =
|
|
||||||
"We have identified an issue with the Mongo Shell and it is unavailable right now. We are actively working on the mitigation.";
|
|
||||||
public static readonly cassandraShellTemporarilyDownMsg =
|
|
||||||
"We have identified an issue with the Cassandra Shell and it is unavailable right now. We are actively working on the mitigation.";
|
|
||||||
public static saveNotebookModalTitle = "Save Notebook in temporary workspace";
|
|
||||||
public static saveNotebookModalContent =
|
|
||||||
"This notebook will be saved in the temporary workspace and will be removed when the session expires. To save your work permanently, save your notebooks to a GitHub repository or download the notebooks to your local machine before the session ends.";
|
|
||||||
public static newNotebookModalTitle = "Create Notebook in temporary workspace";
|
|
||||||
public static newNotebookUploadModalTitle = "Upload Notebook in temporary workspace";
|
|
||||||
public static newNotebookModalContent1 =
|
|
||||||
"A temporary workspace will be created to enable you to work with notebooks. When the session expires, any notebooks in the workspace will be removed.";
|
|
||||||
public static newNotebookModalContent2 =
|
|
||||||
"To save your work permanently, save your notebooks to a GitHub repository or download the notebooks to your local machine before the session ends. ";
|
|
||||||
public static galleryNotebookDownloadContent1 =
|
|
||||||
"To download, run, and make changes to this sample notebook, a temporary workspace will be created. When the session expires, any notebooks in the workspace will be removed.";
|
|
||||||
public static galleryNotebookDownloadContent2 =
|
|
||||||
"To save your work permanently, save your notebooks to a GitHub repository or download the Notebooks to your local machine before the session ends. ";
|
|
||||||
public static cosmosNotebookHomePageUrl = "https://aka.ms/cosmos-notebooks-limits";
|
|
||||||
public static cosmosNotebookGitDocumentationUrl = "https://aka.ms/cosmos-notebooks-github";
|
|
||||||
public static learnMore = "Learn more.";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SparkLibrary {
|
|
||||||
public static readonly nameMinLength = 3;
|
|
||||||
public static readonly nameMaxLength = 63;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AnalyticalStorageTtl {
|
|
||||||
public static readonly Days90: number = 7776000;
|
|
||||||
public static readonly Infinite: number = -1;
|
|
||||||
public static readonly Disabled: number = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TerminalQueryParams {
|
|
||||||
public static readonly Terminal = "terminal";
|
|
||||||
public static readonly Server = "server";
|
|
||||||
public static readonly Token = "token";
|
|
||||||
public static readonly SubscriptionId = "subscriptionId";
|
|
||||||
public static readonly TerminalEndpoint = "terminalEndpoint";
|
|
||||||
}
|
|
||||||
3
src/Common/Constants/AfecFeatures.ts
Normal file
3
src/Common/Constants/AfecFeatures.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const Spark = "spark-public-preview";
|
||||||
|
export const Notebooks = "sparknotebooks-public-preview";
|
||||||
|
export const StorageAnalytics = "storageanalytics-public-preview";
|
||||||
3
src/Common/Constants/AnalyticalStorageTtl.ts
Normal file
3
src/Common/Constants/AnalyticalStorageTtl.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const Days90 = 7776000;
|
||||||
|
export const Infinite = -1;
|
||||||
|
export const Disabled = 0;
|
||||||
2
src/Common/Constants/ApiEndpoints.ts
Normal file
2
src/Common/Constants/ApiEndpoints.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export const runtimeProxy = "/api/RuntimeProxy";
|
||||||
|
export const guestRuntimeProxy = "/api/guest/RuntimeProxy";
|
||||||
6
src/Common/Constants/ApiType.ts
Normal file
6
src/Common/Constants/ApiType.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Mapped to hexadecimal values in the backend
|
||||||
|
export const MongoDB = 1;
|
||||||
|
export const Gremlin = 2;
|
||||||
|
export const Cassandra = 4;
|
||||||
|
export const Table = 8;
|
||||||
|
export const SQL = 16;
|
||||||
5
src/Common/Constants/Areas.ts
Normal file
5
src/Common/Constants/Areas.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const ResourceTree = "Resource Tree";
|
||||||
|
export const ContextualPane = "Contextual Pane";
|
||||||
|
export const Tab = "Tab";
|
||||||
|
export const ShareDialog = "Share Access Dialog";
|
||||||
|
export const Notebook = "Notebook";
|
||||||
6
src/Common/Constants/ArmApiVersions.ts
Normal file
6
src/Common/Constants/ArmApiVersions.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const documentDB = "2015-11-06";
|
||||||
|
export const arcadia = "2019-06-01-preview";
|
||||||
|
export const arcadiaLivy = "2019-11-01-preview";
|
||||||
|
export const arm = "2015-11-01";
|
||||||
|
export const armFeatures = "2014-08-01-preview";
|
||||||
|
export const publicVersion = "2020-04-01";
|
||||||
2
src/Common/Constants/ArmResourceTypes.ts
Normal file
2
src/Common/Constants/ArmResourceTypes.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export const notebookWorkspaces = "Microsoft.DocumentDB/databaseAccounts/notebookWorkspaces";
|
||||||
|
export const synapseWorkspaces = "Microsoft.Synapse/workspaces";
|
||||||
5
src/Common/Constants/BackendDefaults.ts
Normal file
5
src/Common/Constants/BackendDefaults.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const partitionKeyKind = "Hash";
|
||||||
|
export const singlePartitionStorageInGb = "10";
|
||||||
|
export const multiPartitionStorageInGb = "100";
|
||||||
|
export const maxChangeFeedRetentionDuration = 10;
|
||||||
|
export const partitionKeyVersion = 2;
|
||||||
8
src/Common/Constants/CapabilityNames.ts
Normal file
8
src/Common/Constants/CapabilityNames.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const EnableTable = "EnableTable";
|
||||||
|
export const EnableGremlin = "EnableGremlin";
|
||||||
|
export const EnableCassandra = "EnableCassandra";
|
||||||
|
export const EnableAutoScale = "EnableAutoScale";
|
||||||
|
export const EnableNotebooks = "EnableNotebooks";
|
||||||
|
export const EnableStorageAnalytics = "EnableStorageAnalytics";
|
||||||
|
export const EnableMongo = "EnableMongo";
|
||||||
|
export const EnableServerless = "EnableServerless";
|
||||||
9
src/Common/Constants/CassandraBackend.ts
Normal file
9
src/Common/Constants/CassandraBackend.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// TODO: 435619 Add default endpoints per cloud and use regional only when available
|
||||||
|
export const createOrDeleteApi = "api/cassandra/createordelete";
|
||||||
|
export const guestCreateOrDeleteApi = "api/guest/cassandra/createordelete";
|
||||||
|
export const queryApi = "api/cassandra";
|
||||||
|
export const guestQueryApi = "api/guest/cassandra";
|
||||||
|
export const keysApi = "api/cassandra/keys";
|
||||||
|
export const guestKeysApi = "api/guest/cassandra/keys";
|
||||||
|
export const schemaApi = "api/cassandra/schema";
|
||||||
|
export const guestSchemaApi = "api/guest/cassandra/schema";
|
||||||
9
src/Common/Constants/ClientDefaults.ts
Normal file
9
src/Common/Constants/ClientDefaults.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export const requestTimeoutMs = 60000;
|
||||||
|
export const portalCacheTimeoutMs = 10000;
|
||||||
|
export const errorNotificationTimeoutMs = 5000;
|
||||||
|
export const copyHelperTimeoutMs = 2000;
|
||||||
|
export const waitForDOMElementMs = 500;
|
||||||
|
export const cacheBustingTimeoutMs = 10 /** minutes **/ * 60 /** to seconds **/ * 1000; /** to milliseconds **/
|
||||||
|
export const databaseThroughputIncreaseFactor = 100;
|
||||||
|
export const arcadiaTokenRefreshInterval = 20 /** minutes **/ * 60 /** to seconds **/ * 1000; /** to milliseconds **/
|
||||||
|
export const arcadiaTokenRefreshIntervalPaddingMs = 2000;
|
||||||
3
src/Common/Constants/CodeOfConductEndpoints.ts
Normal file
3
src/Common/Constants/CodeOfConductEndpoints.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const privacyStatement = "https://aka.ms/ms-privacy-policy";
|
||||||
|
export const codeOfConduct = "https://aka.ms/cosmos-code-of-conduct";
|
||||||
|
export const termsOfUse = "https://aka.ms/ms-terms-of-use";
|
||||||
1
src/Common/Constants/ConfigurationOverridesValues.ts
Normal file
1
src/Common/Constants/ConfigurationOverridesValues.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const IsBsonSchemaV2 = "true";
|
||||||
1
src/Common/Constants/CorrelationBackend.ts
Normal file
1
src/Common/Constants/CorrelationBackend.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const Url = "https://aka.ms/cosmosdbanalytics";
|
||||||
8
src/Common/Constants/DocumentsGridMetrics.ts
Normal file
8
src/Common/Constants/DocumentsGridMetrics.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const DocumentsPerPage = 100;
|
||||||
|
export const IndividualRowHeight = 34;
|
||||||
|
export const BufferHeight = 28;
|
||||||
|
export const SplitterMinWidth = 200;
|
||||||
|
export const SplitterMaxWidth = 360;
|
||||||
|
|
||||||
|
export const DocumentEditorMinWidthRatio = 0.2;
|
||||||
|
export const DocumentEditorMaxWidthRatio = 0.4;
|
||||||
8
src/Common/Constants/EndpointsRegex.ts
Normal file
8
src/Common/Constants/EndpointsRegex.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const cassandra = [
|
||||||
|
"AccountEndpoint=(.*).cassandra.cosmosdb.azure.com",
|
||||||
|
"HostName=(.*).cassandra.cosmos.azure.com",
|
||||||
|
];
|
||||||
|
export const mongo = "mongodb://.*:(.*)@(.*).documents.azure.com";
|
||||||
|
export const mongoCompute = "mongodb://.*:(.*)@(.*).mongo.cosmos.azure.com";
|
||||||
|
export const sql = "AccountEndpoint=https://(.*).documents.azure.com";
|
||||||
|
export const table = "TableEndpoint=https://(.*).table.cosmosdb.azure.com";
|
||||||
8
src/Common/Constants/Flights.ts
Normal file
8
src/Common/Constants/Flights.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// flight names returned from the portal are always lowercase
|
||||||
|
export const SettingsV2 = "settingsv2";
|
||||||
|
export const MongoIndexEditor = "mongoindexeditor";
|
||||||
|
export const MongoIndexing = "mongoindexing";
|
||||||
|
export const AutoscaleTest = "autoscaletest";
|
||||||
|
export const PartitionKeyTest = "partitionkeytest";
|
||||||
|
export const PKPartitionKeyTest = "pkpartitionkeytest";
|
||||||
|
export const Phoenix = "phoenix";
|
||||||
40
src/Common/Constants/HashRoutePrefixes.ts
Normal file
40
src/Common/Constants/HashRoutePrefixes.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
export const databases = "/dbs/{db_id}";
|
||||||
|
export const collections = "/dbs/{db_id}/colls/{coll_id}";
|
||||||
|
export const sprocHash = "/sprocs/";
|
||||||
|
export const sprocs = collections + sprocHash + "{sproc_id}";
|
||||||
|
export const docs = collections + "/docs/{doc_id}/";
|
||||||
|
export const conflicts = collections + "/conflicts";
|
||||||
|
|
||||||
|
export const databasesWithId = (databaseId: string) => {
|
||||||
|
return databases.replace("{db_id}", databaseId).replace("/", ""); // strip the first slash since hasher adds it
|
||||||
|
};
|
||||||
|
|
||||||
|
export const collectionsWithIds = (databaseId: string, collectionId: string) => {
|
||||||
|
const transformedDatabasePrefix = collections.replace("{db_id}", databaseId);
|
||||||
|
|
||||||
|
return transformedDatabasePrefix.replace("{coll_id}", collectionId).replace("/", ""); // strip the first slash since hasher adds it
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sprocWithIds = (databaseId: string, collectionId: string, sprocId: string, stripFirstSlash = true) => {
|
||||||
|
const transformedDatabasePrefix = sprocs.replace("{db_id}", databaseId);
|
||||||
|
|
||||||
|
const transformedSprocRoute = transformedDatabasePrefix
|
||||||
|
.replace("{coll_id}", collectionId)
|
||||||
|
.replace("{sproc_id}", sprocId);
|
||||||
|
if (stripFirstSlash) {
|
||||||
|
return transformedSprocRoute.replace("/", ""); // strip the first slash since hasher adds it
|
||||||
|
}
|
||||||
|
|
||||||
|
return transformedSprocRoute;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const conflictsWithIds = (databaseId: string, collectionId: string) => {
|
||||||
|
const transformedDatabasePrefix = conflicts.replace("{db_id}", databaseId);
|
||||||
|
|
||||||
|
return transformedDatabasePrefix.replace("{coll_id}", collectionId).replace("/", ""); // strip the first slash since hasher adds it;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const docsWithIds = (databaseId: string, collectionId: string, docId: string): string => {
|
||||||
|
const transformedDatabasePrefix = docs.replace("{db_id}", databaseId);
|
||||||
|
return transformedDatabasePrefix.replace("{coll_id}", collectionId).replace("{doc_id}", docId).replace("/", ""); // strip the first slash since hasher adds it
|
||||||
|
};
|
||||||
30
src/Common/Constants/HttpHeaders.ts
Normal file
30
src/Common/Constants/HttpHeaders.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export const activityId = "x-ms-activity-id";
|
||||||
|
export const apiType = "x-ms-cosmos-apitype";
|
||||||
|
export const authorization = "authorization";
|
||||||
|
export const collectionIndexTransformationProgress = "x-ms-documentdb-collection-index-transformation-progress";
|
||||||
|
export const continuation = "x-ms-continuation";
|
||||||
|
export const correlationRequestId = "x-ms-correlation-request-id";
|
||||||
|
export const enableScriptLogging = "x-ms-documentdb-script-enable-logging";
|
||||||
|
export const guestAccessToken = "x-ms-encrypted-auth-token";
|
||||||
|
export const getReadOnlyKey = "x-ms-get-read-only-key";
|
||||||
|
export const connectionString = "x-ms-connection-string";
|
||||||
|
export const msDate = "x-ms-date";
|
||||||
|
export const location = "Location";
|
||||||
|
export const contentType = "Content-Type";
|
||||||
|
export const offerReplacePending = "x-ms-offer-replace-pending";
|
||||||
|
export const user = "x-ms-user";
|
||||||
|
export const populatePartitionStatistics = "x-ms-documentdb-populatepartitionstatistics";
|
||||||
|
export const queryMetrics = "x-ms-documentdb-query-metrics";
|
||||||
|
export const requestCharge = "x-ms-request-charge";
|
||||||
|
export const resourceQuota = "x-ms-resource-quota";
|
||||||
|
export const resourceUsage = "x-ms-resource-usage";
|
||||||
|
export const retryAfterMs = "x-ms-retry-after-ms";
|
||||||
|
export const scriptLogResults = "x-ms-documentdb-script-log-results";
|
||||||
|
export const populateCollectionThroughputInfo = "x-ms-documentdb-populatecollectionthroughputinfo";
|
||||||
|
export const supportSpatialLegacyCoordinates = "x-ms-documentdb-supportspatiallegacycoordinates";
|
||||||
|
export const usePolygonsSmallerThanAHemisphere = "x-ms-documentdb-usepolygonssmallerthanahemisphere";
|
||||||
|
export const autoPilotThroughput = "autoscaleSettings";
|
||||||
|
export const autoPilotThroughputSDK = "x-ms-cosmos-offer-autopilot-settings";
|
||||||
|
export const partitionKey = "x-ms-documentdb-partitionkey";
|
||||||
|
export const migrateOfferToManualThroughput = "x-ms-cosmos-migrate-offer-to-manual-throughput";
|
||||||
|
export const migrateOfferToAutopilot = "x-ms-cosmos-migrate-offer-to-autopilot";
|
||||||
23
src/Common/Constants/HttpStatusCodes.ts
Normal file
23
src/Common/Constants/HttpStatusCodes.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export const OK = 200;
|
||||||
|
export const Created = 201;
|
||||||
|
export const Accepted = 202;
|
||||||
|
export const NoContent = 204;
|
||||||
|
export const NotModified = 304;
|
||||||
|
export const Unauthorized = 401;
|
||||||
|
export const Forbidden = 403;
|
||||||
|
export const NotFound = 404;
|
||||||
|
export const TooManyRequests = 429;
|
||||||
|
export const Conflict = 409;
|
||||||
|
|
||||||
|
export const InternalServerError = 500;
|
||||||
|
export const BadGateway = 502;
|
||||||
|
export const ServiceUnavailable = 503;
|
||||||
|
export const GatewayTimeout = 504;
|
||||||
|
|
||||||
|
export const RetryableStatusCodes: number[] = [
|
||||||
|
TooManyRequests,
|
||||||
|
InternalServerError, // TODO: Handle all 500s on Portal backend and remove from retries list
|
||||||
|
BadGateway,
|
||||||
|
ServiceUnavailable,
|
||||||
|
GatewayTimeout,
|
||||||
|
];
|
||||||
8
src/Common/Constants/KeyCodes.ts
Normal file
8
src/Common/Constants/KeyCodes.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const Space = 32;
|
||||||
|
export const Enter = 13;
|
||||||
|
export const Escape = 27;
|
||||||
|
export const UpArrow = 38;
|
||||||
|
export const DownArrow = 40;
|
||||||
|
export const LeftArrow = 37;
|
||||||
|
export const RightArrow = 39;
|
||||||
|
export const Tab = 9;
|
||||||
2
src/Common/Constants/MongoDBAccounts.ts
Normal file
2
src/Common/Constants/MongoDBAccounts.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export const protocol = "https";
|
||||||
|
export const defaultPort = "10255";
|
||||||
8
src/Common/Constants/NormalizedEventKey.ts
Normal file
8
src/Common/Constants/NormalizedEventKey.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Normalized per: https://www.w3.org/TR/uievents-key/#named-key-attribute-values
|
||||||
|
export const Space = " ";
|
||||||
|
export const Enter = "Enter";
|
||||||
|
export const Escape = "Escape";
|
||||||
|
export const UpArrow = "ArrowUp";
|
||||||
|
export const DownArrow = "ArrowDown";
|
||||||
|
export const LeftArrow = "ArrowLeft";
|
||||||
|
export const RightArrow = "ArrowRight";
|
||||||
27
src/Common/Constants/Notebook.ts
Normal file
27
src/Common/Constants/Notebook.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export const defaultBasePath = "./notebooks";
|
||||||
|
export const heartbeatDelayMs = 60000;
|
||||||
|
export const kernelRestartInitialDelayMs = 1000;
|
||||||
|
export const kernelRestartMaxDelayMs = 20000;
|
||||||
|
export const autoSaveIntervalMs = 120000;
|
||||||
|
export const memoryGuageToGB = 1048576;
|
||||||
|
export const temporarilyDownMsg = "Notebooks is currently not available. We are working on it.";
|
||||||
|
export const mongoShellTemporarilyDownMsg =
|
||||||
|
"We have identified an issue with the Mongo Shell and it is unavailable right now. We are actively working on the mitigation.";
|
||||||
|
export const cassandraShellTemporarilyDownMsg =
|
||||||
|
"We have identified an issue with the Cassandra Shell and it is unavailable right now. We are actively working on the mitigation.";
|
||||||
|
export const saveNotebookModalTitle = "Save Notebook in temporary workspace";
|
||||||
|
export const saveNotebookModalContent =
|
||||||
|
"This notebook will be saved in the temporary workspace and will be removed when the session expires. To save your work permanently, save your notebooks to a GitHub repository or download the notebooks to your local machine before the session ends.";
|
||||||
|
export const newNotebookModalTitle = "Create Notebook in temporary workspace";
|
||||||
|
export const newNotebookUploadModalTitle = "Upload Notebook in temporary workspace";
|
||||||
|
export const newNotebookModalContent1 =
|
||||||
|
"A temporary workspace will be created to enable you to work with notebooks. When the session expires, any notebooks in the workspace will be removed.";
|
||||||
|
export const newNotebookModalContent2 =
|
||||||
|
"To save your work permanently, save your notebooks to a GitHub repository or download the notebooks to your local machine before the session ends. ";
|
||||||
|
export const galleryNotebookDownloadContent1 =
|
||||||
|
"To download, run, and make changes to this sample notebook, a temporary workspace will be created. When the session expires, any notebooks in the workspace will be removed.";
|
||||||
|
export const galleryNotebookDownloadContent2 =
|
||||||
|
"To save your work permanently, save your notebooks to a GitHub repository or download the Notebooks to your local machine before the session ends. ";
|
||||||
|
export const cosmosNotebookHomePageUrl = "https://aka.ms/cosmos-notebooks-limits";
|
||||||
|
export const cosmosNotebookGitDocumentationUrl = "https://aka.ms/cosmos-notebooks-github";
|
||||||
|
export const learnMore = "Learn more.";
|
||||||
2
src/Common/Constants/OfferVersions.ts
Normal file
2
src/Common/Constants/OfferVersions.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export const V1 = "V1";
|
||||||
|
export const V2 = "V2";
|
||||||
8
src/Common/Constants/Queries.ts
Normal file
8
src/Common/Constants/Queries.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export const CustomPageOption = "custom";
|
||||||
|
export const UnlimitedPageOption = "unlimited";
|
||||||
|
export const itemsPerPage = 100;
|
||||||
|
export const unlimitedItemsPerPage = 100; // TODO: Figure out appropriate value so it works for accounts with a large number of partitions
|
||||||
|
|
||||||
|
export const QueryEditorMinHeightRatio = 0.1;
|
||||||
|
export const QueryEditorMaxHeightRatio = 0.4;
|
||||||
|
export const DefaultMaxDegreeOfParallelism = 6;
|
||||||
4
src/Common/Constants/SavedQueries.ts
Normal file
4
src/Common/Constants/SavedQueries.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export const CollectionName = "___Query";
|
||||||
|
export const DatabaseName = "___Cosmos";
|
||||||
|
export const OfferThroughput = 400;
|
||||||
|
export const PartitionKeyProperty = "id";
|
||||||
6
src/Common/Constants/ServerIds.ts
Normal file
6
src/Common/Constants/ServerIds.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const localhost = "localhost";
|
||||||
|
export const blackforest = "blackforest";
|
||||||
|
export const fairfax = "fairfax";
|
||||||
|
export const mooncake = "mooncake";
|
||||||
|
export const productionPortal = "prod";
|
||||||
|
export const dev = "dev";
|
||||||
2
src/Common/Constants/SparkLibrary.ts
Normal file
2
src/Common/Constants/SparkLibrary.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export const nameMinLength = 3;
|
||||||
|
export const nameMaxLength = 63;
|
||||||
1
src/Common/Constants/TagNames.ts
Normal file
1
src/Common/Constants/TagNames.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const defaultExperience = "defaultExperience";
|
||||||
5
src/Common/Constants/TerminalQueryParams.ts
Normal file
5
src/Common/Constants/TerminalQueryParams.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const Terminal = "terminal";
|
||||||
|
export const Server = "server";
|
||||||
|
export const Token = "token";
|
||||||
|
export const SubscriptionId = "subscriptionId";
|
||||||
|
export const TerminalEndpoint = "terminalEndpoint";
|
||||||
5
src/Common/Constants/TryCosmosExperience.ts
Normal file
5
src/Common/Constants/TryCosmosExperience.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const extendUrl = "https://trycosmosdb.azure.com/api/resource/extendportal?userId={0}";
|
||||||
|
export const deleteUrl = "https://trycosmosdb.azure.com/api/resource/deleteportal?userId={0}";
|
||||||
|
export const collectionsPerAccount = 3;
|
||||||
|
export const maxRU = 5000;
|
||||||
|
export const defaultRU = 3000;
|
||||||
4
src/Common/Constants/Urls.ts
Normal file
4
src/Common/Constants/Urls.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export const feedbackEmail = "https://aka.ms/cosmosdbfeedback?subject=Cosmos%20DB%20Data%20Explorer%20Feedback";
|
||||||
|
export const autoscaleMigration = "https://aka.ms/cosmos-autoscale-migration";
|
||||||
|
export const freeTierInformation = "https://aka.ms/cosmos-free-tier";
|
||||||
|
export const cosmosPricing = "https://aka.ms/azure-cosmos-db-pricing";
|
||||||
105
src/Common/Constants/index.ts
Normal file
105
src/Common/Constants/index.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import * as AfecFeatures from "./AfecFeatures";
|
||||||
|
import * as AnalyticalStorageTtl from "./AnalyticalStorageTtl";
|
||||||
|
import * as ApiEndpoints from "./ApiEndpoints";
|
||||||
|
import * as ApiType from "./ApiType";
|
||||||
|
import * as Areas from "./Areas";
|
||||||
|
import * as ArmApiVersions from "./ArmApiVersions";
|
||||||
|
import * as ArmResourceTypes from "./ArmResourceTypes";
|
||||||
|
import * as BackendDefaults from "./BackendDefaults";
|
||||||
|
import * as CapabilityNames from "./CapabilityNames";
|
||||||
|
import * as CassandraBackend from "./CassandraBackend";
|
||||||
|
import * as ClientDefaults from "./ClientDefaults";
|
||||||
|
import * as CodeOfConductEndpoints from "./CodeOfConductEndpoints";
|
||||||
|
import * as ConfigurationOverridesValues from "./ConfigurationOverridesValues";
|
||||||
|
import * as CorrelationBackend from "./CorrelationBackend";
|
||||||
|
import * as DocumentsGridMetrics from "./DocumentsGridMetrics";
|
||||||
|
import * as EndpointsRegex from "./EndpointsRegex";
|
||||||
|
import * as Flights from "./Flights";
|
||||||
|
import * as HashRoutePrefixes from "./HashRoutePrefixes";
|
||||||
|
import * as HttpHeaders from "./HttpHeaders";
|
||||||
|
import * as HttpStatusCodes from "./HttpStatusCodes";
|
||||||
|
import * as KeyCodes from "./KeyCodes";
|
||||||
|
import * as MongoDBAccounts from "./MongoDBAccounts";
|
||||||
|
import * as NormalizedEventKey from "./NormalizedEventKey";
|
||||||
|
import * as Notebook from "./Notebook";
|
||||||
|
import * as OfferVersions from "./OfferVersions";
|
||||||
|
import * as Queries from "./Queries";
|
||||||
|
import * as SavedQueries from "./SavedQueries";
|
||||||
|
import * as ServerIds from "./ServerIds";
|
||||||
|
import * as SparkLibrary from "./SparkLibrary";
|
||||||
|
import * as TagNames from "./TagNames";
|
||||||
|
import * as TerminalQueryParams from "./TerminalQueryParams";
|
||||||
|
import * as TryCosmosExperience from "./TryCosmosExperience";
|
||||||
|
import * as Urls from "./Urls";
|
||||||
|
|
||||||
|
const StyleConstants = require("less-vars-loader!../../../less/Common/Constants.less");
|
||||||
|
|
||||||
|
export {
|
||||||
|
StyleConstants,
|
||||||
|
SparkLibrary,
|
||||||
|
ConfigurationOverridesValues,
|
||||||
|
OfferVersions,
|
||||||
|
AnalyticalStorageTtl,
|
||||||
|
Notebook,
|
||||||
|
TryCosmosExperience,
|
||||||
|
NormalizedEventKey,
|
||||||
|
KeyCodes,
|
||||||
|
HashRoutePrefixes,
|
||||||
|
Urls,
|
||||||
|
HttpStatusCodes,
|
||||||
|
ApiType,
|
||||||
|
HttpHeaders,
|
||||||
|
Areas,
|
||||||
|
DocumentsGridMetrics,
|
||||||
|
SavedQueries,
|
||||||
|
Queries,
|
||||||
|
CassandraBackend,
|
||||||
|
MongoDBAccounts,
|
||||||
|
TagNames,
|
||||||
|
AfecFeatures,
|
||||||
|
Flights,
|
||||||
|
CorrelationBackend,
|
||||||
|
CapabilityNames,
|
||||||
|
ClientDefaults,
|
||||||
|
BackendDefaults,
|
||||||
|
ArmResourceTypes,
|
||||||
|
ArmApiVersions,
|
||||||
|
TerminalQueryParams,
|
||||||
|
CodeOfConductEndpoints,
|
||||||
|
ApiEndpoints,
|
||||||
|
EndpointsRegex,
|
||||||
|
ServerIds,
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum ConnectionStatusType {
|
||||||
|
Connect = "Connect",
|
||||||
|
Connecting = "Connecting",
|
||||||
|
Connected = "Connected",
|
||||||
|
Failed = "Connection Failed",
|
||||||
|
ReConnect = "Reconnect",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ConflictOperationType {
|
||||||
|
Replace = "replace",
|
||||||
|
Create = "create",
|
||||||
|
Delete = "delete",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EmulatorMasterKey =
|
||||||
|
//[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Well known public masterKey for emulator")]
|
||||||
|
"C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
|
||||||
|
|
||||||
|
// A variable @MyVariable defined in Constants.less is accessible as StyleConstants.MyVariable
|
||||||
|
|
||||||
|
export enum AccountKind {
|
||||||
|
DocumentDB = "DocumentDB",
|
||||||
|
MongoDB = "MongoDB",
|
||||||
|
Parse = "Parse",
|
||||||
|
GlobalDocumentDB = "GlobalDocumentDB",
|
||||||
|
Default = "DocumentDB",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum MongoBackendEndpointType {
|
||||||
|
local,
|
||||||
|
remote,
|
||||||
|
}
|
||||||
@@ -80,8 +80,7 @@ export function queryDocuments(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const endpoint = getFeatureEndpointOrDefault("resourcelist") || "";
|
const endpoint = getFeatureEndpointOrDefault("resourcelist") || "";
|
||||||
|
const headers: HeadersInit = {
|
||||||
const headers = {
|
|
||||||
...defaultHeaders,
|
...defaultHeaders,
|
||||||
...authHeaders(),
|
...authHeaders(),
|
||||||
[CosmosSDKConstants.HttpHeaders.IsQuery]: "true",
|
[CosmosSDKConstants.HttpHeaders.IsQuery]: "true",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ describe("Cache arrays by key", () => {
|
|||||||
const key = "key";
|
const key = "key";
|
||||||
cache.insert(key, 1, 0);
|
cache.insert(key, 1, 0);
|
||||||
cache.clear();
|
cache.clear();
|
||||||
expect(cache.retrieve(key, 0, 1)).toBe(undefined);
|
expect(cache.retrieve(key, 0, 1)).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should invalidate oldest key to keep cache size under maximum", () => {
|
it("should invalidate oldest key to keep cache size under maximum", () => {
|
||||||
@@ -21,7 +21,7 @@ describe("Cache arrays by key", () => {
|
|||||||
cache.insert(key1, 2, 4);
|
cache.insert(key1, 2, 4);
|
||||||
|
|
||||||
expect(cache.retrieve(key1, 0, 3)).toEqual([0, 2, 4]);
|
expect(cache.retrieve(key1, 0, 3)).toEqual([0, 2, 4]);
|
||||||
expect(cache.retrieve(key2, 1, 1)).toEqual(undefined);
|
expect(cache.retrieve(key2, 1, 1)).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should cache and retrieve cached page within boundaries", () => {
|
it("should cache and retrieve cached page within boundaries", () => {
|
||||||
@@ -39,7 +39,7 @@ describe("Cache arrays by key", () => {
|
|||||||
const key = "key";
|
const key = "key";
|
||||||
cache.insert(key, 0, 0);
|
cache.insert(key, 0, 0);
|
||||||
cache.insert(key, 1, 1);
|
cache.insert(key, 1, 1);
|
||||||
expect(cache.retrieve(key, 2, 1)).toEqual(undefined);
|
expect(cache.retrieve(key, 2, 1)).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not retrieve cached page overlapping boundaries", () => {
|
it("should not retrieve cached page overlapping boundaries", () => {
|
||||||
@@ -48,7 +48,7 @@ describe("Cache arrays by key", () => {
|
|||||||
cache.insert(key, 0, 0);
|
cache.insert(key, 0, 0);
|
||||||
cache.insert(key, 1, 1);
|
cache.insert(key, 1, 1);
|
||||||
cache.insert(key, 2, 2);
|
cache.insert(key, 2, 2);
|
||||||
expect(cache.retrieve(key, 2, 4)).toEqual(undefined);
|
expect(cache.retrieve(key, 2, 4)).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not insert non-contiguous element", () => {
|
it("should not insert non-contiguous element", () => {
|
||||||
@@ -57,7 +57,7 @@ describe("Cache arrays by key", () => {
|
|||||||
cache.insert(key, 0, 0);
|
cache.insert(key, 0, 0);
|
||||||
cache.insert(key, 1, 1);
|
cache.insert(key, 1, 1);
|
||||||
cache.insert(key, 3, 3);
|
cache.insert(key, 3, 3);
|
||||||
expect(cache.retrieve(key, 3, 1)).toEqual(undefined);
|
expect(cache.retrieve(key, 3, 1)).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should cache multiple keys", () => {
|
it("should cache multiple keys", () => {
|
||||||
|
|||||||
@@ -61,12 +61,12 @@ export class ArraysByKeyCache<T> {
|
|||||||
* @param pageSize
|
* @param pageSize
|
||||||
*/
|
*/
|
||||||
public retrieve(key: string, startIndex: number, pageSize: number): T[] | null {
|
public retrieve(key: string, startIndex: number, pageSize: number): T[] | null {
|
||||||
if (!Object.prototype.hasOwnProperty.call(this.cache, key)) {
|
if (!this.cache.hasOwnProperty(key)) {
|
||||||
return undefined;
|
return null;
|
||||||
}
|
}
|
||||||
const elements = this.cache[key];
|
const elements = this.cache[key];
|
||||||
if (startIndex + pageSize > elements.length) {
|
if (startIndex + pageSize > elements.length) {
|
||||||
return undefined;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return elements.slice(startIndex, startIndex + pageSize);
|
return elements.slice(startIndex, startIndex + pageSize);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
/* 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";
|
||||||
@@ -294,8 +296,6 @@ 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) {
|
public shareIGraphConfig(igraphConfig: IGraphConfig): void {
|
||||||
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
|
||||||
let finalProperties = editedProperties.existingProperties.concat(editedProperties.addedProperties);
|
const finalProperties = editedProperties.existingProperties.concat(editedProperties.addedProperties);
|
||||||
|
|
||||||
// Compose the query
|
// Compose the query
|
||||||
let pkId = editedProperties.pkId;
|
const 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) {
|
public selectNode(id: string): void {
|
||||||
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() {
|
public deleteHighlightedNode(): void {
|
||||||
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) {
|
public static isEdgeVertexPairArray(data: any): boolean {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pairs: any[] = data;
|
const 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 (
|
||||||
!item.hasOwnProperty("e") ||
|
!Object.prototype.hasOwnProperty.call(item, "e") ||
|
||||||
!item.hasOwnProperty("v") ||
|
!Object.prototype.hasOwnProperty.call(item, "v") ||
|
||||||
!item["e"].hasOwnProperty("id") ||
|
!Object.prototype.hasOwnProperty.call(item["e"], "id") ||
|
||||||
!item["e"].hasOwnProperty("type") ||
|
!Object.prototype.hasOwnProperty.call(item["e"], "type") ||
|
||||||
item["e"].type !== "edge" ||
|
item["e"].type !== "edge" ||
|
||||||
!item["v"].hasOwnProperty("id") ||
|
!Object.prototype.hasOwnProperty.call(item["v"], "id") ||
|
||||||
!item["v"].hasOwnProperty("type") ||
|
!Object.prototype.hasOwnProperty.call(item["e"], "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,7 +588,6 @@ 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);
|
||||||
}
|
}
|
||||||
@@ -668,7 +667,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return promise.then((nbPairsFetched: number) => {
|
return promise.then(() => {
|
||||||
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:
|
||||||
@@ -754,7 +753,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<any> {
|
public createNewEdge(e: GraphNewEdgeData): Q.Promise<unknown> {
|
||||||
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)}'))`;
|
||||||
@@ -772,8 +771,8 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let edge = edges[0];
|
const edge = edges[0];
|
||||||
let graphData = this.originalGraphData;
|
const graphData = this.originalGraphData;
|
||||||
graphData.addEdge(edge);
|
graphData.addEdge(edge);
|
||||||
|
|
||||||
// Allow loadNeighbors to load list new edge
|
// Allow loadNeighbors to load list new edge
|
||||||
@@ -800,10 +799,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<any> {
|
public removeEdge(edgeId: string): Q.Promise<unknown> {
|
||||||
return this.submitToBackend(`g.E('${GraphUtil.escapeSingleQuotes(edgeId)}').drop()`).then(
|
return this.submitToBackend(`g.E('${GraphUtil.escapeSingleQuotes(edgeId)}').drop()`).then(
|
||||||
() => {
|
() => {
|
||||||
let graphData = this.originalGraphData;
|
const graphData = this.originalGraphData;
|
||||||
graphData.removeEdge(edgeId, false);
|
graphData.removeEdge(edgeId, false);
|
||||||
this.updateGraphData(graphData, this.state.igraphConfig);
|
this.updateGraphData(graphData, this.state.igraphConfig);
|
||||||
},
|
},
|
||||||
@@ -826,10 +825,14 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let vertices: any[] = data;
|
const vertices: any[] = data;
|
||||||
if (vertices.length > 0) {
|
if (vertices.length > 0) {
|
||||||
let v0 = vertices[0];
|
const v0 = vertices[0];
|
||||||
if (!v0.hasOwnProperty("id") || !v0.hasOwnProperty("type") || v0.type !== "vertex") {
|
if (
|
||||||
|
!Object.prototype.hasOwnProperty.call(v0, "id") ||
|
||||||
|
!Object.prototype.hasOwnProperty.call(v0, "type") ||
|
||||||
|
v0.type !== "vertex"
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -837,7 +840,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 any;
|
const data = result.data as GraphData.GremlinVertex[];
|
||||||
this.setFilterQueryStatus(FilterQueryStatus.GraphEmptyResult);
|
this.setFilterQueryStatus(FilterQueryStatus.GraphEmptyResult);
|
||||||
|
|
||||||
if (data === null) {
|
if (data === null) {
|
||||||
@@ -927,13 +930,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 };
|
||||||
}
|
}
|
||||||
|
|
||||||
let vertex = vertices[0];
|
const 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);
|
||||||
@@ -1022,7 +1025,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,
|
||||||
{
|
{
|
||||||
@@ -1082,7 +1085,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: string = "";
|
let errorDataStr = "";
|
||||||
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);
|
||||||
@@ -1161,12 +1164,15 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
)}"`
|
)}"`
|
||||||
).then(
|
).then(
|
||||||
(documents: DataModels.DocumentId[]) => {
|
(documents: DataModels.DocumentId[]) => {
|
||||||
$.each(documents, (index: number, doc: any) => {
|
$.each(
|
||||||
newIconsMap[doc["_graph_icon_property_value"]] = {
|
documents,
|
||||||
data: doc["icon"],
|
(index: number, doc: { _graph_icon_property_value: string; icon: string; format: string }) => {
|
||||||
format: doc["format"],
|
newIconsMap[doc["_graph_icon_property_value"]] = {
|
||||||
};
|
data: doc["icon"],
|
||||||
});
|
format: doc["format"],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Update graph configuration
|
// Update graph configuration
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -1223,8 +1229,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, index: number): LeftPane.CaptionId => {
|
(value: any): LeftPane.CaptionId => {
|
||||||
let result = GraphData.GraphData.getNodePropValue(value, key);
|
const 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,
|
||||||
@@ -1237,7 +1243,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<any> {
|
private selectRootNode(id: string): Q.Promise<unknown> {
|
||||||
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 {
|
||||||
@@ -1282,7 +1288,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: any) => {
|
(reason: string) => {
|
||||||
GraphExplorer.reportToConsole(ConsoleDataType.Error, `Failed to select root node. Reason:${reason}`);
|
GraphExplorer.reportToConsole(ConsoleDataType.Error, `Failed to select root node. Reason:${reason}`);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -1349,10 +1355,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 &&
|
||||||
v.hasOwnProperty("properties") &&
|
Object.prototype.hasOwnProperty.call(v, "properties") &&
|
||||||
v.properties.hasOwnProperty(this.props.collectionPartitionKeyProperty) &&
|
Object.prototype.hasOwnProperty.call(v.properties, this.props.collectionPartitionKeyProperty) &&
|
||||||
v.properties[this.props.collectionPartitionKeyProperty].length > 0 &&
|
v.properties[this.props.collectionPartitionKeyProperty].length > 0 &&
|
||||||
v.properties[this.props.collectionPartitionKeyProperty][0].hasOwnProperty("value")
|
Object.prototype.hasOwnProperty.call(v.properties[this.props.collectionPartitionKeyProperty][0], "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);
|
||||||
@@ -1370,8 +1376,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 &&
|
||||||
v.hasOwnProperty("properties") &&
|
Object.prototype.hasOwnProperty.call(v, "properties") &&
|
||||||
v.properties.hasOwnProperty(this.props.collectionPartitionKeyProperty)
|
Object.prototype.hasOwnProperty.call(v.properties, 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);
|
||||||
@@ -1388,14 +1394,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 {
|
||||||
let { id } = d;
|
const { 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 && d.hasOwnProperty(collectionPartitionKeyProperty)) {
|
if (collectionPartitionKeyProperty && Object.prototype.hasOwnProperty.call(d, 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) {
|
||||||
@@ -1425,7 +1431,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[]) => {
|
||||||
let possibleVertices = [] as PossibleVertex[];
|
const 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
|
||||||
@@ -1439,7 +1445,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
caption: item.p,
|
caption: item.p,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (item.hasOwnProperty("p")) {
|
if (Object.prototype.hasOwnProperty.call(item, "p")) {
|
||||||
possibleVertices.push({
|
possibleVertices.push({
|
||||||
value: item.id,
|
value: item.id,
|
||||||
caption: item.p[0]["_value"],
|
caption: item.p[0]["_value"],
|
||||||
@@ -1462,17 +1468,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<any> {
|
private editGraphEdges(editedEdges: EditedEdges): Q.Promise<unknown> {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
// Drop edges
|
// Drop edges
|
||||||
for (let i = 0; i < editedEdges.droppedIds.length; i++) {
|
for (let i = 0; i < editedEdges.droppedIds.length; i++) {
|
||||||
let id = editedEdges.droppedIds[i];
|
const 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++) {
|
||||||
let e = editedEdges.addedEdges[i];
|
const 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
|
||||||
@@ -1525,7 +1531,9 @@ 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.
|
||||||
@@ -1533,17 +1541,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 (var p in item) {
|
for (const 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 (item.hasOwnProperty("properties")) {
|
if (Object.prototype.hasOwnProperty.call(item, "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 (var f in item.properties) {
|
for (const f in item.properties) {
|
||||||
props[f] = true;
|
props[f] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1570,21 +1578,21 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = this.originalGraphData.getVertexById(id);
|
const 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
|
||||||
let props: { [id: string]: ViewModels.GremlinPropertyValueType[] } = {};
|
const props: { [id: string]: ViewModels.GremlinPropertyValueType[] } = {};
|
||||||
for (let p in data.properties) {
|
for (const 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
|
||||||
let sources: NeighborVertexBasicInfo[] = [];
|
const sources: NeighborVertexBasicInfo[] = [];
|
||||||
let targets: NeighborVertexBasicInfo[] = [];
|
const targets: NeighborVertexBasicInfo[] = [];
|
||||||
this.props.onResetDefaultGraphConfigValues();
|
this.props.onResetDefaultGraphConfigValues();
|
||||||
let nodeCaption = this.state.igraphConfigUiData.nodeCaptionChoice;
|
const nodeCaption = this.state.igraphConfigUiData.nodeCaptionChoice;
|
||||||
this.updateSelectedNodeNeighbors(data.id, nodeCaption, sources, targets);
|
this.updateSelectedNodeNeighbors(data.id, nodeCaption, sources, targets);
|
||||||
let sData: GraphHighlightedNodeData = {
|
const sData: GraphHighlightedNodeData = {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
label: data.label,
|
label: data.label,
|
||||||
properties: props,
|
properties: props,
|
||||||
@@ -1611,16 +1619,16 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
targets: NeighborVertexBasicInfo[]
|
targets: NeighborVertexBasicInfo[]
|
||||||
): void {
|
): void {
|
||||||
// update neighbors
|
// update neighbors
|
||||||
let gd = this.originalGraphData;
|
const gd = this.originalGraphData;
|
||||||
let v = gd.getVertexById(id);
|
const 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;
|
||||||
|
|
||||||
let possibleEdgeLabels = {} as any; // Collect all edge labels in a hashset
|
const possibleEdgeLabels = {} as any; // Collect all edge labels in a hashset
|
||||||
|
|
||||||
for (let p in v.inE) {
|
for (const 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) => {
|
||||||
@@ -1629,7 +1637,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;
|
||||||
}
|
}
|
||||||
let caption = GraphData.GraphData.getNodePropValue(gd.getVertexById(neighborId), nodeCaption) as string;
|
const caption = GraphData.GraphData.getNodePropValue(gd.getVertexById(neighborId), nodeCaption) as string;
|
||||||
sources.push({
|
sources.push({
|
||||||
name: caption,
|
name: caption,
|
||||||
id: neighborId,
|
id: neighborId,
|
||||||
@@ -1639,7 +1647,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let p in v.outE) {
|
for (const 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) => {
|
||||||
@@ -1648,7 +1656,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;
|
||||||
}
|
}
|
||||||
let caption = GraphData.GraphData.getNodePropValue(gd.getVertexById(neighborId), nodeCaption) as string;
|
const caption = GraphData.GraphData.getNodePropValue(gd.getVertexById(neighborId), nodeCaption) as string;
|
||||||
targets.push({
|
targets.push({
|
||||||
name: caption,
|
name: caption,
|
||||||
id: neighborId,
|
id: neighborId,
|
||||||
@@ -1660,7 +1668,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, index: number, array: string[]): InputTypeaheadComponent.Item => {
|
(value: string): InputTypeaheadComponent.Item => {
|
||||||
return { caption: value, value: value };
|
return { caption: value, value: value };
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -1681,20 +1689,20 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let updatedVertex = vertices[0];
|
const updatedVertex = vertices[0];
|
||||||
if (this.originalGraphData.hasVertexId(updatedVertex.id)) {
|
if (this.originalGraphData.hasVertexId(updatedVertex.id)) {
|
||||||
let currentVertex = this.originalGraphData.getVertexById(updatedVertex.id);
|
const currentVertex = this.originalGraphData.getVertexById(updatedVertex.id);
|
||||||
// Copy updated properties
|
// Copy updated properties
|
||||||
if (currentVertex.hasOwnProperty("properties")) {
|
if (Object.prototype.hasOwnProperty.call(currentVertex, "properties")) {
|
||||||
delete currentVertex["properties"];
|
delete currentVertex["properties"];
|
||||||
}
|
}
|
||||||
for (var p in updatedVertex) {
|
for (const 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.
|
||||||
let hn = this.state.highlightedNode;
|
const hn = this.state.highlightedNode;
|
||||||
if (hn && hn.id === updatedVertex.id) {
|
if (hn && hn.id === updatedVertex.id) {
|
||||||
this.updatePropertiesPane(hn.id);
|
this.updatePropertiesPane(hn.id);
|
||||||
}
|
}
|
||||||
@@ -1708,7 +1716,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
igraphConfig?: IGraphConfig
|
igraphConfig?: IGraphConfig
|
||||||
) {
|
) {
|
||||||
this.originalGraphData = graphData;
|
this.originalGraphData = graphData;
|
||||||
let gd = JSON.parse(JSON.stringify(this.originalGraphData));
|
const 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;
|
||||||
@@ -1873,7 +1881,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: any) => {
|
.catch((error: Error) => {
|
||||||
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({
|
||||||
|
|||||||
@@ -307,11 +307,18 @@ function createOpenSynapseLinkDialogButton(container: Explorer): CommandButtonCo
|
|||||||
|
|
||||||
function createNewDatabase(container: Explorer): CommandButtonComponentProps {
|
function createNewDatabase(container: Explorer): CommandButtonComponentProps {
|
||||||
const label = "New " + getDatabaseName();
|
const label = "New " + getDatabaseName();
|
||||||
|
const newDatabaseButton = document.activeElement as HTMLElement;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
iconSrc: AddDatabaseIcon,
|
iconSrc: AddDatabaseIcon,
|
||||||
iconAlt: label,
|
iconAlt: label,
|
||||||
onCommandClick: () =>
|
onCommandClick: () =>
|
||||||
useSidePanel.getState().openSidePanel("New " + getDatabaseName(), <AddDatabasePanel explorer={container} />),
|
useSidePanel
|
||||||
|
.getState()
|
||||||
|
.openSidePanel(
|
||||||
|
"New " + getDatabaseName(),
|
||||||
|
<AddDatabasePanel explorer={container} buttonElement={newDatabaseButton} />
|
||||||
|
),
|
||||||
commandButtonLabel: label,
|
commandButtonLabel: label,
|
||||||
ariaLabel: label,
|
ariaLabel: label,
|
||||||
hasPopup: true,
|
hasPopup: true,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* 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 {
|
||||||
@@ -30,6 +31,19 @@ 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;
|
||||||
@@ -41,7 +55,7 @@ export class NotebookComponentBootstrapper {
|
|||||||
this.contentRef = options.contentRef;
|
this.contentRef = options.contentRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static wrapModelIntoContent(name: string, path: string, content: any) {
|
protected static wrapModelIntoContent(name: string, path: string, content: unknown): IWrapModel {
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
path,
|
path,
|
||||||
@@ -49,7 +63,7 @@ export class NotebookComponentBootstrapper {
|
|||||||
created: "",
|
created: "",
|
||||||
content,
|
content,
|
||||||
format: "json",
|
format: "json",
|
||||||
mimetype: null as any,
|
mimetype: undefined,
|
||||||
size: 0,
|
size: 0,
|
||||||
writeable: false,
|
writeable: false,
|
||||||
type: "notebook",
|
type: "notebook",
|
||||||
@@ -85,7 +99,7 @@ export class NotebookComponentBootstrapper {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public setContent(name: string, content: any): void {
|
public setContent(name: string, content: unknown): void {
|
||||||
this.getStore().dispatch(
|
this.getStore().dispatch(
|
||||||
actions.fetchContentFulfilled({
|
actions.fetchContentFulfilled({
|
||||||
filepath: undefined,
|
filepath: undefined,
|
||||||
@@ -270,7 +284,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ import "./NotebookReadOnlyRenderer.less";
|
|||||||
import SandboxOutputs from "./outputs/SandboxOutputs";
|
import SandboxOutputs from "./outputs/SandboxOutputs";
|
||||||
|
|
||||||
export interface NotebookRendererProps {
|
export interface NotebookRendererProps {
|
||||||
contentRef: any;
|
contentRef: ContentRef;
|
||||||
hideInputs?: boolean;
|
hideInputs?: boolean;
|
||||||
hidePrompts?: boolean;
|
hidePrompts?: boolean;
|
||||||
|
addTransform: (component: React.ComponentType & { MIMETYPE: string }) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,7 +28,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 any);
|
loadTransform(this.props as NotebookRendererProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +60,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: any; contentRef: ContentRef }) => (
|
code: ({ id, contentRef }: { id: string; 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),
|
||||||
@@ -73,14 +74,14 @@ class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> {
|
|||||||
}}
|
}}
|
||||||
</CodeCell>
|
</CodeCell>
|
||||||
),
|
),
|
||||||
markdown: ({ id, contentRef }: { id: any; contentRef: ContentRef }) => (
|
markdown: ({ id, contentRef }: { id: string; 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: any; contentRef: ContentRef }) => (
|
raw: ({ id, contentRef }: { id: string; contentRef: ContentRef }) => (
|
||||||
<RawCell id={id} contentRef={contentRef} cell_type="raw">
|
<RawCell id={id} contentRef={contentRef} cell_type="raw">
|
||||||
{{
|
{{
|
||||||
editor: {
|
editor: {
|
||||||
@@ -98,6 +99,7 @@ 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 {
|
||||||
@@ -114,4 +116,4 @@ const makeMapDispatchToProps = (initialDispatch: Dispatch, initialProps: Noteboo
|
|||||||
return mapDispatchToProps;
|
return mapDispatchToProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(null, makeMapDispatchToProps)(NotebookReadOnlyRenderer);
|
export default connect(undefined, makeMapDispatchToProps)(NotebookReadOnlyRenderer);
|
||||||
|
|||||||
@@ -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 * as Constants from "../../Common/Constants";
|
import { CollectionCreation } from "Shared/Constants";
|
||||||
import { createCollection } from "../../Common/dataAccess/createCollection";
|
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||||
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
|
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
|
||||||
import { configContext, Platform } from "../../ConfigContext";
|
import { userContext } from "UserContext";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import { getCollectionName } from "Utils/APITypeUtils";
|
||||||
import { SubscriptionType } from "../../Contracts/SubscriptionType";
|
import { isCapabilityEnabled, isServerlessAccount } from "Utils/CapabilityUtils";
|
||||||
import { useSidePanel } from "../../hooks/useSidePanel";
|
import { getUpsellMessage } from "Utils/PricingUtils";
|
||||||
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.partitionKey.trim();
|
let partitionKeyString = this.state.isSharded ? this.state.partitionKey.trim() : undefined;
|
||||||
|
|
||||||
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'
|
||||||
|
|||||||
@@ -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 Constants from "../../../Common/Constants";
|
import * as SharedConstants from "Shared/Constants";
|
||||||
import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils";
|
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||||
import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip";
|
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
|
||||||
import { useSidePanel } from "../../../hooks/useSidePanel";
|
import { userContext } from "UserContext";
|
||||||
import * as SharedConstants from "../../../Shared/Constants";
|
import { isServerlessAccount } from "Utils/CapabilityUtils";
|
||||||
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";
|
||||||
|
|||||||
@@ -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 { Areas } from "../../../Common/Constants";
|
import { DefaultExperienceUtility } from "Shared/DefaultExperienceUtility";
|
||||||
import { deleteCollection } from "../../../Common/dataAccess/deleteCollection";
|
import { Action, ActionModifiers } from "Shared/Telemetry/TelemetryConstants";
|
||||||
import DeleteFeedback from "../../../Common/DeleteFeedback";
|
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
|
||||||
import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils";
|
import { userContext } from "UserContext";
|
||||||
import { Collection } from "../../../Contracts/ViewModels";
|
import { getCollectionName } from "Utils/APITypeUtils";
|
||||||
import { useSidePanel } from "../../../hooks/useSidePanel";
|
import * as NotificationConsoleUtils from "Utils/NotificationConsoleUtils";
|
||||||
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";
|
||||||
|
|||||||
@@ -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 { Areas } from "../../Common/Constants";
|
import { DefaultExperienceUtility } from "Shared/DefaultExperienceUtility";
|
||||||
import { deleteDatabase } from "../../Common/dataAccess/deleteDatabase";
|
import { Action, ActionModifiers } from "Shared/Telemetry/TelemetryConstants";
|
||||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
|
||||||
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
|
import { userContext } from "UserContext";
|
||||||
import { Collection, Database } from "../../Contracts/ViewModels";
|
import { logConsoleError } 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 { 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";
|
||||||
|
|||||||
@@ -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 * as Constants from "../../../Common/Constants";
|
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||||
import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip";
|
import * as StringUtility from "Shared/StringUtility";
|
||||||
import { configContext } from "../../../ConfigContext";
|
import { userContext } from "UserContext";
|
||||||
import { useSidePanel } from "../../../hooks/useSidePanel";
|
import { logConsoleInfo } from "Utils/NotificationConsoleUtils";
|
||||||
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 = () => {
|
||||||
|
|||||||
@@ -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 * as ViewModels from "../../../Contracts/ViewModels";
|
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "Utils/NotificationConsoleUtils";
|
||||||
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";
|
||||||
|
|||||||
@@ -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 { Upload } from "../../../Common/Upload/Upload";
|
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "Utils/NotificationConsoleUtils";
|
||||||
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";
|
||||||
|
|
||||||
|
|||||||
@@ -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 { Upload } from "../../../Common/Upload/Upload";
|
import { logConsoleError } from "Utils/NotificationConsoleUtils";
|
||||||
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";
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import _ from "underscore";
|
|
||||||
import Q from "q";
|
import Q from "q";
|
||||||
|
import _ from "underscore";
|
||||||
import * as Entities from "../Entities";
|
|
||||||
import * as QueryBuilderConstants from "../Constants";
|
import * as QueryBuilderConstants from "../Constants";
|
||||||
|
import * as Entities from "../Entities";
|
||||||
import * as Utilities from "../Utilities";
|
import * as Utilities from "../Utilities";
|
||||||
|
|
||||||
export function getRowSelector(selectorSchema: Entities.IProperty[]): string {
|
export function getRowSelector(selectorSchema: Entities.IProperty[]): string {
|
||||||
var selector: string = "";
|
let selector = "";
|
||||||
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) + '"]';
|
||||||
@@ -15,10 +14,10 @@ export function getRowSelector(selectorSchema: Entities.IProperty[]): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isRowVisible(dataTableScrollBodyQuery: JQuery, element: HTMLElement): boolean {
|
export function isRowVisible(dataTableScrollBodyQuery: JQuery, element: HTMLElement): boolean {
|
||||||
var isVisible = false;
|
let isVisible = false;
|
||||||
|
|
||||||
if (dataTableScrollBodyQuery.length && element) {
|
if (dataTableScrollBodyQuery.length && element) {
|
||||||
var elementRect: ClientRect = element.getBoundingClientRect(),
|
const 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;
|
||||||
@@ -29,17 +28,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) {
|
||||||
var dataTableScrollBodyQuery: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableScrollBodySelector),
|
const dataTableScrollBodyQuery: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableScrollBodySelector),
|
||||||
selectedRowElement: HTMLElement = dataTableRows.get(currentIndex);
|
selectedRowElement: HTMLElement = dataTableRows.get(currentIndex);
|
||||||
|
|
||||||
if (dataTableScrollBodyQuery.length && selectedRowElement) {
|
if (dataTableScrollBodyQuery.length && selectedRowElement) {
|
||||||
var isVisible: boolean = isRowVisible(dataTableScrollBodyQuery, selectedRowElement);
|
const isVisible: boolean = isRowVisible(dataTableScrollBodyQuery, selectedRowElement);
|
||||||
|
|
||||||
if (!isVisible) {
|
if (!isVisible) {
|
||||||
var selectedRowQuery: JQuery = $(selectedRowElement),
|
const selectedRowQuery: JQuery = $(selectedRowElement),
|
||||||
scrollPosition: number = dataTableScrollBodyQuery.scrollTop(),
|
scrollPosition: number = dataTableScrollBodyQuery.scrollTop(),
|
||||||
selectedElementPosition: number = selectedRowQuery.position().top,
|
selectedElementPosition: number = selectedRowQuery.position().top;
|
||||||
newScrollPosition: number = 0;
|
let newScrollPosition = 0;
|
||||||
|
|
||||||
if (isScrollUp) {
|
if (isScrollUp) {
|
||||||
newScrollPosition = scrollPosition + selectedElementPosition;
|
newScrollPosition = scrollPosition + selectedElementPosition;
|
||||||
@@ -55,7 +54,7 @@ export function scrollToRowIfNeeded(dataTableRows: JQuery, currentIndex: number,
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function scrollToTopIfNeeded(): void {
|
export function scrollToTopIfNeeded(): void {
|
||||||
var $dataTableRows: JQuery = $(QueryBuilderConstants.htmlSelectors.dataTableAllRowsSelector),
|
const $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) {
|
||||||
@@ -88,13 +87,14 @@ 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> {
|
||||||
var columnsCount: number = targetOrder.length;
|
const columnsCount: number = targetOrder.length;
|
||||||
var isCurrentOrderPassedIn: boolean = !!currentOrder;
|
const isCurrentOrderPassedIn = !!currentOrder;
|
||||||
if (!isCurrentOrderPassedIn) {
|
if (!isCurrentOrderPassedIn) {
|
||||||
currentOrder = getInitialOrder(columnsCount);
|
currentOrder = getInitialOrder(columnsCount);
|
||||||
}
|
}
|
||||||
var isSameOrder: boolean = Utilities.isEqual(currentOrder, targetOrder);
|
const 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.
|
||||||
var transformationOrder: number[] = isCurrentOrderPassedIn
|
const 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[] {
|
||||||
var invertedArray: number[] = [];
|
const 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,20 +170,21 @@ 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[] {
|
||||||
var transformationOrder: number[] = [];
|
let transformationOrder: number[] = [];
|
||||||
if (currentOrder && targetOrder && currentOrder.length === targetOrder.length) {
|
if (currentOrder && targetOrder && currentOrder.length === targetOrder.length) {
|
||||||
var invertedCurrentOrder: number[] = invertIndexValues(currentOrder);
|
const 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[] {
|
||||||
var columns: DataTables.ColumnsMethods = table.columns();
|
const columns: DataTables.ColumnsMethods = table.columns();
|
||||||
var headers: string[] = [];
|
let 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
|
||||||
var columnIndexes: number[] = (<any>columns)[0];
|
//eslint-disable-next-line
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import TableEntityListViewModel from "./TableEntityListViewModel";
|
|||||||
|
|
||||||
export default class TableCommands {
|
export default class TableCommands {
|
||||||
// Command Ids
|
// Command Ids
|
||||||
public static editEntityCommand: string = "edit";
|
public static editEntityCommand = "edit";
|
||||||
public static deleteEntitiesCommand: string = "delete";
|
public static deleteEntitiesCommand = "delete";
|
||||||
public static reorderColumnsCommand: string = "reorder";
|
public static reorderColumnsCommand = "reorder";
|
||||||
public static resetColumnsCommand: string = "reset";
|
public static resetColumnsCommand = "reset";
|
||||||
public static customizeColumnsCommand: string = "customizeColumns";
|
public static customizeColumnsCommand = "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 {
|
||||||
var singleItemSelected: boolean = DataTableUtilities.containSingleItem(selectedEntites);
|
const singleItemSelected = DataTableUtilities.containSingleItem(selectedEntites);
|
||||||
var atLeastOneItemSelected: boolean = DataTableUtilities.containItems(selectedEntites);
|
const atLeastOneItemSelected = DataTableUtilities.containItems(selectedEntites);
|
||||||
switch (commandName) {
|
switch (commandName) {
|
||||||
case TableCommands.editEntityCommand:
|
case TableCommands.editEntityCommand:
|
||||||
return singleItemSelected;
|
return singleItemSelected;
|
||||||
@@ -47,6 +47,7 @@ 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
|
||||||
@@ -56,12 +57,9 @@ 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
|
||||||
@@ -69,7 +67,7 @@ export default class TableCommands {
|
|||||||
if (!DataTableUtilities.containItems(viewModel.selected())) {
|
if (!DataTableUtilities.containItems(viewModel.selected())) {
|
||||||
return null; // Error
|
return null; // Error
|
||||||
}
|
}
|
||||||
var entitiesToDelete: Entities.ITableEntity[] = viewModel.selected();
|
const 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?"
|
||||||
@@ -82,7 +80,7 @@ export default class TableCommands {
|
|||||||
() => {
|
() => {
|
||||||
viewModel.queryTablesTab.container.tableDataClient
|
viewModel.queryTablesTab.container.tableDataClient
|
||||||
.deleteDocuments(viewModel.queryTablesTab.collection, entitiesToDelete)
|
.deleteDocuments(viewModel.queryTablesTab.collection, entitiesToDelete)
|
||||||
.then((results: any) => {
|
.then(() => {
|
||||||
return viewModel.removeEntitiesFromCache(entitiesToDelete).then(() => {
|
return viewModel.removeEntitiesFromCache(entitiesToDelete).then(() => {
|
||||||
viewModel.redrawTableThrottled();
|
viewModel.redrawTableThrottled();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as Utilities from "../Utilities";
|
|
||||||
import * as Entities from "../Entities";
|
import * as Entities from "../Entities";
|
||||||
|
import * as Utilities from "../Utilities";
|
||||||
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() {
|
public preClear(): void {
|
||||||
this.tableQuery = null;
|
this.tableQuery = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos";
|
import { ItemDefinition, QueryIterator, Resource } from "@azure/cosmos";
|
||||||
|
|
||||||
export interface ITableEntity {
|
export interface ITableEntity {
|
||||||
[property: string]: ITableEntityAttribute;
|
[property: string]: ITableEntityAttribute;
|
||||||
@@ -17,6 +17,7 @@ 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>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import QueryClauseViewModel from "./QueryClauseViewModel";
|
|
||||||
import * as Utilities from "../Utilities";
|
import * as Utilities from "../Utilities";
|
||||||
|
import QueryClauseViewModel from "./QueryClauseViewModel";
|
||||||
|
|
||||||
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;
|
||||||
@@ -17,7 +18,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 {
|
||||||
var tempArray = new Array<QueryClauseViewModel>();
|
const tempArray = new Array<QueryClauseViewModel>();
|
||||||
|
|
||||||
this.flattenClausesImpl(this, tempArray);
|
this.flattenClausesImpl(this, tempArray);
|
||||||
targetArray.removeAll();
|
targetArray.removeAll();
|
||||||
@@ -31,10 +32,10 @@ export default class ClauseGroup {
|
|||||||
newClause.clauseGroup = this;
|
newClause.clauseGroup = this;
|
||||||
this.children.push(newClause);
|
this.children.push(newClause);
|
||||||
} else {
|
} else {
|
||||||
var targetGroup = insertBefore.clauseGroup;
|
const targetGroup = insertBefore.clauseGroup;
|
||||||
|
|
||||||
if (targetGroup) {
|
if (targetGroup) {
|
||||||
var insertBeforeIndex = targetGroup.children.indexOf(insertBefore);
|
const insertBeforeIndex = targetGroup.children.indexOf(insertBefore);
|
||||||
newClause.clauseGroup = targetGroup;
|
newClause.clauseGroup = targetGroup;
|
||||||
targetGroup.children.splice(insertBeforeIndex, 0, newClause);
|
targetGroup.children.splice(insertBeforeIndex, 0, newClause);
|
||||||
}
|
}
|
||||||
@@ -42,19 +43,19 @@ export default class ClauseGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public deleteClause(clause: QueryClauseViewModel): void {
|
public deleteClause(clause: QueryClauseViewModel): void {
|
||||||
var targetGroup = clause.clauseGroup;
|
const targetGroup = clause.clauseGroup;
|
||||||
|
|
||||||
if (targetGroup) {
|
if (targetGroup) {
|
||||||
var index = targetGroup.children.indexOf(clause);
|
const 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) {
|
||||||
var parent = targetGroup.parentGroup;
|
const parent = targetGroup.parentGroup;
|
||||||
var targetGroupIndex = parent.children.indexOf(targetGroup);
|
const targetGroupIndex = parent.children.indexOf(targetGroup);
|
||||||
|
|
||||||
if (targetGroup.children.length === 1) {
|
if (targetGroup.children.length === 1) {
|
||||||
var orphan = targetGroup.children.shift();
|
const orphan = targetGroup.children.shift();
|
||||||
|
|
||||||
if (orphan instanceof QueryClauseViewModel) {
|
if (orphan instanceof QueryClauseViewModel) {
|
||||||
(<QueryClauseViewModel>orphan).clauseGroup = parent;
|
(<QueryClauseViewModel>orphan).clauseGroup = parent;
|
||||||
@@ -71,14 +72,14 @@ export default class ClauseGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public removeAll(): void {
|
public removeAll(): void {
|
||||||
var allClauses: QueryClauseViewModel[] = new Array<QueryClauseViewModel>();
|
const 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>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,12 +88,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).
|
||||||
var selection = this.getCheckedItemsInfo();
|
const selection = this.getCheckedItemsInfo();
|
||||||
|
|
||||||
if (selection.canGroup) {
|
if (selection.canGroup) {
|
||||||
var newGroup = new ClauseGroup(false, this);
|
const 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.
|
||||||
var groupedItems = this.children.splice(selection.begin, selection.end - selection.begin + 1, newGroup);
|
const groupedItems = this.children.splice(selection.begin, selection.end - selection.begin + 1, newGroup);
|
||||||
|
|
||||||
groupedItems &&
|
groupedItems &&
|
||||||
groupedItems.forEach((element) => {
|
groupedItems.forEach((element) => {
|
||||||
@@ -118,13 +119,13 @@ export default class ClauseGroup {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var parentGroup = this.parentGroup;
|
const parentGroup = this.parentGroup;
|
||||||
var index = parentGroup.children.indexOf(this);
|
let index = parentGroup.children.indexOf(this);
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
parentGroup.children.splice(index, 1);
|
parentGroup.children.splice(index, 1);
|
||||||
|
|
||||||
var toPromote = this.children.splice(0, this.children.length);
|
const toPromote = this.children.splice(0, this.children.length);
|
||||||
|
|
||||||
// Move all children one level up.
|
// Move all children one level up.
|
||||||
toPromote &&
|
toPromote &&
|
||||||
@@ -146,16 +147,16 @@ export default class ClauseGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public findDeepestGroupInChildren(skipIndex?: number): ClauseGroup {
|
public findDeepestGroupInChildren(skipIndex?: number): ClauseGroup {
|
||||||
var deepest: ClauseGroup = this;
|
let deepest = <ClauseGroup>this;
|
||||||
var level: number = 0;
|
let level = 0;
|
||||||
var func = (currentGroup: ClauseGroup): void => {
|
const func = (currentGroup: ClauseGroup): void => {
|
||||||
level++;
|
level++;
|
||||||
if (currentGroup.getCurrentGroupDepth() > deepest.getCurrentGroupDepth()) {
|
if (currentGroup.getCurrentGroupDepth() > deepest.getCurrentGroupDepth()) {
|
||||||
deepest = currentGroup;
|
deepest = currentGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < currentGroup.children.length; i++) {
|
for (let i = 0; i < currentGroup.children.length; i++) {
|
||||||
var currentItem = currentGroup.children[i];
|
const currentItem = currentGroup.children[i];
|
||||||
|
|
||||||
if ((i !== skipIndex || level > 1) && currentItem instanceof ClauseGroup) {
|
if ((i !== skipIndex || level > 1) && currentItem instanceof ClauseGroup) {
|
||||||
func(currentItem);
|
func(currentItem);
|
||||||
@@ -170,16 +171,16 @@ export default class ClauseGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getCheckedItemsInfo(): { canGroup: boolean; begin: number; end: number } {
|
private getCheckedItemsInfo(): { canGroup: boolean; begin: number; end: number } {
|
||||||
var beginIndex = -1;
|
let beginIndex = -1;
|
||||||
var endIndex = -1;
|
let 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.
|
||||||
var gapFlag = false;
|
let gapFlag = false;
|
||||||
var count = 0;
|
let count = 0;
|
||||||
|
|
||||||
for (var i = 0; i < this.children.length; i++) {
|
for (let i = 0; i < this.children.length; i++) {
|
||||||
var currentItem = this.children[i];
|
const currentItem = this.children[i];
|
||||||
var subGroupSelectionState: { allSelected: boolean; partiallySelected: boolean; nonSelected: boolean };
|
let subGroupSelectionState: { allSelected: boolean; partiallySelected: boolean; nonSelected: boolean };
|
||||||
|
|
||||||
if (currentItem instanceof ClauseGroup) {
|
if (currentItem instanceof ClauseGroup) {
|
||||||
subGroupSelectionState = (<ClauseGroup>currentItem).getSelectionState();
|
subGroupSelectionState = (<ClauseGroup>currentItem).getSelectionState();
|
||||||
@@ -235,10 +236,10 @@ export default class ClauseGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getSelectionState(): { allSelected: boolean; partiallySelected: boolean; nonSelected: boolean } {
|
private getSelectionState(): { allSelected: boolean; partiallySelected: boolean; nonSelected: boolean } {
|
||||||
var selectedCount = 0;
|
let selectedCount = 0;
|
||||||
|
|
||||||
for (var i = 0; i < this.children.length; i++) {
|
for (let i = 0; i < this.children.length; i++) {
|
||||||
var currentItem = this.children[i];
|
const currentItem = this.children[i];
|
||||||
|
|
||||||
if (currentItem instanceof ClauseGroup && (<ClauseGroup>currentItem).getSelectionState().allSelected) {
|
if (currentItem instanceof ClauseGroup && (<ClauseGroup>currentItem).getSelectionState().allSelected) {
|
||||||
selectedCount++;
|
selectedCount++;
|
||||||
@@ -260,8 +261,8 @@ export default class ClauseGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private unselectAll(): void {
|
private unselectAll(): void {
|
||||||
for (var i = 0; i < this.children.length; i++) {
|
for (let i = 0; i < this.children.length; i++) {
|
||||||
var currentItem = this.children[i];
|
const currentItem = this.children[i];
|
||||||
|
|
||||||
if (currentItem instanceof ClauseGroup) {
|
if (currentItem instanceof ClauseGroup) {
|
||||||
(<ClauseGroup>currentItem).unselectAll();
|
(<ClauseGroup>currentItem).unselectAll();
|
||||||
@@ -278,8 +279,8 @@ export default class ClauseGroup {
|
|||||||
targetArray.splice(0, targetArray.length);
|
targetArray.splice(0, targetArray.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < queryGroup.children.length; i++) {
|
for (let i = 0; i < queryGroup.children.length; i++) {
|
||||||
var currentItem = queryGroup.children[i];
|
const currentItem = queryGroup.children[i];
|
||||||
|
|
||||||
if (currentItem instanceof ClauseGroup) {
|
if (currentItem instanceof ClauseGroup) {
|
||||||
this.flattenClausesImpl(currentItem, targetArray);
|
this.flattenClausesImpl(currentItem, targetArray);
|
||||||
@@ -292,13 +293,13 @@ export default class ClauseGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getTreeDepth(): number {
|
public getTreeDepth(): number {
|
||||||
var currentDepth = this.getCurrentGroupDepth();
|
let currentDepth = this.getCurrentGroupDepth();
|
||||||
|
|
||||||
for (var i = 0; i < this.children.length; i++) {
|
for (let i = 0; i < this.children.length; i++) {
|
||||||
var currentItem = this.children[i];
|
const currentItem = this.children[i];
|
||||||
|
|
||||||
if (currentItem instanceof ClauseGroup) {
|
if (currentItem instanceof ClauseGroup) {
|
||||||
var newDepth = (<ClauseGroup>currentItem).getTreeDepth();
|
const newDepth = (<ClauseGroup>currentItem).getTreeDepth();
|
||||||
|
|
||||||
if (newDepth > currentDepth) {
|
if (newDepth > currentDepth) {
|
||||||
currentDepth = newDepth;
|
currentDepth = newDepth;
|
||||||
@@ -310,8 +311,8 @@ export default class ClauseGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getCurrentGroupDepth(): number {
|
public getCurrentGroupDepth(): number {
|
||||||
var group = <ClauseGroup>this;
|
let group = <ClauseGroup>this;
|
||||||
var depth = 0;
|
let depth = 0;
|
||||||
|
|
||||||
while (!group.isRootGroup) {
|
while (!group.isRootGroup) {
|
||||||
depth++;
|
depth++;
|
||||||
|
|||||||
@@ -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 {
|
||||||
var colorCount = Constants.clauseGroupColors.length;
|
const colorCount = Constants.clauseGroupColors.length;
|
||||||
|
|
||||||
if (group.isRootGroup) {
|
if (group.isRootGroup) {
|
||||||
return Constants.transparentColor;
|
return Constants.transparentColor;
|
||||||
|
|||||||
@@ -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, null); // The actual data structure containing the clause information.
|
public queryClauses = new ClauseGroup(true, undefined); // 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() {
|
||||||
var example1 = new QueryClauseViewModel(
|
const example1 = new QueryClauseViewModel(
|
||||||
this,
|
this,
|
||||||
"",
|
"",
|
||||||
"PartitionKey",
|
"PartitionKey",
|
||||||
@@ -121,7 +121,7 @@ export default class QueryBuilderViewModel {
|
|||||||
//null,
|
//null,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
var example2 = new QueryClauseViewModel(
|
const example2 = new QueryClauseViewModel(
|
||||||
this,
|
this,
|
||||||
"And",
|
"And",
|
||||||
"RowKey",
|
"RowKey",
|
||||||
@@ -140,13 +140,13 @@ export default class QueryBuilderViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getODataFilterFromClauses = (): string => {
|
public getODataFilterFromClauses = (): string => {
|
||||||
var filterString: string = "";
|
let filterString = "";
|
||||||
var treeTraversal = (group: ClauseGroup): void => {
|
const treeTraversal = (group: ClauseGroup): void => {
|
||||||
for (var i = 0; i < group.children.length; i++) {
|
for (let i = 0; i < group.children.length; i++) {
|
||||||
var currentItem = group.children[i];
|
const currentItem = group.children[i];
|
||||||
|
|
||||||
if (currentItem instanceof QueryClauseViewModel) {
|
if (currentItem instanceof QueryClauseViewModel) {
|
||||||
var clause = <QueryClauseViewModel>currentItem;
|
const 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 => {
|
||||||
var filterString: string = "SELECT * FROM c";
|
let filterString = "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");
|
||||||
var first = true;
|
let first = true;
|
||||||
var treeTraversal = (group: ClauseGroup): void => {
|
const treeTraversal = (group: ClauseGroup): void => {
|
||||||
for (var i = 0; i < group.children.length; i++) {
|
for (let i = 0; i < group.children.length; i++) {
|
||||||
var currentItem = group.children[i];
|
const currentItem = group.children[i];
|
||||||
|
|
||||||
if (currentItem instanceof QueryClauseViewModel) {
|
if (currentItem instanceof QueryClauseViewModel) {
|
||||||
var clause = <QueryClauseViewModel>currentItem;
|
const clause = <QueryClauseViewModel>currentItem;
|
||||||
let timeStampValue: string = this.timestampToSqlValue(clause);
|
const timeStampValue: string = this.timestampToSqlValue(clause);
|
||||||
var value = clause.value();
|
let 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)}`;
|
||||||
var filterString: string = `SELECT * FROM ${tableToQuery}`;
|
let filterString = `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");
|
||||||
var first = true;
|
let first = true;
|
||||||
var treeTraversal = (group: ClauseGroup): void => {
|
const treeTraversal = (group: ClauseGroup): void => {
|
||||||
for (var i = 0; i < group.children.length; i++) {
|
for (let i = 0; i < group.children.length; i++) {
|
||||||
var currentItem = group.children[i];
|
const currentItem = group.children[i];
|
||||||
|
|
||||||
if (currentItem instanceof QueryClauseViewModel) {
|
if (currentItem instanceof QueryClauseViewModel) {
|
||||||
var clause = <QueryClauseViewModel>currentItem;
|
const clause = <QueryClauseViewModel>currentItem;
|
||||||
let timeStampValue: string = this.timestampToSqlValue(clause);
|
const timeStampValue = this.timestampToSqlValue(clause);
|
||||||
var value = clause.value();
|
let 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();
|
||||||
let newHeaders = this.tableEntityListViewModel.headers;
|
const 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 {
|
||||||
var result = "";
|
let 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("(");
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentGroup: ClauseGroup = clause.clauseGroup;
|
let 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 {
|
||||||
var result = "";
|
let result = "";
|
||||||
|
|
||||||
if (
|
if (
|
||||||
clause.clauseGroup.isRootGroup ||
|
clause.clauseGroup.isRootGroup ||
|
||||||
@@ -333,7 +333,7 @@ export default class QueryBuilderViewModel {
|
|||||||
result = result.concat(")");
|
result = result.concat(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentGroup: ClauseGroup = clause.clauseGroup;
|
let currentGroup: ClauseGroup = clause.clauseGroup;
|
||||||
|
|
||||||
while (
|
while (
|
||||||
!currentGroup.isRootGroup &&
|
!currentGroup.isRootGroup &&
|
||||||
@@ -364,14 +364,17 @@ 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(
|
||||||
@@ -391,9 +394,11 @@ 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;
|
||||||
@@ -403,16 +408,21 @@ 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}`;
|
||||||
@@ -434,6 +444,7 @@ 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}`;
|
||||||
@@ -454,7 +465,7 @@ export default class QueryBuilderViewModel {
|
|||||||
case Constants.Operator.NotEqualTo:
|
case Constants.Operator.NotEqualTo:
|
||||||
return Constants.ODataOperator.NotEqualTo;
|
return Constants.ODataOperator.NotEqualTo;
|
||||||
}
|
}
|
||||||
return null;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
public groupClauses = (): void => {
|
public groupClauses = (): void => {
|
||||||
@@ -463,11 +474,11 @@ export default class QueryBuilderViewModel {
|
|||||||
this.updateCanGroupClauses();
|
this.updateCanGroupClauses();
|
||||||
};
|
};
|
||||||
|
|
||||||
public addClauseIndex = (index: number, data: any): void => {
|
public addClauseIndex = (index: number): void => {
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
var newClause = new QueryClauseViewModel(
|
const newClause = new QueryClauseViewModel(
|
||||||
this,
|
this,
|
||||||
"And",
|
"And",
|
||||||
"",
|
"",
|
||||||
@@ -492,28 +503,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, null);
|
this.addClauseIndex(this.clauseArray().length);
|
||||||
};
|
};
|
||||||
|
|
||||||
public onAddClauseKeyDown = (index: number, data: any, event: KeyboardEvent, source: any): boolean => {
|
public onAddClauseKeyDown = (index: number, event: KeyboardEvent): boolean => {
|
||||||
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
|
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
|
||||||
this.addClauseIndex(index, data);
|
this.addClauseIndex(index);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
public onAddNewClauseKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
public onAddNewClauseKeyDown = (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, null);
|
this.addClauseIndex(this.clauseArray().length - 1);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
public deleteClause = (index: number, data: any): void => {
|
public deleteClause = (index: number): 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("");
|
||||||
@@ -523,9 +534,9 @@ export default class QueryBuilderViewModel {
|
|||||||
$(window).resize();
|
$(window).resize();
|
||||||
};
|
};
|
||||||
|
|
||||||
public onDeleteClauseKeyDown = (index: number, data: any, event: KeyboardEvent, source: any): boolean => {
|
public onDeleteClauseKeyDown = (index: number, event: KeyboardEvent): boolean => {
|
||||||
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
|
if (event.keyCode === KeyCodes.Enter || event.keyCode === KeyCodes.Space) {
|
||||||
this.deleteClause(index, data);
|
this.deleteClause(index);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -539,25 +550,26 @@ 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[] => {
|
||||||
var placeHolderGroupViewModel = new ClauseGroupViewModel(this.queryClauses, false, this);
|
const placeHolderGroupViewModel = new ClauseGroupViewModel(this.queryClauses, false, this);
|
||||||
var treeDepth = this.queryClauses.getTreeDepth();
|
const treeDepth = this.queryClauses.getTreeDepth();
|
||||||
var groupViewModels = new Array<ClauseGroupViewModel>(treeDepth);
|
const groupViewModels = new Array<ClauseGroupViewModel>(treeDepth);
|
||||||
|
|
||||||
// Prefill the arry with placeholders.
|
// Prefill the arry with placeholders.
|
||||||
for (var i = 0; i < groupViewModels.length; i++) {
|
for (let i = 0; i < groupViewModels.length; i++) {
|
||||||
groupViewModels[i] = placeHolderGroupViewModel;
|
groupViewModels[i] = placeHolderGroupViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentGroup = clause.clauseGroup;
|
let 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.
|
||||||
var isLeftMostPath = (): boolean => {
|
const isLeftMostPath = (): boolean => {
|
||||||
var group = clause.clauseGroup;
|
let 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;
|
||||||
@@ -573,13 +585,14 @@ 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.
|
||||||
var isRightMostPath = (): boolean => {
|
const isRightMostPath = (): boolean => {
|
||||||
var group = clause.clauseGroup;
|
let 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;
|
||||||
@@ -594,26 +607,26 @@ export default class QueryBuilderViewModel {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
var vmIndex = groupViewModels.length - 1;
|
let vmIndex = groupViewModels.length - 1;
|
||||||
var skipIndex = -1;
|
let skipIndex = -1;
|
||||||
var lastDepth = clause.groupDepth;
|
let 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.
|
||||||
var deepestInSiblings = currentGroup.findDeepestGroupInChildren(skipIndex).getCurrentGroupDepth();
|
const 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.
|
||||||
var repeatCount = Math.max(deepestInSiblings - lastDepth, 0);
|
const repeatCount = Math.max(deepestInSiblings - lastDepth, 0);
|
||||||
|
|
||||||
for (var i = 0; i <= repeatCount; i++) {
|
for (let i = 0; i <= repeatCount; i++) {
|
||||||
var isLeftMost = isLeftMostPath();
|
const isLeftMost = isLeftMostPath();
|
||||||
var isRightMost = isRightMostPath();
|
const isRightMost = isRightMostPath();
|
||||||
var groupViewModel = new ClauseGroupViewModel(currentGroup, i === 0 && isLeftMost, this);
|
const groupViewModel = new ClauseGroupViewModel(currentGroup, i === 0 && isLeftMost, this);
|
||||||
|
|
||||||
groupViewModel.showTopBorder(isLeftMost);
|
groupViewModel.showTopBorder(isLeftMost);
|
||||||
groupViewModel.showBottomBorder(isRightMost);
|
groupViewModel.showBottomBorder(isRightMost);
|
||||||
@@ -635,9 +648,9 @@ export default class QueryBuilderViewModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public addCustomRange(timestamp: CustomTimestampHelper.ITimestampQuery, clauseToAdd: QueryClauseViewModel): void {
|
public addCustomRange(timestamp: CustomTimestampHelper.ITimestampQuery, clauseToAdd: QueryClauseViewModel): void {
|
||||||
var index = this.clauseArray.peek().indexOf(clauseToAdd);
|
const index = this.clauseArray.peek().indexOf(clauseToAdd);
|
||||||
|
|
||||||
var newClause = new QueryClauseViewModel(
|
const newClause = new QueryClauseViewModel(
|
||||||
this,
|
this,
|
||||||
//this._tableEntityListViewModel.tableExplorerContext.hostProxy,
|
//this._tableEntityListViewModel.tableExplorerContext.hostProxy,
|
||||||
"And",
|
"And",
|
||||||
@@ -662,10 +675,10 @@ export default class QueryBuilderViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private scrollToBottom(): void {
|
private scrollToBottom(): void {
|
||||||
var scrollBox = document.getElementById("scroll");
|
const scrollBox = document.getElementById("scroll");
|
||||||
if (!this.scrollEventListener) {
|
if (!this.scrollEventListener) {
|
||||||
scrollBox.addEventListener("scroll", function () {
|
scrollBox.addEventListener("scroll", function () {
|
||||||
var translate = "translate(0," + this.scrollTop + "px)";
|
const 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;
|
||||||
@@ -673,7 +686,7 @@ export default class QueryBuilderViewModel {
|
|||||||
});
|
});
|
||||||
this.scrollEventListener = true;
|
this.scrollEventListener = true;
|
||||||
}
|
}
|
||||||
var isScrolledToBottom = scrollBox.scrollHeight - scrollBox.clientHeight <= scrollBox.scrollHeight + 1;
|
const isScrolledToBottom = scrollBox.scrollHeight - scrollBox.clientHeight <= scrollBox.scrollHeight + 1;
|
||||||
if (isScrolledToBottom) {
|
if (isScrolledToBottom) {
|
||||||
scrollBox.scrollTop = scrollBox.scrollHeight - scrollBox.clientHeight;
|
scrollBox.scrollTop = scrollBox.scrollHeight - scrollBox.clientHeight;
|
||||||
}
|
}
|
||||||
@@ -685,8 +698,8 @@ export default class QueryBuilderViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private deleteClauseImpl(index: number): void {
|
private deleteClauseImpl(index: number): void {
|
||||||
var clause = this.clauseArray()[index];
|
const clause = this.clauseArray()[index];
|
||||||
var previousClause = index === 0 ? 0 : index - 1;
|
const 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]) {
|
||||||
@@ -731,7 +744,7 @@ export default class QueryBuilderViewModel {
|
|||||||
|
|
||||||
private timestampToSqlValue(clause: QueryClauseViewModel): string {
|
private timestampToSqlValue(clause: QueryClauseViewModel): string {
|
||||||
if (clause.isValue()) {
|
if (clause.isValue()) {
|
||||||
return null;
|
return undefined;
|
||||||
} else if (clause.isTimestamp()) {
|
} else if (clause.isTimestamp()) {
|
||||||
return this.getTimeStampToSqlQuery(clause);
|
return this.getTimeStampToSqlQuery(clause);
|
||||||
// } else if (clause.isCustomLastTimestamp()) {
|
// } else if (clause.isCustomLastTimestamp()) {
|
||||||
@@ -743,7 +756,7 @@ export default class QueryBuilderViewModel {
|
|||||||
return clause.customTimeValue();
|
return clause.customTimeValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTimeStampToQuery(clause: QueryClauseViewModel): void {
|
private getTimeStampToQuery(clause: QueryClauseViewModel): void {
|
||||||
@@ -789,7 +802,7 @@ export default class QueryBuilderViewModel {
|
|||||||
case Constants.timeOptions.currentYear:
|
case Constants.timeOptions.currentYear:
|
||||||
return CustomTimestampHelper._queryCurrentYearLocal();
|
return CustomTimestampHelper._queryCurrentYearLocal();
|
||||||
}
|
}
|
||||||
return null;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public checkIfClauseChanged(): void {
|
public checkIfClauseChanged(): void {
|
||||||
|
|||||||
@@ -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<any>;
|
public value: ko.Observable<string>;
|
||||||
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: any,
|
value: string,
|
||||||
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((value) => {
|
this.and_or.subscribe(() => {
|
||||||
this._queryBuilderViewModel.checkIfClauseChanged();
|
this._queryBuilderViewModel.checkIfClauseChanged();
|
||||||
});
|
});
|
||||||
this.field.subscribe((value) => {
|
this.field.subscribe(() => {
|
||||||
this.changeField();
|
this.changeField();
|
||||||
});
|
});
|
||||||
this.type.subscribe((value) => {
|
this.type.subscribe(() => {
|
||||||
this.changeType();
|
this.changeType();
|
||||||
});
|
});
|
||||||
this.timeValue.subscribe((value) => {
|
this.timeValue.subscribe(() => {
|
||||||
// if (this.timeValue() === QueryBuilderConstants.timeOptions.custom) {
|
// if (this.timeValue() === QueryBuilderConstants.timeOptions.custom) {
|
||||||
// this.customTimestampDialog();
|
// this.customTimestampDialog();
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
this.customTimeValue.subscribe((value) => {
|
this.customTimeValue.subscribe(() => {
|
||||||
this._queryBuilderViewModel.checkIfClauseChanged();
|
this._queryBuilderViewModel.checkIfClauseChanged();
|
||||||
});
|
});
|
||||||
this.value.subscribe((value) => {
|
this.value.subscribe(() => {
|
||||||
this._queryBuilderViewModel.checkIfClauseChanged();
|
this._queryBuilderViewModel.checkIfClauseChanged();
|
||||||
});
|
});
|
||||||
this.operator.subscribe((value) => {
|
this.operator.subscribe(() => {
|
||||||
this._queryBuilderViewModel.checkIfClauseChanged();
|
this._queryBuilderViewModel.checkIfClauseChanged();
|
||||||
});
|
});
|
||||||
this._groupCheckSubscription = this.checkedForGrouping.subscribe((value) => {
|
this._groupCheckSubscription = this.checkedForGrouping.subscribe(() => {
|
||||||
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 = null;
|
this.clauseGroup = undefined;
|
||||||
this._queryBuilderViewModel = null;
|
this._queryBuilderViewModel = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ 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;
|
||||||
@@ -34,7 +35,7 @@ export default class Trigger {
|
|||||||
this.triggerType = ko.observable(data.triggerType);
|
this.triggerType = ko.observable(data.triggerType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public select() {
|
public select(): void {
|
||||||
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",
|
||||||
@@ -43,7 +44,8 @@ export default class Trigger {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static create(source: ViewModels.Collection, event: MouseEvent) {
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
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: "",
|
||||||
@@ -99,7 +101,7 @@ export default class Trigger {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public delete() {
|
public delete(): void {
|
||||||
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?",
|
||||||
@@ -110,7 +112,8 @@ 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);
|
||||||
},
|
},
|
||||||
(reason) => {}
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
() => {}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
"Cancel",
|
"Cancel",
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export class GitHubOAuthService {
|
|||||||
return params.state;
|
return params.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async finishOAuth(params: IGitHubConnectorParams) {
|
public async finishOAuth(params: IGitHubConnectorParams): Promise<void> {
|
||||||
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() {
|
public resetToken(): void {
|
||||||
this.token(undefined);
|
this.token(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ describe("Pinned repos", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("updatePinnedRepos invokes pinned repos subscribers", async () => {
|
it("updatePinnedRepos invokes pinned repos subscribers", async () => {
|
||||||
const callback = jest.fn().mockImplementation((pinnedRepos: IPinnedRepo[]) => {});
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
const callback = jest.fn().mockImplementation(() => {});
|
||||||
|
|
||||||
junoClient.subscribeToPinnedRepos(callback);
|
junoClient.subscribeToPinnedRepos(callback);
|
||||||
const response = await junoClient.updatePinnedRepos(samplePinnedRepos);
|
const response = await junoClient.updatePinnedRepos(samplePinnedRepos);
|
||||||
@@ -60,7 +61,8 @@ describe("Pinned repos", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("getPinnedRepos invokes pinned repos subscribers", async () => {
|
it("getPinnedRepos invokes pinned repos subscribers", async () => {
|
||||||
const callback = jest.fn().mockImplementation((pinnedRepos: IPinnedRepo[]) => {});
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
|
const callback = jest.fn().mockImplementation(() => {});
|
||||||
|
|
||||||
junoClient.subscribeToPinnedRepos(callback);
|
junoClient.subscribeToPinnedRepos(callback);
|
||||||
const response = await junoClient.getPinnedRepos("scope");
|
const response = await junoClient.getPinnedRepos("scope");
|
||||||
@@ -153,7 +155,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.getSampleNotebooks();
|
const response = await junoClient.getSampleNotebooks();
|
||||||
@@ -165,7 +167,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.getPublicNotebooks();
|
const response = await junoClient.getPublicNotebooks();
|
||||||
@@ -178,7 +180,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.getNotebookInfo(id);
|
const response = await junoClient.getNotebookInfo(id);
|
||||||
@@ -191,7 +193,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 any,
|
text: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.getNotebookContent(id);
|
const response = await junoClient.getNotebookContent(id);
|
||||||
@@ -204,7 +206,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
const response = await junoClient.increaseNotebookViews(id);
|
const response = await junoClient.increaseNotebookViews(id);
|
||||||
|
|
||||||
@@ -218,7 +220,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.increaseNotebookDownloadCount(id);
|
const response = await junoClient.increaseNotebookDownloadCount(id);
|
||||||
@@ -243,7 +245,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.favoriteNotebook(id);
|
const response = await junoClient.favoriteNotebook(id);
|
||||||
@@ -268,7 +270,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.unfavoriteNotebook(id);
|
const response = await junoClient.unfavoriteNotebook(id);
|
||||||
@@ -292,7 +294,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.getFavoriteNotebooks();
|
const response = await junoClient.getFavoriteNotebooks();
|
||||||
@@ -315,7 +317,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.getPublishedNotebooks();
|
const response = await junoClient.getPublishedNotebooks();
|
||||||
@@ -339,7 +341,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.deleteNotebook(id);
|
const response = await junoClient.deleteNotebook(id);
|
||||||
@@ -369,7 +371,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 any,
|
json: () => undefined as undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await junoClient.publishNotebook(name, description, tags, thumbnailUrl, content);
|
const response = await junoClient.publishNotebook(name, description, tags, thumbnailUrl, content);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export interface IPublishNotebookRequest {
|
|||||||
description: string;
|
description: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
thumbnailUrl: string;
|
thumbnailUrl: string;
|
||||||
content: any;
|
content: unknown;
|
||||||
addLinkToNotebookViewer: boolean;
|
addLinkToNotebookViewer: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ describe("GalleryUtils", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("downloadItem shows dialog in data explorer", () => {
|
it("downloadItem shows dialog in data explorer", () => {
|
||||||
const container = {} as Explorer;
|
const container = new 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);
|
||||||
|
|||||||
@@ -69,7 +69,11 @@ 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];
|
||||||
set({ activeTab: tabToTheRight || lastOpenTab });
|
const newActiveTab = tabToTheRight ?? lastOpenTab;
|
||||||
|
set({ activeTab: newActiveTab });
|
||||||
|
if (newActiveTab) {
|
||||||
|
newActiveTab.onActivate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set({ openedTabs: updatedTabs });
|
set({ openedTabs: updatedTabs });
|
||||||
|
|||||||
@@ -15,18 +15,13 @@
|
|||||||
"target": "es2017",
|
"target": "es2017",
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"lib": [
|
"lib": ["es5", "es6", "dom"],
|
||||||
"es5",
|
|
||||||
"es6",
|
|
||||||
"dom"
|
|
||||||
],
|
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"types": [
|
"types": ["jest"],
|
||||||
"jest"
|
"baseUrl": "src"
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"typedocOptions": {
|
"typedocOptions": {
|
||||||
"entryPoints": [
|
"entryPoints": [
|
||||||
@@ -42,11 +37,6 @@
|
|||||||
"includes": "./src/SelfServe/Documentation",
|
"includes": "./src/SelfServe/Documentation",
|
||||||
"disableSources": true
|
"disableSources": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src", "./src/**/*", "./utils/**/*"],
|
||||||
"./src/**/*",
|
"exclude": ["./src/**/__mocks__/**/*"]
|
||||||
"./utils/**/*"
|
}
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"./src/**/__mocks__/**/*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
"./src/Bindings/ReactBindingHandler.ts",
|
"./src/Bindings/ReactBindingHandler.ts",
|
||||||
"./src/Common/ArrayHashMap.ts",
|
"./src/Common/ArrayHashMap.ts",
|
||||||
"./src/Common/CollapsedResourceTree.tsx",
|
"./src/Common/CollapsedResourceTree.tsx",
|
||||||
"./src/Common/Constants.ts",
|
|
||||||
"./src/Common/DeleteFeedback.ts",
|
"./src/Common/DeleteFeedback.ts",
|
||||||
"./src/Common/DocumentUtility.ts",
|
"./src/Common/DocumentUtility.ts",
|
||||||
"./src/Common/EnvironmentUtility.ts",
|
"./src/Common/EnvironmentUtility.ts",
|
||||||
|
|||||||
@@ -227,6 +227,7 @@ module.exports = function (_env = {}, argv = {}) {
|
|||||||
rules,
|
rules,
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
|
modules: [path.resolve(__dirname, "src"), "node_modules"],
|
||||||
alias: {
|
alias: {
|
||||||
process: "process/browser",
|
process: "process/browser",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user