Compare commits

..

78 Commits

Author SHA1 Message Date
Balaji Sridharan
5b0a98dce7 Removing TODO comments 2021-02-17 10:43:23 -08:00
Balaji Sridharan
67ebce444f Stylecop changes 2021-02-16 00:21:44 -08:00
Balaji Sridharan
a09bcc7197 Merge branch 'users/fnbalaji/PortalChangesForDGW' of https://github.com/Azure/cosmos-explorer into users/fnbalaji/PortalChangesForDGW 2021-02-15 23:49:54 -08:00
Balaji Sridharan
b2390e23e7 Portal changes for DedicatedGateway. CR feedback 2021-02-15 23:49:14 -08:00
fnbalaji
f922103e5c Merge branch 'master' into users/fnbalaji/PortalChangesForDGW 2021-02-15 23:39:50 -08:00
victor-meng
22d8a7a1be Move database settings tab to react (#386)
Co-authored-by: Steve Faulkner <southpolesteve@gmail.com>
2021-02-10 16:06:14 -06:00
victor-meng
4210e0752b Move delete collection confirmation pane to react (#417) 2021-02-10 13:44:00 -08:00
Steve Faulkner
b217d4be1b Delete Cassandra tables/keyspaces via ARM (#436) 2021-02-08 18:52:53 -06:00
victor-meng
81fd442fad Make getCollectionDataUsageSize call fail gracefully (#434) 2021-02-08 16:02:02 -08:00
Steve Faulkner
87f7dd2230 Rename Feedback -> Report Issue (#425)
Co-authored-by: victor-meng <56978073+victor-meng@users.noreply.github.com>
2021-02-08 14:23:55 -06:00
Srinath Narayanan
9926fd97a2 Test explorer changes (#420)
* Changes to publish pane

* fixed format errors

* fixed failing test

* added test explorer changes for mongo accounts

* added log for test

* fixed lit errors

* added secrets to ci.yml file

* fixed failing self serve test
2021-02-08 09:42:16 -08:00
Balaji Sridharan
faa98de9e9 Portal changes for DedicatedGateway
Changes to support creation and deletion of DedicatedGateway resource.

Tested locally with various scenarios.
2021-02-08 05:16:10 -08:00
Tanuj Mittal
2a7546e0de Skip SelfServe e2e test (#432) 2021-02-06 02:30:46 +05:30
Tanuj Mittal
4b442dd869 Use GET instead of PATCH for some Juno endpoints (#431) 2021-02-06 02:01:34 +05:30
Tanuj Mittal
f0b4737313 Update gallery colors (#430)
* Update gallery colors

* fix lint error

* Fix test
2021-02-06 01:19:36 +05:30
Srinath Narayanan
8dc5ed590a Added Spinner for public gallery (#427)
* Added more publish changes

* addressed PR comments

* fixed lint errors

Co-authored-by: Tanuj Mittal <tamitta@microsoft.com>
2021-02-05 11:32:26 -08:00
Tanuj Mittal
afaa844d28 Telemetry updates (#429) 2021-02-06 00:26:20 +05:30
Tanuj Mittal
3e5a876ef2 Fix setting isGalleryPublishEnabled when flight is enabled (#428) 2021-02-05 20:55:08 +05:30
Tanuj Mittal
51abf1560a Disable dark overlay for Dialog (#423) 2021-02-05 19:28:57 +05:30
Srinath Narayanan
1c0fed88c0 Changes to cards in notebook gallery (#422)
* added gallery changes

* addressed PR comments
2021-02-05 02:32:55 -08:00
Tanuj Mittal
93cfd52e36 Update Code of Conduct Overlay and other minor changes (#424)
* Use light theme for coc-overlay

* Updates

* Fix vertical height for COC overlay
2021-02-05 14:56:50 +05:30
Tanuj Mittal
3fd014ddad Disable caching for config.json file (#421)
* Disable caching for config.json file

* Disable cache when fetching config.json
2021-02-04 15:25:13 +05:30
Srinath Narayanan
3b6fda4fa5 Changes to notebook publish pane (#419)
* Changes to publish pane

* fixed format errors

* fixed failing test

Co-authored-by: Tanuj Mittal <tamitta@microsoft.com>
2021-02-03 10:46:51 -08:00
Tanuj Mittal
db7c45c9b8 Enable gallery publishing in MPAC (#416)
* Enable gallery publishing in MPAC

* Address feedback

* Use ENABLE_GALLERY_PUBLISH config in standalone gallery

* Fix test
2021-02-03 23:42:11 +05:30
Tanuj Mittal
4f6b75fe79 More gallery updates (#418)
* More gallery updates

* Add PublishContent icon

* Address feedback
2021-02-03 23:24:27 +05:30
Tanuj Mittal
5038a01079 Add telemetry for Notebooks Gallery and other updates (#413)
* Add telemetry for Notebooks Gallery

* More changes

* Address feedback and fix lint error

* Fix margins for My published work
2021-02-03 14:48:50 +05:30
Tanuj Mittal
e0063c76d9 Add support for gallerypublish flight (#412) 2021-02-03 02:05:19 +05:30
Tanuj Mittal
9278654479 Public gallery improvements (#409)
- [x] Don't show extension in name field for publish
- [x] Open "Your published work" tab after publishing
- [x] Continue showing dialog for Report Abuse status
- [x] For showing COC in Public Gallery tab show backdrop of thumbnails
- [x] Liked -> My Favorites & Your published work -> My published work
2021-01-29 17:04:38 +00:00
Tanuj Mittal
59113d7bbf Update Juno endpoints (#405) 2021-01-29 20:28:20 +05:30
Tim Sander
88d8200c14 Check that customer is using Mongo 3.6 before applying index everything policy (#410) 2021-01-28 15:26:47 -06:00
Srinath Narayanan
6aaddd9c60 Added localization for the Self Serve Model (#406)
* added localization for selfserve model

* added comment

* addressed PR comments

* fixed format errors

* Addressed PR comments
2021-01-28 11:17:02 -08:00
Jordi Bunster
f8ede0cc1e Remove Q from ViewModels (#390)
I got cold feet at the thought of merging #324 in one go, so I'm going to split it into smaller chunks and keep rebasing the large one until there's no more Q.
2021-01-28 18:13:26 +00:00
Laurent Nguyen
bddb288a89 Update package versions and package-lock.json (#404)
The file `package-lock.json` is not in sync with `package.json` anymore. This causes build issues when upgrading a package.
This change sync's `package-lock.json` and fixes the build issues.
2021-01-28 08:50:24 +00:00
Steve Faulkner
a14d20a88e Fix applyExplorerBindings call in Portal (#408) 2021-01-27 20:37:14 -06:00
Steve Faulkner
f1db1ed978 Region Select Button (#407) 2021-01-27 15:32:53 -06:00
Laurent Nguyen
86a483c3a4 Fix notebook cell selection bug (#402)
This fixes a bug that prevents getting focus to a text cell (effectively preventing editing) when the window height is small after double-clicking on a neighboring code cell.
The issue is that selecting a text cell is broken likely because there's a behavior change in MonacoEditor that keeps the focus on the code cell. The selection issue will probably be resolved when migrating the text cell to Monaco (which will acquire and keep focus the same way), but for now, this will disable the faulty code which doesn't appear to work anymore (presumably auto-scrolling to the cell).
2021-01-27 09:09:54 +00:00
Tanuj Mittal
263262a040 Update Juno endpoints to pass subscriptionId (#339)
Corresponding [server side change](https://msdata.visualstudio.com/CosmosDB/_git/CosmosDB-portal/pullrequest/464443?_a=overview) has been deployed to Prod so now we can go ahead with DE side changes.
2021-01-27 08:08:58 +00:00
victor-meng
bd4d8da065 Move notification console to react (#400) 2021-01-26 15:32:37 -08:00
Steve Faulkner
59ec18cd9b Add basic static code metrics (#396) 2021-01-26 13:13:13 -06:00
Srinath Narayanan
49bf8c60db Added more Self Serve functionalities (#401)
* added recursion and inition decorators

* working version

* added todo comment and removed console.log

* Added Recursive add

* removed type requirement

* proper resolution of promises

* added custom element and base class

* Made selfServe standalone page

* Added custom renderer as async type

* Added overall defaults

* added inital open from data explorer

* removed landingpage

* added feature for self serve type

* renamed sqlx->example and added invalid type

* Added comments for Example

* removed unnecessary changes

* Resolved PR comments

Added tests
Moved onSubmt and initialize inside base class
Moved testExplorer to separate folder
made fields of SelfServe Class non static

* fixed lint errors

* fixed compilation errors

* Removed reactbinding changes

* renamed dropdown -> choice

* Added SelfServeComponent

* Addressed PR comments

* added toggle, visibility, text display,commandbar

* added sqlx example

* added onRefrssh

* formatting changes

* rmoved radioswitch display

* updated smartui tests

* Added more tests

* onSubmit -> onSave

* Resolved PR comments
2021-01-26 09:44:14 -08:00
Steve Faulkner
b0b973b21a Refactor explorer config into useKnockoutExplorer hook (#397)
Co-authored-by: Steve Faulkner <stfaul@microsoft.com>
2021-01-25 13:56:15 -06:00
Chris-MS-896
3529e80f0d no message (#398) 2021-01-22 10:02:35 -06:00
Srinath Narayanan
a298fd8389 Added message to indicate compound indexes are not supported in Mongo Index editor (#395)
* mongo message

* Added test and bug fix in Main.tsx

* format changes

* added new formatting

* added null check
2021-01-21 10:56:05 -08:00
Steve Faulkner
1ecc467f60 Remove IE nuget (#394) 2021-01-20 12:46:12 -06:00
Steve Faulkner
b3cafe3468 Add telemetry to Spark+Synapse Pools (#392) 2021-01-20 11:08:29 -06:00
Steve Faulkner
4be53284b5 Prettier 2.0 (#393) 2021-01-20 09:15:01 -06:00
Srinath Narayanan
c1937ca464 Added the Self Serve Data Model (#367)
* added recursion and inition decorators

* working version

* added todo comment and removed console.log

* Added Recursive add

* removed type requirement

* proper resolution of promises

* added custom element and base class

* Made selfServe standalone page

* Added custom renderer as async type

* Added overall defaults

* added inital open from data explorer

* removed landingpage

* added feature for self serve type

* renamed sqlx->example and added invalid type

* Added comments for Example

* removed unnecessary changes

* Resolved PR comments

Added tests
Moved onSubmt and initialize inside base class
Moved testExplorer to separate folder
made fields of SelfServe Class non static

* fixed lint errors

* fixed compilation errors

* Removed reactbinding changes

* renamed dropdown -> choice

* Added SelfServeComponent

* Addressed PR comments

* merged master

* added selfservetype.none for emulator and hosted experience

* fixed formatting errors

* Removed "any" type

* undid package.json changes
2021-01-19 22:42:45 -08:00
Steve Faulkner
2b2de7c645 Migrated Hosted Explorer to React (#360)
Co-authored-by: Victor Meng <vimeng@microsoft.com>
Co-authored-by: Steve Faulkner <stfaul@microsoft.com>
2021-01-19 16:31:55 -06:00
Deborah Chen
8c40df0fa1 Adding in experimentation for autoscale test (#345)
* Adding autoscale flight info

* Add flight info to cassandra collection pane

* Add telemetry for autoscale toggle on/off in create resource blade and scale/settings

* Run formatting and add expected properties to test file

* removing empty line

* Updating to pass unit tests

Co-authored-by: Steve Faulkner <southpolesteve@gmail.com>
2021-01-15 17:15:15 -06:00
Steve Faulkner
fcbc9474ea Remove Preview for Synapse Link (#389) 2021-01-15 09:51:14 -06:00
Steve Faulkner
81f861af39 Empty commit to refresh nuget after transient failures 2021-01-14 17:37:24 -06:00
victor-meng
9afa29cdb6 Properly construct the query to delete Cassandra row (#388) 2021-01-14 16:59:31 -06:00
Chris-MS-896
9a1e8b2d87 Add rest of three utils files to Matser (#370)
* 'minor change'
2021-01-13 17:49:06 -06:00
Tim Sander
babda4d9cb fix issue where Mongo indexing checkbox stops adding wildcard index (#384) 2021-01-12 18:38:16 -06:00
Steve Faulkner
9d20a13dd4 Warn on SubQuery (#378) 2021-01-12 13:53:15 -06:00
Chris-MS-896
3effbe6991 no message (#372) 2021-01-12 13:09:20 -06:00
Chris-MS-896
af53697ff4 Add file of Terminal to Master (#371)
* "minor changes"
2021-01-12 12:55:47 -06:00
Chris-MS-896
b1ad80480e Add two files of notebook component in Matser (#363)
* “minor changes”
2021-01-12 12:55:21 -06:00
Armando Trejo Oliver
9247a6c4a2 A11y fixes - Add a skip link and remove duplicate ids (#381)
* Add a skip link to allow people who navigate sequentially through content more direct access to the primary content of the Data Explorer

Co-authored-by: Chris Cao (Zen3 Infosolutions America Inc) <v-yiqcao@microsoft.com>

* Rename id of partition key field in  Add Collection Pane to ensure no  elements contain duplicate attributes.

Co-authored-by: Chris Cao (Zen3 Infosolutions America Inc) <v-yiqcao@microsoft.com>
2021-01-12 09:55:04 -08:00
Steve Faulkner
767d46480e Revert TablesEntitiyListViewModel changes (#382) 2021-01-11 16:16:40 -06:00
Chris-MS-896
2d98c5d269 add ArraysByKeyCache.ts (#366)
* 'add ArraysByKeyCache'
* "minor change"
2021-01-08 22:51:50 -06:00
Steve Faulkner
6627172a52 Add Architecture Diagram to README (#380) 2021-01-08 22:20:40 -06:00
Steve Faulkner
19fa5e17a5 Fix JSONEditor bug with undefined value (#379) 2021-01-08 22:20:06 -06:00
Chris-MS-896
a4a367a212 Add all arm request related files to Matser (#373)
* “minor changes”
* 'changes for unit test'
2021-01-08 21:56:29 -06:00
Chris-MS-896
983c9201bb Add two files of GraphExplorer component in Master (#365) 2021-01-08 21:14:53 -06:00
Chris-MS-896
76d7f00a90 Add two files of Table to master (#364) 2021-01-08 20:56:59 -06:00
Chris-MS-896
6490597736 add CollapsiblePanel/CollapsiblePanelComponent.ts and /ErrorDisplayComponent to Master (#357) 2021-01-08 20:29:15 -06:00
Chris-MS-896
229119e697 add file offerUtility to tsconfig (#356) 2021-01-08 20:14:12 -06:00
Steve Faulkner
ceefd7c615 Fix Conflict Resolution path setting (#377)
* Fix Conflict Resolution path setting

* Fix test
2021-01-08 12:36:44 -06:00
Laurent Nguyen
6e619175c6 Fix missing scrollbar in left pane when too many collections/notebooks (#375)
Constrain left pane container to height: 100% so that scrollbar show up when content wants to overflow.
The `main` classname seems too generic, but I left it alone (so I don't break anything), since this part will eventually be ported to React.
2021-01-08 14:00:26 +00:00
victor-meng
08e8bf4bcf Fix two settings tab issues (#374) 2021-01-07 15:38:13 -06:00
Chris-MS-896
89dc0f394b Add Spliter file to Master (#358) 2021-01-06 12:51:42 -06:00
Chris-MS-896
30e0001b7f no message (#359) 2021-01-05 16:45:13 -06:00
Steve Faulkner
4a8f408112 Add UX for Mongo indexing experiment (#368)
Co-authored-by: Tim Sander <tisande@microsoft.com>
2021-01-05 16:04:55 -06:00
Armando Trejo Oliver
e801364800 Remove stale .main class from tree.less (#362)
.main CSS class has a naming conflict with Moncao editor CSS classes and this is causing  A11y issues with Moncao editor.

This class should no longer be used since we moved to the new tree component in REACT, so I am removing it. From my testing, this is not affecting anything.

If we find any styling issue later, we should fix without adding back this class.
2021-01-05 10:53:55 -08:00
victor-meng
a55f2d0de9 Free tier improvements in DE (#348)
Co-authored-by: Steve Faulkner <southpolesteve@gmail.com>
2021-01-04 12:56:55 -08:00
Steve Faulkner
d40b1aa9b5 Remove Empty Query Logging (#361) 2021-01-04 13:58:01 -06:00
Steve Faulkner
cc63cdc1fd Remove dependency on canvas (#354) 2020-12-26 21:56:37 -06:00
590 changed files with 57019 additions and 51131 deletions

View File

@@ -87,7 +87,7 @@ 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/Explorer.ts src/Explorer/Explorer.tsx
src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.test.ts src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.test.ts
src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.ts src/Explorer/Graph/GraphExplorerComponent/ArraysByKeyCache.ts
src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.test.ts src/Explorer/Graph/GraphExplorerComponent/D3ForceGraph.test.ts
@@ -241,9 +241,6 @@ src/Platform/Hosted/Authorization.ts
src/Platform/Hosted/DataAccessUtility.ts src/Platform/Hosted/DataAccessUtility.ts
src/Platform/Hosted/ExplorerFactory.ts src/Platform/Hosted/ExplorerFactory.ts
src/Platform/Hosted/Helpers/ConnectionStringParser.test.ts src/Platform/Hosted/Helpers/ConnectionStringParser.test.ts
src/Platform/Hosted/Helpers/ConnectionStringParser.ts
src/Platform/Hosted/HostedUtils.test.ts
src/Platform/Hosted/HostedUtils.ts
src/Platform/Hosted/Main.ts src/Platform/Hosted/Main.ts
src/Platform/Hosted/Maint.test.ts src/Platform/Hosted/Maint.test.ts
src/Platform/Hosted/NotificationsClient.ts src/Platform/Hosted/NotificationsClient.ts

View File

@@ -1,41 +1,39 @@
module.exports = { module.exports = {
env: { env: {
browser: true, browser: true,
es6: true es6: true,
}, },
plugins: ["@typescript-eslint", "no-null", "prefer-arrow"], plugins: ["@typescript-eslint", "no-null", "prefer-arrow"],
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
globals: { globals: {
Atomics: "readonly", Atomics: "readonly",
SharedArrayBuffer: "readonly" SharedArrayBuffer: "readonly",
}, },
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
parserOptions: { parserOptions: {
ecmaFeatures: { ecmaFeatures: {
jsx: true jsx: true,
}, },
ecmaVersion: 2018, ecmaVersion: 2018,
sourceType: "module" sourceType: "module",
}, },
overrides: [ overrides: [
{ {
files: ["**/*.tsx"], files: ["**/*.tsx"],
env: { extends: ["plugin:react/recommended"], // TODO: Add react-hooks
jest: true plugins: ["react"],
},
extends: ["plugin:react/recommended"],
plugins: ["react"]
}, },
{ {
files: ["**/*.{test,spec}.{ts,tsx}"], files: ["**/*.{test,spec}.{ts,tsx}"],
env: { env: {
jest: true jest: true,
}, },
extends: ["plugin:jest/recommended"], extends: ["plugin:jest/recommended"],
plugins: ["jest"] plugins: ["jest"],
} },
], ],
rules: { rules: {
"no-console": ["error", { allow: ["error", "warn", "dir"] }],
curly: "error", curly: "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",
@@ -43,12 +41,13 @@ module.exports = {
"@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",
"react/display-name": "off",
"no-restricted-syntax": [ "no-restricted-syntax": [
"error", "error",
{ {
selector: "CallExpression[callee.object.name='JSON'][callee.property.name='stringify'] Identifier[name=/$err/]", selector: "CallExpression[callee.object.name='JSON'][callee.property.name='stringify'] Identifier[name=/$err/]",
message: "Do not use JSON.stringify(error). It will print '{}'" message: "Do not use JSON.stringify(error). It will print '{}'",
} },
] ],
} },
}; };

View File

@@ -9,6 +9,20 @@ on:
branches: branches:
- master - master
jobs: jobs:
codemetrics:
runs-on: ubuntu-latest
name: "Log Code Metrics"
if: github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v2
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x
- run: npm ci
- run: node utils/codeMetrics.js
env:
CODE_METRICS_APP_ID: ${{ secrets.CODE_METRICS_APP_ID }}
compile: compile:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: "Compile TypeScript" name: "Compile TypeScript"
@@ -94,7 +108,7 @@ jobs:
npm ci npm ci
npm start & npm start &
npm run wait-for-server npm run wait-for-server
npx jest -c ./jest.config.e2e.js --detectOpenHandles sql npx jest -c ./jest.config.e2e.js --detectOpenHandles test/sql/container.spec.ts
shell: bash shell: bash
env: env:
DATA_EXPLORER_ENDPOINT: "https://localhost:1234/explorer.html?platform=Emulator" DATA_EXPLORER_ENDPOINT: "https://localhost:1234/explorer.html?platform=Emulator"
@@ -142,6 +156,7 @@ jobs:
run: | run: |
npm ci npm ci
npm start & npm start &
node utils/cleanupDBs.js
npm run wait-for-server npm run wait-for-server
npm run test:e2e npm run test:e2e
shell: bash shell: bash
@@ -151,6 +166,8 @@ jobs:
PORTAL_RUNNER_RESOURCE_GROUP: ${{ secrets.PORTAL_RUNNER_RESOURCE_GROUP }} PORTAL_RUNNER_RESOURCE_GROUP: ${{ secrets.PORTAL_RUNNER_RESOURCE_GROUP }}
PORTAL_RUNNER_DATABASE_ACCOUNT: ${{ secrets.PORTAL_RUNNER_DATABASE_ACCOUNT }} PORTAL_RUNNER_DATABASE_ACCOUNT: ${{ secrets.PORTAL_RUNNER_DATABASE_ACCOUNT }}
PORTAL_RUNNER_DATABASE_ACCOUNT_KEY: ${{ secrets.PORTAL_RUNNER_DATABASE_ACCOUNT_KEY }} PORTAL_RUNNER_DATABASE_ACCOUNT_KEY: ${{ secrets.PORTAL_RUNNER_DATABASE_ACCOUNT_KEY }}
PORTAL_RUNNER_MONGO_DATABASE_ACCOUNT: ${{ secrets.PORTAL_RUNNER_MONGO_DATABASE_ACCOUNT }}
PORTAL_RUNNER_MONGO_DATABASE_ACCOUNT_KEY: ${{ secrets.PORTAL_RUNNER_MONGO_DATABASE_ACCOUNT_KEY }}
NOTEBOOKS_TEST_RUNNER_TENANT_ID: ${{ secrets.NOTEBOOKS_TEST_RUNNER_TENANT_ID }} NOTEBOOKS_TEST_RUNNER_TENANT_ID: ${{ secrets.NOTEBOOKS_TEST_RUNNER_TENANT_ID }}
NOTEBOOKS_TEST_RUNNER_CLIENT_ID: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_ID }} NOTEBOOKS_TEST_RUNNER_CLIENT_ID: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_ID }}
NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET }} NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET }}
@@ -213,28 +230,3 @@ jobs:
name: packages name: packages
with: with:
path: "*.nupkg" path: "*.nupkg"
nugetie:
name: Publish Nuget IE
if: github.ref == 'refs/heads/master' || contains(github.ref, 'hotfix/') || contains(github.ref, 'release/')
needs: [lint, format, compile, build, unittest, endtoendemulator, endtoendhosted, accessibility]
runs-on: ubuntu-latest
env:
NUGET_SOURCE: ${{ secrets.NUGET_SOURCE }}
AZURE_DEVOPS_PAT: ${{ secrets.AZURE_DEVOPS_PAT }}
steps:
- uses: nuget/setup-nuget@v1
with:
nuget-api-key: ${{ secrets.NUGET_API_KEY }}
- name: Download Dist Folder
uses: actions/download-artifact@v2
with:
name: dist
- run: cp ./configs/prod.json config.json
- run: sed -i 's/Azure.Cosmos.DB.Data.Explorer/Azure.Cosmos.DB.Data.Explorer.IE/g' DataExplorer.nuspec
- run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "GitHub" -Password "$AZURE_DEVOPS_PAT"
- run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}"
- run: nuget push -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg
- uses: actions/upload-artifact@v2
name: packages
with:
path: "*.nupkg"

View File

@@ -69,6 +69,10 @@ Jest and Puppeteer are used for end to end browser based tests and are contained
We generally adhere to the release strategy [documented by the Azure SDK Guidelines](https://azure.github.io/azure-sdk/policies_repobranching.html#release-branches). Most releases should happen from the master branch. If master contains commits that cannot be released, you may create a release from a `release/` or `hotfix/` branch. See linked documentation for more details. We generally adhere to the release strategy [documented by the Azure SDK Guidelines](https://azure.github.io/azure-sdk/policies_repobranching.html#release-branches). Most releases should happen from the master branch. If master contains commits that cannot be released, you may create a release from a `release/` or `hotfix/` branch. See linked documentation for more details.
### Architechture
[![](https://mermaid.ink/img/eyJjb2RlIjoiZ3JhcGggTFJcbiAgaG9zdGVkKGh0dHBzOi8vY29zbW9zLmF6dXJlLmNvbSlcbiAgcG9ydGFsKFBvcnRhbClcbiAgZW11bGF0b3IoRW11bGF0b3IpXG4gIGFhZFtBQURdXG4gIHJlc291cmNlVG9rZW5bUmVzb3VyY2UgVG9rZW5dXG4gIGNvbm5lY3Rpb25TdHJpbmdbQ29ubmVjdGlvbiBTdHJpbmddXG4gIHBvcnRhbFRva2VuW0VuY3J5cHRlZCBQb3J0YWwgVG9rZW5dXG4gIG1hc3RlcktleVtNYXN0ZXIgS2V5XVxuICBhcm1bQVJNIFJlc291cmNlIFByb3ZpZGVyXVxuICBkYXRhcGxhbmVbRGF0YSBQbGFuZV1cbiAgcHJveHlbUG9ydGFsIEFQSSBQcm94eV1cbiAgc3FsW1NRTF1cbiAgbW9uZ29bTW9uZ29dXG4gIHRhYmxlc1tUYWJsZXNdXG4gIGNhc3NhbmRyYVtDYXNzYW5kcmFdXG4gIGdyYWZbR3JhcGhdXG5cblxuICBlbXVsYXRvciAtLT4gbWFzdGVyS2V5IC0tLS0-IGRhdGFwbGFuZVxuICBwb3J0YWwgLS0-IGFhZFxuICBob3N0ZWQgLS0-IHBvcnRhbFRva2VuICYgcmVzb3VyY2VUb2tlbiAmIGNvbm5lY3Rpb25TdHJpbmcgJiBhYWRcbiAgYWFkIC0tLT4gYXJtXG4gIGFhZCAtLS0-IGRhdGFwbGFuZVxuICBhYWQgLS0tPiBwcm94eVxuICByZXNvdXJjZVRva2VuIC0tLT4gc3FsIC0tPiBkYXRhcGxhbmVcbiAgcG9ydGFsVG9rZW4gLS0tPiBwcm94eVxuICBwcm94eSAtLT4gZGF0YXBsYW5lXG4gIGNvbm5lY3Rpb25TdHJpbmcgLS0-IHNxbCAmIG1vbmdvICYgY2Fzc2FuZHJhICYgZ3JhZiAmIHRhYmxlc1xuICBzcWwgLS0-IGRhdGFwbGFuZVxuICB0YWJsZXMgLS0-IGRhdGFwbGFuZVxuICBtb25nbyAtLT4gcHJveHlcbiAgY2Fzc2FuZHJhIC0tPiBwcm94eVxuICBncmFmIC0tPiBwcm94eVxuXG5cdFx0IiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifSwidXBkYXRlRWRpdG9yIjpmYWxzZX0)](https://mermaid-js.github.io/mermaid-live-editor/#/edit/eyJjb2RlIjoiZ3JhcGggTFJcbiAgaG9zdGVkKGh0dHBzOi8vY29zbW9zLmF6dXJlLmNvbSlcbiAgcG9ydGFsKFBvcnRhbClcbiAgZW11bGF0b3IoRW11bGF0b3IpXG4gIGFhZFtBQURdXG4gIHJlc291cmNlVG9rZW5bUmVzb3VyY2UgVG9rZW5dXG4gIGNvbm5lY3Rpb25TdHJpbmdbQ29ubmVjdGlvbiBTdHJpbmddXG4gIHBvcnRhbFRva2VuW0VuY3J5cHRlZCBQb3J0YWwgVG9rZW5dXG4gIG1hc3RlcktleVtNYXN0ZXIgS2V5XVxuICBhcm1bQVJNIFJlc291cmNlIFByb3ZpZGVyXVxuICBkYXRhcGxhbmVbRGF0YSBQbGFuZV1cbiAgcHJveHlbUG9ydGFsIEFQSSBQcm94eV1cbiAgc3FsW1NRTF1cbiAgbW9uZ29bTW9uZ29dXG4gIHRhYmxlc1tUYWJsZXNdXG4gIGNhc3NhbmRyYVtDYXNzYW5kcmFdXG4gIGdyYWZbR3JhcGhdXG5cblxuICBlbXVsYXRvciAtLT4gbWFzdGVyS2V5IC0tLS0-IGRhdGFwbGFuZVxuICBwb3J0YWwgLS0-IGFhZFxuICBob3N0ZWQgLS0-IHBvcnRhbFRva2VuICYgcmVzb3VyY2VUb2tlbiAmIGNvbm5lY3Rpb25TdHJpbmcgJiBhYWRcbiAgYWFkIC0tLT4gYXJtXG4gIGFhZCAtLS0-IGRhdGFwbGFuZVxuICBhYWQgLS0tPiBwcm94eVxuICByZXNvdXJjZVRva2VuIC0tLT4gc3FsIC0tPiBkYXRhcGxhbmVcbiAgcG9ydGFsVG9rZW4gLS0tPiBwcm94eVxuICBwcm94eSAtLT4gZGF0YXBsYW5lXG4gIGNvbm5lY3Rpb25TdHJpbmcgLS0-IHNxbCAmIG1vbmdvICYgY2Fzc2FuZHJhICYgZ3JhZiAmIHRhYmxlc1xuICBzcWwgLS0-IGRhdGFwbGFuZVxuICB0YWJsZXMgLS0-IGRhdGFwbGFuZVxuICBtb25nbyAtLT4gcHJveHlcbiAgY2Fzc2FuZHJhIC0tPiBwcm94eVxuICBncmFmIC0tPiBwcm94eVxuXG5cdFx0IiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifSwidXBkYXRlRWRpdG9yIjpmYWxzZX0)
# Contributing # Contributing
Please read the [contribution guidelines](./CONTRIBUTING.md). Please read the [contribution guidelines](./CONTRIBUTING.md).

View File

@@ -1,3 +1,4 @@
module.exports = { module.exports = {
presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-react", "@babel/preset-typescript"] presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-react", "@babel/preset-typescript"],
plugins: [["@babel/plugin-proposal-decorators", { legacy: true }]],
}; };

7
canvas/README.md Normal file
View File

@@ -0,0 +1,7 @@
# Why?
This adds a mock module for `canvas`. Nteract has a ignored require and undeclared dependency on this module. `cavnas` is a server side node module and is not used in browser side code for nteract.
Installing it locally (`npm install canvas`) will resolve the problem, but it is a native module so it is flaky depending on the system, node version, processor arch, etc. This module provides a simpler, more robust solution.
Remove this workaround if [this bug](https://github.com/nteract/any-vega/issues/2) ever gets resolved

1
canvas/index.js Normal file
View File

@@ -0,0 +1 @@
module.exports = {}

11
canvas/package.json Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "canvas",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

View File

@@ -1,3 +1,4 @@
{ {
"JUNO_ENDPOINT": "https://tools-staging.cosmos.azure.com" "JUNO_ENDPOINT": "https://tools-staging.cosmos.azure.com",
"ENABLE_GALLERY_PUBLISH": true
} }

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.31449 2.01439L4.00103 5.31963L3.26105 4.57965L7.8407 0L12.4203 4.57965L11.6804 5.31963L8.36691 2.01439V12.8428H7.31449V2.01439ZM13.629 12.8428H14.6814V16H1V12.8428H2.05242V14.9476H13.629V12.8428Z" fill="#0078D4"/>
</svg>

After

Width:  |  Height:  |  Size: 329 B

View File

@@ -6,6 +6,6 @@ module.exports = {
slowMo: 55, slowMo: 55,
defaultViewport: null, defaultViewport: null,
ignoreHTTPSErrors: true, ignoreHTTPSErrors: true,
args: ["--disable-web-security"] args: ["--disable-web-security"],
} },
}; };

View File

@@ -1,5 +1,5 @@
module.exports = { module.exports = {
preset: "jest-puppeteer", preset: "jest-puppeteer",
testMatch: ["<rootDir>/test/**/*.spec.[jt]s?(x)"], testMatch: ["<rootDir>/test/**/*.spec.[jt]s?(x)"],
setupFiles: ["dotenv/config"] setupFiles: ["dotenv/config"],
}; };

View File

@@ -39,11 +39,11 @@ module.exports = {
// An object that configures minimum threshold enforcement for coverage results // An object that configures minimum threshold enforcement for coverage results
coverageThreshold: { coverageThreshold: {
global: { global: {
branches: 20, branches: 22,
functions: 24, functions: 28,
lines: 30, lines: 33,
statements: 29.0 statements: 31,
} },
}, },
// Make calling deprecated APIs throw helpful error messages // Make calling deprecated APIs throw helpful error messages
@@ -76,7 +76,7 @@ module.exports = {
"office-ui-fabric-react/lib/(.*)$": "office-ui-fabric-react/lib-commonjs/$1", // https://github.com/OfficeDev/office-ui-fabric-react/wiki/Fabric-6-Release-Notes "office-ui-fabric-react/lib/(.*)$": "office-ui-fabric-react/lib-commonjs/$1", // https://github.com/OfficeDev/office-ui-fabric-react/wiki/Fabric-6-Release-Notes
"^dnd-core$": "dnd-core/dist/cjs", "^dnd-core$": "dnd-core/dist/cjs",
"^react-dnd$": "react-dnd/dist/cjs", "^react-dnd$": "react-dnd/dist/cjs",
"^react-dnd-html5-backend$": "react-dnd-html5-backend/dist/cjs" "^react-dnd-html5-backend$": "react-dnd-html5-backend/dist/cjs",
}, },
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
@@ -164,11 +164,11 @@ module.exports = {
// A map from regular expressions to paths to transformers // A map from regular expressions to paths to transformers
transform: { transform: {
"^.+\\.html?$": "html-loader-jest", "^.+\\.html?$": "html-loader-jest",
"^.+\\.[t|j]sx?$": "babel-jest" "^.+\\.[t|j]sx?$": "babel-jest",
}, },
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
transformIgnorePatterns: ["/node_modules/", "/externals/"] transformIgnorePatterns: ["/node_modules/", "/externals/"],
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined, // unmockedModulePathPatterns: undefined,

View File

@@ -3,8 +3,8 @@
/******************************************************************************/ /******************************************************************************/
@font-face { @font-face {
font-family: wf_segoe-ui_normal; font-family: wf_segoe-ui_normal;
src: url('../../fonts/segoe-ui/west-european/normal/latest.woff'); src: url("../../fonts/segoe-ui/west-european/normal/latest.woff");
} }
@DataExplorerFont: wf_segoe-ui_normal, "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif; @DataExplorerFont: wf_segoe-ui_normal, "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif;
@@ -20,26 +20,26 @@
COLORS COLORS
/******************************************************************************/ /******************************************************************************/
@AccentMediumHigh: #0058AD; @AccentMediumHigh: #0058ad;
@AccentMedium: #004E87; @AccentMedium: #004e87;
@AccentHigh: #1EBAED; @AccentHigh: #1ebaed;
@AccentExtraHigh: #55B3FF; @AccentExtraHigh: #55b3ff;
@AccentLow: #EDF6FF; @AccentLow: #edf6ff;
@AccentMediumLow: #DDEEFE; @AccentMediumLow: #ddeefe;
@AccentLight: #EEF7FF; @AccentLight: #eef7ff;
@AccentExtra: #DDF0FF; @AccentExtra: #ddf0ff;
@SelectionHigh: #B91F26; @SelectionHigh: #b91f26;
@BaseLight: #FFFFFF; @BaseLight: #ffffff;
@BaseDark: #000000; @BaseDark: #000000;
@NotificationLow: #FFF4CE; @NotificationLow: #fff4ce;
@NotificationHigh: #F9E9B0; @NotificationHigh: #f9e9b0;
@Purple1: #8A2DA5; @Purple1: #8a2da5;
@Dirty: #9b4f96; @Dirty: #9b4f96;
@BaseLow: #F2F2F2; @BaseLow: #f2f2f2;
@BaseMediumLow: #E6E6E6; @BaseMediumLow: #e6e6e6;
@BaseMedium: #CCCCCC; @BaseMedium: #cccccc;
@BaseMediumHigh: #767676; @BaseMediumHigh: #767676;
@BaseHigh: #393939; @BaseHigh: #393939;
@@ -53,10 +53,17 @@
@ErrorColor: @SelectionHigh; @ErrorColor: @SelectionHigh;
@SelectionColor: #3074B0; @SelectionColor: #3074b0;
@FocusColor: #605e5c; @FocusColor: #605e5c;
@GalleryBackgroundColor: #fdfdfd;
//Icons
@InfoIconColor: #0072c6;
@WarningIconColor: #db7500;
@ErrorIconColor: #b91f26;
/****************************************************************************** /******************************************************************************
METRICS METRICS
/******************************************************************************/ /******************************************************************************/
@@ -80,7 +87,7 @@
@ImgWidth: 14px; @ImgWidth: 14px;
@ImgHeight: 14px; @ImgHeight: 14px;
@toggleFontWeight:700; @toggleFontWeight: 700;
//Resource Tree //Resource Tree
@TreeLineHeight: 17px; @TreeLineHeight: 17px;
@@ -144,16 +151,16 @@
/**********************************************************************************/ /**********************************************************************************/
.flex-display(@display: flex) { .flex-display(@display: flex) {
display: ~"-webkit-@{display}"; display: ~"-webkit-@{display}";
display: ~"-ms-@{display}box"; // IE10 uses -ms-flexbox display: ~"-ms-@{display}box"; // IE10 uses -ms-flexbox
display: ~"-ms-@{display}"; // IE11 display: ~"-ms-@{display}"; // IE11
display: @display; display: @display;
} }
.flex-direction(@direction: column) { .flex-direction(@direction: column) {
-webkit-flex-direction: @direction; -webkit-flex-direction: @direction;
-ms-flex-direction: @direction; -ms-flex-direction: @direction;
flex-direction: @direction; flex-direction: @direction;
} }
/************************************************************************************* /*************************************************************************************
@@ -161,32 +168,31 @@
**************************************************************************************/ **************************************************************************************/
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
.selectedRadio, .selectedRadio,
.selectedRadio:hover, .selectedRadio:hover,
.selectedRadio:active, .selectedRadio:active,
.selectedRadio.dirty, .selectedRadio.dirty,
.tab [type=radio]:checked ~ label, .tab [type="radio"]:checked ~ label,
.tab [type=radio]:checked ~ label:hover { .tab [type="radio"]:checked ~ label:hover {
-ms-high-contrast-adjust: none; -ms-high-contrast-adjust: none;
-webkit-text-fill-color: HighlightText; -webkit-text-fill-color: HighlightText;
color: HighlightText; color: HighlightText;
border-color: HighlightText; border-color: HighlightText;
background-color: Highlight; background-color: Highlight;
} }
.queryMetricsSummaryTuple { .queryMetricsSummaryTuple {
th,
th, td { td {
&:nth-child(2) {
&:nth-child(2) { width: @IETableDataWidth;
width: @IETableDataWidth; }
}
&:nth-child(3) {
&:nth-child(3) { width: 50%;
width: 50%; }
}
}
} }
}
} }
/******************************************************************************************** /********************************************************************************************
@@ -194,15 +200,15 @@
*********************************************************************************************/ *********************************************************************************************/
.hover() { .hover() {
background-color: @AccentLight; background-color: @AccentLight;
} }
.active() { .active() {
background-color: @AccentExtra; background-color: @AccentExtra;
} }
.focus() { .focus() {
outline: 1px dashed @FocusColor; outline: 1px dashed @FocusColor;
} }
/************************************************************************************************ /************************************************************************************************
@@ -212,63 +218,87 @@
@ToggleWidth: 180px; @ToggleWidth: 180px;
.toggleSwitch() { .toggleSwitch() {
max-width: 100%; max-width: 100%;
margin-bottom: @SmallSpace; margin-bottom: @SmallSpace;
padding: @SmallSpace; padding: @SmallSpace;
cursor: pointer; cursor: pointer;
color: @BaseHigh; color: @BaseHigh;
font-weight: 400; font-weight: 400;
font-size: @mediumFontSize; font-size: @mediumFontSize;
font-family: @DataExplorerFont; font-family: @DataExplorerFont;
} }
.selectedToggle() { .selectedToggle() {
border-bottom: 2px solid @BaseHigh; border-bottom: 2px solid @BaseHigh;
} }
.unselectedToggle() { .unselectedToggle() {
color: @AccentMediumHigh; color: @AccentMediumHigh;
} }
/******************************************************************************************************** /********************************************************************************************************
Common Data Explorer Icons Common Data Explorer Icons
*********************************************************************************************************/ *********************************************************************************************************/
.dataExplorerIcons() { .dataExplorerIcons() {
cursor: pointer; cursor: pointer;
width: @ImgWidth; width: @ImgWidth;
height: @ImgHeight; height: @ImgHeight;
} }
/********************************************************************************************************* /*********************************************************************************************************
Info Tooltip Info Tooltip
**********************************************************************************************************/ **********************************************************************************************************/
.infoTooltip() { .infoTooltip() {
position: relative; position: relative;
display: inline-block; display: inline-block;
} }
.tooltipText(@textColor: @BaseLight, @backgroundColor: @BaseHigh) { .tooltipText(@textColor: @BaseLight, @backgroundColor: @BaseHigh) {
visibility: hidden; visibility: hidden;
background-color: @backgroundColor; background-color: @backgroundColor;
color: @textColor; color: @textColor;
position: absolute; position: absolute;
z-index: 1; z-index: 1;
left: @MediumSpace; left: @MediumSpace;
padding: @MediumSpace; padding: @MediumSpace;
} }
.tooltipTextAfter(@color: @BaseDark) { .tooltipTextAfter(@color: @BaseDark) {
content: ""; content: "";
position: absolute; position: absolute;
right: 100%; right: 100%;
border-style: solid; border-style: solid;
border-color: transparent @color transparent transparent; border-color: transparent @color transparent transparent;
left: 0px; left: 0px;
width: 0; width: 0;
height: 0; height: 0;
border-color: @InfoPointerColor transparent; border-color: @InfoPointerColor transparent;
} }
.tooltipVisible() { .tooltipVisible() {
visibility: visible; visibility: visible;
}
.inputTooltip() {
position: relative;
}
.inputTooltipText(@textColor: @BaseLight, @backgroundColor: @BaseHigh) {
background-color: @backgroundColor;
color: @textColor;
position: absolute;
z-index: 1;
padding: @MediumSpace;
}
.inputTooltipTextAfter(@color: @BaseDark) {
content: "";
position: absolute;
right: 100%;
border-style: solid;
border-color: transparent @color transparent transparent;
left: 10px;
width: 0;
height: 0;
border-color: @InfoPointerColor transparent;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,11 @@
@NavMediumSpace: 10px; @NavMediumSpace: 10px;
@NavLargeSpace: 15px; @NavLargeSpace: 15px;
.skip-link {
position: fixed;
top: -200px;
}
html { html {
font-family: wf_segoe-ui_normal, "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif; font-family: wf_segoe-ui_normal, "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif;
padding: 0px; padding: 0px;

View File

@@ -1,20 +1,12 @@
@import "./Common/Constants"; @import "./Common/Constants";
.main {
width: 100%;
float: left;
transition: all .0s ease-in-out;
-ms-transition: all 0s ease-in-out;
-webkit-transition: all 0s ease-in-out;
-moz-transition: all .0s ease-in-out;
height: 100%;
background-color: white;
border-left: 0px solid white;
}
.resourceTree { .resourceTree {
height: 100%; height: 100%;
flex: 0 0 auto; flex: 0 0 auto;
.main {
height: 100%;
}
} }
.resourceTreeScroll { .resourceTreeScroll {

5086
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,13 +7,13 @@
"@azure/arm-cosmosdb": "9.1.0", "@azure/arm-cosmosdb": "9.1.0",
"@azure/cosmos": "3.9.0", "@azure/cosmos": "3.9.0",
"@azure/cosmos-language-service": "0.0.5", "@azure/cosmos-language-service": "0.0.5",
"@azure/identity": "1.1.0", "@azure/identity": "1.2.1",
"@azure/msal-browser": "2.8.0", "@babel/plugin-proposal-class-properties": "7.12.1",
"@azure/msal-react": "1.0.0-alpha.1", "@babel/plugin-proposal-decorators": "7.12.12",
"@jupyterlab/services": "6.0.0-rc.2", "@jupyterlab/services": "6.0.2",
"@jupyterlab/terminal": "3.0.0-rc.2", "@jupyterlab/terminal": "3.0.3",
"@microsoft/applicationinsights-web": "2.5.9", "@microsoft/applicationinsights-web": "2.5.9",
"@nteract/commutable": "7.3.2", "@nteract/commutable": "7.4.2",
"@nteract/connected-components": "6.8.2", "@nteract/connected-components": "6.8.2",
"@nteract/core": "15.1.0", "@nteract/core": "15.1.0",
"@nteract/data-explorer": "8.0.3", "@nteract/data-explorer": "8.0.3",
@@ -38,6 +38,7 @@
"@nteract/transform-vega": "7.0.6", "@nteract/transform-vega": "7.0.6",
"@octokit/rest": "17.9.2", "@octokit/rest": "17.9.2",
"@phosphor/widgets": "1.9.3", "@phosphor/widgets": "1.9.3",
"@testing-library/jest-dom": "5.11.9",
"@types/mkdirp": "1.0.1", "@types/mkdirp": "1.0.1",
"@types/node-fetch": "2.5.7", "@types/node-fetch": "2.5.7",
"@uifabric/react-cards": "0.109.110", "@uifabric/react-cards": "0.109.110",
@@ -46,7 +47,7 @@
"applicationinsights": "1.8.0", "applicationinsights": "1.8.0",
"babel-polyfill": "6.26.0", "babel-polyfill": "6.26.0",
"bootstrap": "3.4.1", "bootstrap": "3.4.1",
"canvas": "2.6.1", "canvas": "file:./canvas",
"clean-webpack-plugin": "0.1.19", "clean-webpack-plugin": "0.1.19",
"copy-webpack-plugin": "6.0.2", "copy-webpack-plugin": "6.0.2",
"crossroads": "0.12.2", "crossroads": "0.12.2",
@@ -63,6 +64,9 @@
"eslint-plugin-react": "7.20.0", "eslint-plugin-react": "7.20.0",
"hasher": "1.2.0", "hasher": "1.2.0",
"html2canvas": "1.0.0-rc.5", "html2canvas": "1.0.0-rc.5",
"i18next": "19.8.4",
"i18next-browser-languagedetector": "6.0.1",
"i18next-http-backend": "1.0.23",
"immutable": "4.0.0-rc.12", "immutable": "4.0.0-rc.12",
"is-ci": "2.0.0", "is-ci": "2.0.0",
"jquery": "3.5.1", "jquery": "3.5.1",
@@ -71,6 +75,7 @@
"knockout": "3.5.1", "knockout": "3.5.1",
"mkdirp": "1.0.4", "mkdirp": "1.0.4",
"monaco-editor": "0.18.1", "monaco-editor": "0.18.1",
"msal": "1.4.4",
"object.entries": "1.1.0", "object.entries": "1.1.0",
"office-ui-fabric-react": "7.134.1", "office-ui-fabric-react": "7.134.1",
"p-retry": "4.2.0", "p-retry": "4.2.0",
@@ -82,14 +87,17 @@
"react-animate-height": "2.0.8", "react-animate-height": "2.0.8",
"react-dnd": "9.4.0", "react-dnd": "9.4.0",
"react-dnd-html5-backend": "9.4.0", "react-dnd-html5-backend": "9.4.0",
"react-dom": "16.9.0", "react-dom": "16.13.1",
"react-hotkeys": "2.0.0", "react-hotkeys": "2.0.0",
"react-i18next": "11.8.5",
"react-notification-system": "0.2.17", "react-notification-system": "0.2.17",
"react-redux": "7.1.3", "react-redux": "7.1.3",
"redux": "4.0.4", "redux": "4.0.4",
"reflect-metadata": "0.1.13",
"rx-jupyter": "5.5.12", "rx-jupyter": "5.5.12",
"rxjs": "6.6.3", "rxjs": "6.6.3",
"styled-components": "4.3.2", "styled-components": "4.3.2",
"swr": "0.4.0",
"text-encoding": "0.7.0", "text-encoding": "0.7.0",
"underscore": "1.9.1", "underscore": "1.9.1",
"url-polyfill": "1.1.7", "url-polyfill": "1.1.7",
@@ -103,6 +111,7 @@
"@babel/preset-env": "7.9.0", "@babel/preset-env": "7.9.0",
"@babel/preset-react": "7.9.4", "@babel/preset-react": "7.9.4",
"@babel/preset-typescript": "7.9.0", "@babel/preset-typescript": "7.9.0",
"@testing-library/react": "11.2.3",
"@types/applicationinsights-js": "1.0.7", "@types/applicationinsights-js": "1.0.7",
"@types/codemirror": "0.0.56", "@types/codemirror": "0.0.56",
"@types/crossroads": "0.0.30", "@types/crossroads": "0.0.30",
@@ -111,7 +120,7 @@
"@types/enzyme-adapter-react-16": "1.0.6", "@types/enzyme-adapter-react-16": "1.0.6",
"@types/expect-puppeteer": "4.4.3", "@types/expect-puppeteer": "4.4.3",
"@types/hasher": "0.0.31", "@types/hasher": "0.0.31",
"@types/jest": "23.3.10", "@types/jest": "26.0.20",
"@types/jest-environment-puppeteer": "4.3.2", "@types/jest-environment-puppeteer": "4.3.2",
"@types/memoize-one": "4.1.1", "@types/memoize-one": "4.1.1",
"@types/node": "12.11.1", "@types/node": "12.11.1",
@@ -119,8 +128,8 @@
"@types/prop-types": "15.5.8", "@types/prop-types": "15.5.8",
"@types/puppeteer": "3.0.1", "@types/puppeteer": "3.0.1",
"@types/q": "1.5.1", "@types/q": "1.5.1",
"@types/react": "16.9.56", "@types/react": "17.0.0",
"@types/react-dom": "16.0.7", "@types/react-dom": "17.0.0",
"@types/react-notification-system": "0.2.39", "@types/react-notification-system": "0.2.39",
"@types/react-redux": "7.1.7", "@types/react-redux": "7.1.7",
"@types/sinon": "2.3.3", "@types/sinon": "2.3.3",
@@ -144,7 +153,9 @@
"eslint-cli": "1.1.1", "eslint-cli": "1.1.1",
"eslint-plugin-no-null": "1.0.2", "eslint-plugin-no-null": "1.0.2",
"eslint-plugin-prefer-arrow": "1.2.2", "eslint-plugin-prefer-arrow": "1.2.2",
"eslint-plugin-react-hooks": "4.2.0",
"expose-loader": "0.7.5", "expose-loader": "0.7.5",
"fast-glob": "3.2.5",
"file-loader": "2.0.0", "file-loader": "2.0.0",
"fs-extra": "7.0.0", "fs-extra": "7.0.0",
"html-loader": "0.5.5", "html-loader": "0.5.5",
@@ -161,7 +172,7 @@
"mini-css-extract-plugin": "0.4.3", "mini-css-extract-plugin": "0.4.3",
"monaco-editor-webpack-plugin": "1.7.0", "monaco-editor-webpack-plugin": "1.7.0",
"node-fetch": "2.6.1", "node-fetch": "2.6.1",
"prettier": "1.19.1", "prettier": "2.2.1",
"puppeteer": "4.0.0", "puppeteer": "4.0.0",
"raw-loader": "0.5.1", "raw-loader": "0.5.1",
"rimraf": "3.0.0", "rimraf": "3.0.0",

View File

@@ -2,5 +2,6 @@ export enum AuthType {
AAD = "aad", AAD = "aad",
EncryptedToken = "encryptedtoken", EncryptedToken = "encryptedtoken",
MasterKey = "masterkey", MasterKey = "masterkey",
ResourceToken = "resourcetoken" ResourceToken = "resourcetoken",
ConnectionString = "connectionstring",
} }

View File

@@ -1,5 +1,6 @@
import * as ko from "knockout"; import * as ko from "knockout";
import * as ReactBindingHandler from "./ReactBindingHandler"; import * as ReactBindingHandler from "./ReactBindingHandler";
import "../Explorer/Tables/DataTable/DataTableBindingManager";
export class BindingHandlersRegisterer { export class BindingHandlersRegisterer {
public static registerBindingHandlers() { public static registerBindingHandlers() {
@@ -13,7 +14,7 @@ export class BindingHandlersRegisterer {
) { ) {
const value = ko.unwrap(wrappedValueAccessor()); const value = ko.unwrap(wrappedValueAccessor());
bindingContext?.$data.isTemplateReady(value); bindingContext?.$data.isTemplateReady(value);
} },
} as ko.BindingHandler; } as ko.BindingHandler;
ReactBindingHandler.Registerer.register(); ReactBindingHandler.Registerer.register();

View File

@@ -42,7 +42,7 @@ export class Registerer {
// Initial rendering at mount point // Initial rendering at mount point
ReactDOM.render(adapter.renderComponent(), element); ReactDOM.render(adapter.renderComponent(), element);
} },
} as ko.BindingHandler; } as ko.BindingHandler;
} }
} }

View File

@@ -40,7 +40,7 @@ export class ArrayHashMap<T> {
public forEach(key: string, iteratorFct: (value: T) => void) { public forEach(key: string, iteratorFct: (value: T) => void) {
const values = this.store.get(key); const values = this.store.get(key);
if (values) { if (values) {
values.forEach(value => iteratorFct(value)); values.forEach((value) => iteratorFct(value));
} }
} }

View File

@@ -1,10 +1,3 @@
import { HashMap } from "./HashMap";
export class AuthorizationEndpoints {
public static arm: string = "https://management.core.windows.net/";
public static common: string = "https://login.windows.net/";
}
export class CodeOfConductEndpoints { export class CodeOfConductEndpoints {
public static privacyStatement: string = "https://aka.ms/ms-privacy-policy"; public static privacyStatement: string = "https://aka.ms/ms-privacy-policy";
public static codeOfConduct: string = "https://aka.ms/cosmos-code-of-conduct"; public static codeOfConduct: string = "https://aka.ms/cosmos-code-of-conduct";
@@ -14,7 +7,7 @@ export class CodeOfConductEndpoints {
export class EndpointsRegex { export class EndpointsRegex {
public static readonly cassandra = [ public static readonly cassandra = [
"AccountEndpoint=(.*).cassandra.cosmosdb.azure.com", "AccountEndpoint=(.*).cassandra.cosmosdb.azure.com",
"HostName=(.*).cassandra.cosmos.azure.com" "HostName=(.*).cassandra.cosmos.azure.com",
]; ];
public static readonly mongo = "mongodb://.*:(.*)@(.*).documents.azure.com"; public static readonly mongo = "mongodb://.*:(.*)@(.*).documents.azure.com";
public static readonly mongoCompute = "mongodb://.*:(.*)@(.*).mongo.cosmos.azure.com"; public static readonly mongoCompute = "mongodb://.*:(.*)@(.*).mongo.cosmos.azure.com";
@@ -126,12 +119,18 @@ export class Features {
public static readonly enableSchema = "enableschema"; public static readonly enableSchema = "enableschema";
public static readonly enableSDKoperations = "enablesdkoperations"; public static readonly enableSDKoperations = "enablesdkoperations";
public static readonly showMinRUSurvey = "showminrusurvey"; public static readonly showMinRUSurvey = "showminrusurvey";
public static readonly enableDatabaseSettingsTabV1 = "enabledbsettingsv1";
public static readonly selfServeType = "selfservetype";
public static readonly enableKOPanel = "enablekopanel";
} }
// flight names returned from the portal are always lowercase // flight names returned from the portal are always lowercase
export class Flights { export class Flights {
public static readonly SettingsV2 = "settingsv2"; public static readonly SettingsV2 = "settingsv2";
public static readonly MongoIndexEditor = "mongoindexeditor"; public static readonly MongoIndexEditor = "mongoindexeditor";
public static readonly MongoIndexing = "mongoindexing";
public static readonly AutoscaleTest = "autoscaletest";
public static readonly GalleryPublish = "gallerypublish";
} }
export class AfecFeatures { export class AfecFeatures {
@@ -140,19 +139,6 @@ export class AfecFeatures {
public static readonly StorageAnalytics = "storageanalytics-public-preview"; public static readonly StorageAnalytics = "storageanalytics-public-preview";
} }
export class Spark {
public static readonly MaxWorkerCount = 10;
public static readonly SKUs: HashMap<string> = new HashMap({
"Cosmos.Spark.D1s": "D1s / 1 core / 4GB RAM",
"Cosmos.Spark.D2s": "D2s / 2 cores / 8GB RAM",
"Cosmos.Spark.D4s": "D4s / 4 cores / 16GB RAM",
"Cosmos.Spark.D8s": "D8s / 8 cores / 32GB RAM",
"Cosmos.Spark.D16s": "D16s / 16 cores / 64GB RAM",
"Cosmos.Spark.D32s": "D32s / 32 cores / 128GB RAM",
"Cosmos.Spark.D64s": "D64s / 64 cores / 256GB RAM"
});
}
export class TagNames { export class TagNames {
public static defaultExperience: string = "defaultExperience"; public static defaultExperience: string = "defaultExperience";
} }
@@ -164,7 +150,7 @@ export class MongoDBAccounts {
export enum MongoBackendEndpointType { export enum MongoBackendEndpointType {
local, local,
remote remote,
} }
// TODO: 435619 Add default endpoints per cloud and use regional only when available // TODO: 435619 Add default endpoints per cloud and use regional only when available
@@ -291,7 +277,7 @@ export class HttpStatusCodes {
HttpStatusCodes.InternalServerError, // TODO: Handle all 500s on Portal backend and remove from retries list HttpStatusCodes.InternalServerError, // TODO: Handle all 500s on Portal backend and remove from retries list
HttpStatusCodes.BadGateway, HttpStatusCodes.BadGateway,
HttpStatusCodes.ServiceUnavailable, HttpStatusCodes.ServiceUnavailable,
HttpStatusCodes.GatewayTimeout HttpStatusCodes.GatewayTimeout,
]; ];
} }
@@ -347,10 +333,7 @@ export class HashRoutePrefixes {
public static docsWithIds(databaseId: string, collectionId: string, docId: string) { public static docsWithIds(databaseId: string, collectionId: string, docId: string) {
const transformedDatabasePrefix: string = this.docs.replace("{db_id}", databaseId); const transformedDatabasePrefix: string = this.docs.replace("{db_id}", databaseId);
return transformedDatabasePrefix return transformedDatabasePrefix.replace("{coll_id}", collectionId).replace("{doc_id}", docId).replace("/", ""); // strip the first slash since hasher adds it
.replace("{coll_id}", collectionId)
.replace("{doc_id}", docId)
.replace("/", ""); // strip the first slash since hasher adds it
} }
} }
@@ -396,7 +379,7 @@ export class OfferVersions {
export enum ConflictOperationType { export enum ConflictOperationType {
Replace = "replace", Replace = "replace",
Create = "create", Create = "create",
Delete = "delete" Delete = "delete",
} }
export const EmulatorMasterKey = export const EmulatorMasterKey =

View File

@@ -10,17 +10,17 @@ describe("tokenProvider", () => {
resourceId: "", resourceId: "",
resourceType: "dbs" as ResourceType, resourceType: "dbs" as ResourceType,
headers: {}, headers: {},
getAuthorizationTokenUsingMasterKey: () => "" getAuthorizationTokenUsingMasterKey: () => "",
}; };
beforeEach(() => { beforeEach(() => {
updateConfigContext({ updateConfigContext({
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com" BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
}); });
window.fetch = jest.fn().mockImplementation(() => { window.fetch = jest.fn().mockImplementation(() => {
return { return {
json: () => "{}", json: () => "{}",
headers: new Map() headers: new Map(),
}; };
}); });
}); });
@@ -36,7 +36,7 @@ describe("tokenProvider", () => {
it("does not call the auth service if a master key is set", async () => { it("does not call the auth service if a master key is set", async () => {
updateUserContext({ updateUserContext({
masterKey: "foo" masterKey: "foo",
}); });
await tokenProvider(options); await tokenProvider(options);
expect((window.fetch as any).mock.calls.length).toBe(0); expect((window.fetch as any).mock.calls.length).toBe(0);
@@ -50,7 +50,7 @@ describe("getTokenFromAuthService", () => {
window.fetch = jest.fn().mockImplementation(() => { window.fetch = jest.fn().mockImplementation(() => {
return { return {
json: () => "{}", json: () => "{}",
headers: new Map() headers: new Map(),
}; };
}); });
}); });
@@ -61,7 +61,7 @@ describe("getTokenFromAuthService", () => {
it("builds the correct URL in production", () => { it("builds the correct URL in production", () => {
updateConfigContext({ updateConfigContext({
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com" BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
}); });
getTokenFromAuthService("GET", "dbs", "foo"); getTokenFromAuthService("GET", "dbs", "foo");
expect(window.fetch).toHaveBeenCalledWith( expect(window.fetch).toHaveBeenCalledWith(
@@ -72,7 +72,7 @@ describe("getTokenFromAuthService", () => {
it("builds the correct URL in dev", () => { it("builds the correct URL in dev", () => {
updateConfigContext({ updateConfigContext({
BACKEND_ENDPOINT: "https://localhost:1234" BACKEND_ENDPOINT: "https://localhost:1234",
}); });
getTokenFromAuthService("GET", "dbs", "foo"); getTokenFromAuthService("GET", "dbs", "foo");
expect(window.fetch).toHaveBeenCalledWith( expect(window.fetch).toHaveBeenCalledWith(
@@ -96,15 +96,15 @@ describe("endpoint", () => {
documentEndpoint: "bar", documentEndpoint: "bar",
gremlinEndpoint: "foo", gremlinEndpoint: "foo",
tableEndpoint: "foo", tableEndpoint: "foo",
cassandraEndpoint: "foo" cassandraEndpoint: "foo",
} },
} },
}); });
expect(endpoint()).toEqual("bar"); expect(endpoint()).toEqual("bar");
}); });
it("uses _endpoint if set", () => { it("uses _endpoint if set", () => {
updateUserContext({ updateUserContext({
endpoint: "baz" endpoint: "baz",
}); });
expect(endpoint()).toEqual("baz"); expect(endpoint()).toEqual("baz");
}); });
@@ -121,7 +121,7 @@ describe("requestPlugin", () => {
updateConfigContext({ updateConfigContext({
platform: Platform.Hosted, platform: Platform.Hosted,
BACKEND_ENDPOINT: "https://localhost:1234", BACKEND_ENDPOINT: "https://localhost:1234",
PROXY_PATH: "/proxy" PROXY_PATH: "/proxy",
}); });
const headers = {}; const headers = {};
const endpoint = "https://docs.azure.com"; const endpoint = "https://docs.azure.com";

View File

@@ -58,13 +58,13 @@ export async function getTokenFromAuthService(verb: string, resourceType: string
method: "POST", method: "POST",
headers: { headers: {
"content-type": "application/json", "content-type": "application/json",
"x-ms-encrypted-auth-token": userContext.accessToken "x-ms-encrypted-auth-token": userContext.accessToken,
}, },
body: JSON.stringify({ body: JSON.stringify({
verb, verb,
resourceType, resourceType,
resourceId resourceId,
}) }),
}); });
//TODO I am not sure why we have to parse the JSON again here. fetch should do it for us when we call .json() //TODO I am not sure why we have to parse the JSON again here. fetch should do it for us when we call .json()
const result = JSON.parse(await response.json()); const result = JSON.parse(await response.json());
@@ -77,13 +77,13 @@ export async function getTokenFromAuthService(verb: string, resourceType: string
export function client(): Cosmos.CosmosClient { export function client(): Cosmos.CosmosClient {
const options: Cosmos.CosmosClientOptions = { const options: Cosmos.CosmosClientOptions = {
endpoint: endpoint() || " ", // CosmosClient gets upset if we pass a falsy value here endpoint: endpoint() || "https://cosmos.azure.com", // CosmosClient gets upset if we pass a bad URL. This should never actually get called
key: userContext.masterKey, key: userContext.masterKey,
tokenProvider, tokenProvider,
connectionPolicy: { connectionPolicy: {
enableEndpointDiscovery: false enableEndpointDiscovery: false,
}, },
userAgentSuffix: "Azure Portal" userAgentSuffix: "Azure Portal",
}; };
if (configContext.PROXY_PATH !== undefined) { if (configContext.PROXY_PATH !== undefined) {

View File

@@ -73,7 +73,7 @@ export default class EditableUtility {
return false; return false;
}); });
observable.subscribe(edit => { observable.subscribe((edit) => {
var edits = observable.edits && observable.edits(); var edits = observable.edits && observable.edits();
if (!edits) { if (!edits) {
return; return;
@@ -83,9 +83,9 @@ export default class EditableUtility {
}); });
observable.editableIsValid = ko.observable<boolean>(true); observable.editableIsValid = ko.observable<boolean>(true);
observable.subscribe(value => { observable.subscribe((value) => {
const validations: ((value: T) => boolean)[] = (observable.validations && observable.validations()) || []; const validations: ((value: T) => boolean)[] = (observable.validations && observable.validations()) || [];
const isValid = validations.every(validate => validate(value)); const isValid = validations.every((validate) => validate(value));
observable.editableIsValid(isValid); observable.editableIsValid(isValid);
}); });

View File

@@ -21,7 +21,7 @@ export const handleError = (error: string | ARMError | Error, area: string, cons
sendNotificationForError(errorMessage, errorCode); sendNotificationForError(errorMessage, errorCode);
}; };
export const getErrorMessage = (error: string | Error): string => { export const getErrorMessage = (error: string | Error = ""): string => {
const errorMessage = typeof error === "string" ? error : error.message; const errorMessage = typeof error === "string" ? error : error.message;
return replaceKnownError(errorMessage); return replaceKnownError(errorMessage);
}; };
@@ -37,7 +37,7 @@ const sendNotificationForError = (errorMessage: string, errorCode: number | stri
} }
sendMessage({ sendMessage({
type: MessageTypes.ForbiddenError, type: MessageTypes.ForbiddenError,
reason: errorMessage reason: errorMessage,
}); });
} }
}; };
@@ -45,10 +45,10 @@ const sendNotificationForError = (errorMessage: string, errorCode: number | stri
const replaceKnownError = (errorMessage: string): string => { const replaceKnownError = (errorMessage: string): string => {
if ( if (
window.dataExplorer?.subscriptionType() === SubscriptionType.Internal && window.dataExplorer?.subscriptionType() === SubscriptionType.Internal &&
errorMessage.indexOf("SharedOffer is Disabled for your account") >= 0 errorMessage?.indexOf("SharedOffer is Disabled for your account") >= 0
) { ) {
return "Database throughput is not supported for internal subscriptions."; return "Database throughput is not supported for internal subscriptions.";
} else if (errorMessage.indexOf("Partition key paths must contain only valid") >= 0) { } else if (errorMessage?.indexOf("Partition key paths must contain only valid") >= 0) {
return "Partition key paths must contain only valid characters and not contain a trailing slash or wildcard character."; return "Partition key paths must contain only valid characters and not contain a trailing slash or wildcard character.";
} }

View File

@@ -11,8 +11,8 @@ describe("nextPage", () => {
queryMetrics: {}, queryMetrics: {},
requestCharge: 1, requestCharge: 1,
headers: {}, headers: {},
activityId: "foo" activityId: "foo",
}) }),
}; };
expect(await nextPage(fakeIterator, 10)).toMatchSnapshot(); expect(await nextPage(fakeIterator, 10)).toMatchSnapshot();

View File

@@ -14,7 +14,7 @@ export interface MinimalQueryIterator {
// Pick<QueryIterator<any>, "fetchNext">; // Pick<QueryIterator<any>, "fetchNext">;
export function nextPage(documentsIterator: MinimalQueryIterator, firstItemIndex: number): Promise<QueryResults> { export function nextPage(documentsIterator: MinimalQueryIterator, firstItemIndex: number): Promise<QueryResults> {
return documentsIterator.fetchNext().then(response => { return documentsIterator.fetchNext().then((response) => {
const documents = response.resources; const documents = response.resources;
const headers = (response as any).headers || {}; // TODO this is a private key. Remove any const headers = (response as any).headers || {}; // TODO this is a private key. Remove any
const itemCount = (documents && documents.length) || 0; const itemCount = (documents && documents.length) || 0;
@@ -26,7 +26,7 @@ export function nextPage(documentsIterator: MinimalQueryIterator, firstItemIndex
lastItemIndex: Number(firstItemIndex) + Number(itemCount), lastItemIndex: Number(firstItemIndex) + Number(itemCount),
headers, headers,
activityId: response.activityId, activityId: response.activityId,
requestCharge: response.requestCharge requestCharge: response.requestCharge,
}; };
}); });
} }

View File

@@ -29,7 +29,7 @@ export function logError(errorMessage: string, area: string, code?: number | str
function _logEntry(entry: Diagnostics.LogEntry): void { function _logEntry(entry: Diagnostics.LogEntry): void {
sendMessage({ sendMessage({
type: MessageTypes.LogInfo, type: MessageTypes.LogInfo,
data: JSON.stringify(entry) data: JSON.stringify(entry),
}); });
const severityLevel = ((level: Diagnostics.LogEntryLevel): SeverityLevel => { const severityLevel = ((level: Diagnostics.LogEntryLevel): SeverityLevel => {
@@ -60,6 +60,6 @@ function _generateLogEntry(
level, level,
message, message,
area, area,
code code,
}; };
} }

View File

@@ -6,7 +6,7 @@ describe("Message Handler", () => {
let mockPromise = { let mockPromise = {
id: "123", id: "123",
startTime: new Date(), startTime: new Date(),
deferred: Q.defer<any>() deferred: Q.defer<any>(),
}; };
let mockMessage = { message: { id: "123", data: "{}" } }; let mockMessage = { message: { id: "123", data: "{}" } };
MessageHandler.RequestMap[mockPromise.id] = mockPromise; MessageHandler.RequestMap[mockPromise.id] = mockPromise;
@@ -18,7 +18,7 @@ describe("Message Handler", () => {
let message = { let message = {
id: "123", id: "123",
startTime: new Date(), startTime: new Date(),
deferred: Q.defer<any>() deferred: Q.defer<any>(),
}; };
MessageHandler.handleCachedDataMessage(message); MessageHandler.handleCachedDataMessage(message);

View File

@@ -35,7 +35,7 @@ export function sendCachedDataMessage<TResponseDataModel>(
let cachedDataPromise: CachedDataPromise<TResponseDataModel> = { let cachedDataPromise: CachedDataPromise<TResponseDataModel> = {
deferred: Q.defer<TResponseDataModel>(), deferred: Q.defer<TResponseDataModel>(),
startTime: new Date(), startTime: new Date(),
id: _.uniqueId() id: _.uniqueId(),
}; };
RequestMap[cachedDataPromise.id] = cachedDataPromise; RequestMap[cachedDataPromise.id] = cachedDataPromise;
sendMessage({ type: messageType, params: params, id: cachedDataPromise.id }); sendMessage({ type: messageType, params: params, id: cachedDataPromise.id });
@@ -54,7 +54,7 @@ export function sendMessage(data: any): void {
portalChildWindow.parent.postMessage( portalChildWindow.parent.postMessage(
{ {
signature: "pcIframe", signature: "pcIframe",
data: data data: data,
}, },
portalChildWindow.document.referrer portalChildWindow.document.referrer
); );

View File

@@ -14,7 +14,7 @@ const fetchMock = () => {
ok: true, ok: true,
text: () => "{}", text: () => "{}",
json: () => "{}", json: () => "{}",
headers: new Map() headers: new Map(),
}); });
}; };
@@ -27,8 +27,8 @@ const collection = {
partitionKey: { partitionKey: {
paths: ["/pk"], paths: ["/pk"],
kind: "Hash", kind: "Hash",
version: 1 version: 1,
} },
} as Collection; } as Collection;
const documentId = ({ const documentId = ({
@@ -38,8 +38,8 @@ const documentId = ({
partitionKey: { partitionKey: {
paths: ["/pk"], paths: ["/pk"],
kind: "Hash", kind: "Hash",
version: 1 version: 1,
} },
} as unknown) as DocumentId; } as unknown) as DocumentId;
const databaseAccount = { const databaseAccount = {
@@ -52,8 +52,8 @@ const databaseAccount = {
documentEndpoint: "bar", documentEndpoint: "bar",
gremlinEndpoint: "foo", gremlinEndpoint: "foo",
tableEndpoint: "foo", tableEndpoint: "foo",
cassandraEndpoint: "foo" cassandraEndpoint: "foo",
} },
} as DatabaseAccount; } as DatabaseAccount;
describe("MongoProxyClient", () => { describe("MongoProxyClient", () => {
@@ -61,10 +61,10 @@ describe("MongoProxyClient", () => {
beforeEach(() => { beforeEach(() => {
resetConfigContext(); resetConfigContext();
updateUserContext({ updateUserContext({
databaseAccount databaseAccount,
}); });
updateConfigContext({ updateConfigContext({
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com" BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
}); });
window.fetch = jest.fn().mockImplementation(fetchMock); window.fetch = jest.fn().mockImplementation(fetchMock);
}); });
@@ -93,10 +93,10 @@ describe("MongoProxyClient", () => {
beforeEach(() => { beforeEach(() => {
resetConfigContext(); resetConfigContext();
updateUserContext({ updateUserContext({
databaseAccount databaseAccount,
}); });
updateConfigContext({ updateConfigContext({
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com" BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
}); });
window.fetch = jest.fn().mockImplementation(fetchMock); window.fetch = jest.fn().mockImplementation(fetchMock);
}); });
@@ -125,10 +125,10 @@ describe("MongoProxyClient", () => {
beforeEach(() => { beforeEach(() => {
resetConfigContext(); resetConfigContext();
updateUserContext({ updateUserContext({
databaseAccount databaseAccount,
}); });
updateConfigContext({ updateConfigContext({
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com" BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
}); });
window.fetch = jest.fn().mockImplementation(fetchMock); window.fetch = jest.fn().mockImplementation(fetchMock);
}); });
@@ -157,10 +157,10 @@ describe("MongoProxyClient", () => {
beforeEach(() => { beforeEach(() => {
resetConfigContext(); resetConfigContext();
updateUserContext({ updateUserContext({
databaseAccount databaseAccount,
}); });
updateConfigContext({ updateConfigContext({
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com" BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
}); });
window.fetch = jest.fn().mockImplementation(fetchMock); window.fetch = jest.fn().mockImplementation(fetchMock);
}); });
@@ -189,10 +189,10 @@ describe("MongoProxyClient", () => {
beforeEach(() => { beforeEach(() => {
resetConfigContext(); resetConfigContext();
updateUserContext({ updateUserContext({
databaseAccount databaseAccount,
}); });
updateConfigContext({ updateConfigContext({
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com" BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
}); });
window.fetch = jest.fn().mockImplementation(fetchMock); window.fetch = jest.fn().mockImplementation(fetchMock);
}); });
@@ -222,10 +222,10 @@ describe("MongoProxyClient", () => {
resetConfigContext(); resetConfigContext();
delete window.authType; delete window.authType;
updateUserContext({ updateUserContext({
databaseAccount databaseAccount,
}); });
updateConfigContext({ updateConfigContext({
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com" BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
}); });
}); });

View File

@@ -16,7 +16,7 @@ import { sendMessage } from "./MessageHandler";
const defaultHeaders = { const defaultHeaders = {
[HttpHeaders.apiType]: ApiType.MongoDB.toString(), [HttpHeaders.apiType]: ApiType.MongoDB.toString(),
[CosmosSDKConstants.HttpHeaders.MaxEntityCount]: "100", [CosmosSDKConstants.HttpHeaders.MaxEntityCount]: "100",
[CosmosSDKConstants.HttpHeaders.Version]: "2017-11-15" [CosmosSDKConstants.HttpHeaders.Version]: "2017-11-15",
}; };
function authHeaders() { function authHeaders() {
@@ -31,7 +31,7 @@ export function queryIterator(databaseId: string, collection: Collection, query:
let continuationToken: string; let continuationToken: string;
return { return {
fetchNext: () => { fetchNext: () => {
return queryDocuments(databaseId, collection, false, query).then(response => { return queryDocuments(databaseId, collection, false, query).then((response) => {
continuationToken = response.continuationToken; continuationToken = response.continuationToken;
const headers: { [key: string]: string | number } = {}; const headers: { [key: string]: string | number } = {};
response.headers.forEach((value, key) => { response.headers.forEach((value, key) => {
@@ -42,10 +42,10 @@ export function queryIterator(databaseId: string, collection: Collection, query:
headers, headers,
requestCharge: Number(headers[CosmosSDKConstants.HttpHeaders.RequestCharge]), requestCharge: Number(headers[CosmosSDKConstants.HttpHeaders.RequestCharge]),
activityId: String(headers[CosmosSDKConstants.HttpHeaders.ActivityId]), activityId: String(headers[CosmosSDKConstants.HttpHeaders.ActivityId]),
hasMoreResults: !!continuationToken hasMoreResults: !!continuationToken,
}; };
}); });
} },
}; };
} }
@@ -74,7 +74,9 @@ export function queryDocuments(
rg: userContext.resourceGroup, rg: userContext.resourceGroup,
dba: databaseAccount.name, dba: databaseAccount.name,
pk: pk:
collection && collection.partitionKey && !collection.partitionKey.systemKey ? collection.partitionKeyProperty : "" collection && collection.partitionKey && !collection.partitionKey.systemKey
? collection.partitionKeyProperty
: "",
}; };
const endpoint = getEndpoint() || ""; const endpoint = getEndpoint() || "";
@@ -87,7 +89,7 @@ export function queryDocuments(
[CosmosSDKConstants.HttpHeaders.EnableScanInQuery]: "true", [CosmosSDKConstants.HttpHeaders.EnableScanInQuery]: "true",
[CosmosSDKConstants.HttpHeaders.EnableCrossPartitionQuery]: "true", [CosmosSDKConstants.HttpHeaders.EnableCrossPartitionQuery]: "true",
[CosmosSDKConstants.HttpHeaders.ParallelizeCrossPartitionQuery]: "true", [CosmosSDKConstants.HttpHeaders.ParallelizeCrossPartitionQuery]: "true",
[HttpHeaders.contentType]: "application/query+json" [HttpHeaders.contentType]: "application/query+json",
}; };
if (continuationToken) { if (continuationToken) {
@@ -100,14 +102,14 @@ export function queryDocuments(
.fetch(`${endpoint}${path}?${queryString.stringify(params)}`, { .fetch(`${endpoint}${path}?${queryString.stringify(params)}`, {
method: "POST", method: "POST",
body: JSON.stringify({ query }), body: JSON.stringify({ query }),
headers headers,
}) })
.then(async response => { .then(async (response) => {
if (response.ok) { if (response.ok) {
return { return {
continuationToken: response.headers.get(CosmosSDKConstants.HttpHeaders.Continuation), continuationToken: response.headers.get(CosmosSDKConstants.HttpHeaders.Continuation),
documents: (await response.json()).Documents as DataModels.DocumentId[], documents: (await response.json()).Documents as DataModels.DocumentId[],
headers: response.headers headers: response.headers,
}; };
} }
errorHandling(response, "querying documents", params); errorHandling(response, "querying documents", params);
@@ -135,7 +137,9 @@ export function readDocument(
rg: userContext.resourceGroup, rg: userContext.resourceGroup,
dba: databaseAccount.name, dba: databaseAccount.name,
pk: pk:
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey ? documentId.partitionKeyProperty : "" documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
? documentId.partitionKeyProperty
: "",
}; };
const endpoint = getEndpoint(); const endpoint = getEndpoint();
@@ -147,10 +151,10 @@ export function readDocument(
...authHeaders(), ...authHeaders(),
[CosmosSDKConstants.HttpHeaders.PartitionKey]: encodeURIComponent( [CosmosSDKConstants.HttpHeaders.PartitionKey]: encodeURIComponent(
JSON.stringify(documentId.partitionKeyHeader()) JSON.stringify(documentId.partitionKeyHeader())
) ),
} },
}) })
.then(response => { .then((response) => {
if (response.ok) { if (response.ok) {
return response.json(); return response.json();
} }
@@ -175,7 +179,7 @@ export function createDocument(
sid: userContext.subscriptionId, sid: userContext.subscriptionId,
rg: userContext.resourceGroup, rg: userContext.resourceGroup,
dba: databaseAccount.name, dba: databaseAccount.name,
pk: collection && collection.partitionKey && !collection.partitionKey.systemKey ? partitionKeyProperty : "" pk: collection && collection.partitionKey && !collection.partitionKey.systemKey ? partitionKeyProperty : "",
}; };
const endpoint = getEndpoint(); const endpoint = getEndpoint();
@@ -186,10 +190,10 @@ export function createDocument(
body: JSON.stringify(documentContent), body: JSON.stringify(documentContent),
headers: { headers: {
...defaultHeaders, ...defaultHeaders,
...authHeaders() ...authHeaders(),
} },
}) })
.then(response => { .then((response) => {
if (response.ok) { if (response.ok) {
return response.json(); return response.json();
} }
@@ -218,7 +222,9 @@ export function updateDocument(
rg: userContext.resourceGroup, rg: userContext.resourceGroup,
dba: databaseAccount.name, dba: databaseAccount.name,
pk: pk:
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey ? documentId.partitionKeyProperty : "" documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
? documentId.partitionKeyProperty
: "",
}; };
const endpoint = getEndpoint(); const endpoint = getEndpoint();
@@ -230,10 +236,10 @@ export function updateDocument(
...defaultHeaders, ...defaultHeaders,
...authHeaders(), ...authHeaders(),
[HttpHeaders.contentType]: "application/json", [HttpHeaders.contentType]: "application/json",
[CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()) [CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()),
} },
}) })
.then(response => { .then((response) => {
if (response.ok) { if (response.ok) {
return response.json(); return response.json();
} }
@@ -257,7 +263,9 @@ export function deleteDocument(databaseId: string, collection: Collection, docum
rg: userContext.resourceGroup, rg: userContext.resourceGroup,
dba: databaseAccount.name, dba: databaseAccount.name,
pk: pk:
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey ? documentId.partitionKeyProperty : "" documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
? documentId.partitionKeyProperty
: "",
}; };
const endpoint = getEndpoint(); const endpoint = getEndpoint();
@@ -268,10 +276,10 @@ export function deleteDocument(databaseId: string, collection: Collection, docum
...defaultHeaders, ...defaultHeaders,
...authHeaders(), ...authHeaders(),
[HttpHeaders.contentType]: "application/json", [HttpHeaders.contentType]: "application/json",
[CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()) [CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()),
} },
}) })
.then(response => { .then((response) => {
if (response.ok) { if (response.ok) {
return undefined; return undefined;
} }
@@ -299,7 +307,7 @@ export function createMongoCollectionWithProxy(
rg: userContext.resourceGroup, rg: userContext.resourceGroup,
dba: databaseAccount.name, dba: databaseAccount.name,
isAutoPilot: !!params.autoPilotMaxThroughput, isAutoPilot: !!params.autoPilotMaxThroughput,
autoPilotThroughput: params.autoPilotMaxThroughput?.toString() autoPilotThroughput: params.autoPilotMaxThroughput?.toString(),
}; };
const endpoint = getEndpoint(); const endpoint = getEndpoint();
@@ -314,11 +322,11 @@ export function createMongoCollectionWithProxy(
headers: { headers: {
...defaultHeaders, ...defaultHeaders,
...authHeaders(), ...authHeaders(),
[HttpHeaders.contentType]: "application/json" [HttpHeaders.contentType]: "application/json",
} },
} }
) )
.then(response => { .then((response) => {
if (response.ok) { if (response.ok) {
return response.json(); return response.json();
} }

View File

@@ -14,7 +14,7 @@
*/ */
export default class MongoUtility { export default class MongoUtility {
public static tojson = function(x: any, indent: string, nolint: boolean) { public static tojson = function (x: any, indent: string, nolint: boolean) {
if (x === null || x === undefined) { if (x === null || x === undefined) {
return String(x); return String(x);
} }
@@ -71,7 +71,7 @@ export default class MongoUtility {
} }
}; };
private static tojsonObject = function(x: any, indent: string, nolint: boolean) { private static tojsonObject = function (x: any, indent: string, nolint: boolean) {
var lineEnding = nolint ? " " : "\n"; var lineEnding = nolint ? " " : "\n";
var tabSpace = nolint ? "" : "\t"; var tabSpace = nolint ? "" : "\t";
indent = indent || ""; indent = indent || "";
@@ -114,7 +114,7 @@ export default class MongoUtility {
} }
} }
// Add proper line endings, indents, and commas to each line // Add proper line endings, indents, and commas to each line
s += $.map(pairs, function(pair) { s += $.map(pairs, function (pair) {
return lineEnding + indent + pair; return lineEnding + indent + pair;
}).join(","); }).join(",");
s += lineEnding; s += lineEnding;
@@ -124,7 +124,7 @@ export default class MongoUtility {
return s + indent + "}"; return s + indent + "}";
}; };
private static tojsonArray = function(a: any, indent: string, nolint: boolean) { private static tojsonArray = function (a: any, indent: string, nolint: boolean) {
if (a.length === 0) { if (a.length === 0) {
return "[ ]"; return "[ ]";
} }
@@ -151,7 +151,7 @@ export default class MongoUtility {
return s; return s;
}; };
private static hasDefinedProperty = function(obj: any, prop: string): boolean { private static hasDefinedProperty = function (obj: any, prop: string): boolean {
if (Object.getPrototypeOf === undefined || Object.getPrototypeOf(obj) === null) { if (Object.getPrototypeOf === undefined || Object.getPrototypeOf(obj) === null) {
return false; return false;
} else if (obj.hasOwnProperty(prop)) { } else if (obj.hasOwnProperty(prop)) {

View File

@@ -9,14 +9,14 @@ describe("parseSDKOfferResponse", () => {
offerThroughput: 500, offerThroughput: 500,
collectionThroughputInfo: { collectionThroughputInfo: {
minimumRUForCollection: 400, minimumRUForCollection: 400,
numPhysicalPartitions: 1 numPhysicalPartitions: 1,
} },
}, },
id: "test" id: "test",
} as SDKOfferDefinition; } as SDKOfferDefinition;
const mockResponse = { const mockResponse = {
resource: mockOfferDefinition resource: mockOfferDefinition,
} as OfferResponse; } as OfferResponse;
const expectedResult: Offer = { const expectedResult: Offer = {
@@ -25,7 +25,7 @@ describe("parseSDKOfferResponse", () => {
minimumThroughput: 400, minimumThroughput: 400,
id: "test", id: "test",
offerDefinition: mockOfferDefinition, offerDefinition: mockOfferDefinition,
offerReplacePending: false offerReplacePending: false,
}; };
expect(OfferUtility.parseSDKOfferResponse(mockResponse)).toEqual(expectedResult); expect(OfferUtility.parseSDKOfferResponse(mockResponse)).toEqual(expectedResult);
@@ -37,17 +37,17 @@ describe("parseSDKOfferResponse", () => {
offerThroughput: 400, offerThroughput: 400,
collectionThroughputInfo: { collectionThroughputInfo: {
minimumRUForCollection: 400, minimumRUForCollection: 400,
numPhysicalPartitions: 1 numPhysicalPartitions: 1,
}, },
offerAutopilotSettings: { offerAutopilotSettings: {
maxThroughput: 5000 maxThroughput: 5000,
} },
}, },
id: "test" id: "test",
} as SDKOfferDefinition; } as SDKOfferDefinition;
const mockResponse = { const mockResponse = {
resource: mockOfferDefinition resource: mockOfferDefinition,
} as OfferResponse; } as OfferResponse;
const expectedResult: Offer = { const expectedResult: Offer = {
@@ -56,7 +56,7 @@ describe("parseSDKOfferResponse", () => {
minimumThroughput: 400, minimumThroughput: 400,
id: "test", id: "test",
offerDefinition: mockOfferDefinition, offerDefinition: mockOfferDefinition,
offerReplacePending: false offerReplacePending: false,
}; };
expect(OfferUtility.parseSDKOfferResponse(mockResponse)).toEqual(expectedResult); expect(OfferUtility.parseSDKOfferResponse(mockResponse)).toEqual(expectedResult);

View File

@@ -2,8 +2,11 @@ import { Offer, SDKOfferDefinition } from "../Contracts/DataModels";
import { OfferResponse } from "@azure/cosmos"; import { OfferResponse } from "@azure/cosmos";
import { HttpHeaders } from "./Constants"; import { HttpHeaders } from "./Constants";
export const parseSDKOfferResponse = (offerResponse: OfferResponse): Offer => { export const parseSDKOfferResponse = (offerResponse: OfferResponse): Offer | undefined => {
const offerDefinition: SDKOfferDefinition = offerResponse?.resource; const offerDefinition: SDKOfferDefinition | undefined = offerResponse?.resource;
if (!offerDefinition) {
return undefined;
}
const offerContent = offerDefinition.content; const offerContent = offerDefinition.content;
if (!offerContent) { if (!offerContent) {
return undefined; return undefined;
@@ -12,14 +15,14 @@ export const parseSDKOfferResponse = (offerResponse: OfferResponse): Offer => {
const minimumThroughput = offerContent.collectionThroughputInfo?.minimumRUForCollection; const minimumThroughput = offerContent.collectionThroughputInfo?.minimumRUForCollection;
const autopilotSettings = offerContent.offerAutopilotSettings; const autopilotSettings = offerContent.offerAutopilotSettings;
if (autopilotSettings) { if (autopilotSettings && autopilotSettings.maxThroughput && minimumThroughput) {
return { return {
id: offerDefinition.id, id: offerDefinition.id,
autoscaleMaxThroughput: autopilotSettings.maxThroughput, autoscaleMaxThroughput: autopilotSettings.maxThroughput,
manualThroughput: undefined, manualThroughput: undefined,
minimumThroughput, minimumThroughput,
offerDefinition, offerDefinition,
offerReplacePending: offerResponse.headers?.[HttpHeaders.offerReplacePending] === "true" offerReplacePending: offerResponse.headers?.[HttpHeaders.offerReplacePending] === "true",
}; };
} }
@@ -29,6 +32,6 @@ export const parseSDKOfferResponse = (offerResponse: OfferResponse): Offer => {
manualThroughput: offerContent.offerThroughput, manualThroughput: offerContent.offerThroughput,
minimumThroughput, minimumThroughput,
offerDefinition, offerDefinition,
offerReplacePending: offerResponse.headers?.[HttpHeaders.offerReplacePending] === "true" offerReplacePending: offerResponse.headers?.[HttpHeaders.offerReplacePending] === "true",
}; };
}; };

View File

@@ -30,7 +30,7 @@ export const fetchPortalNotifications = async (): Promise<DataModels.Notificatio
const headers = { [authorizationHeader.header]: authorizationHeader.token }; const headers = { [authorizationHeader.header]: authorizationHeader.token };
const response = await window.fetch(url, { const response = await window.fetch(url, {
headers headers,
}); });
if (!response.ok) { if (!response.ok) {

View File

@@ -20,7 +20,7 @@ export class QueriesClient {
private static readonly PartitionKey: DataModels.PartitionKey = { private static readonly PartitionKey: DataModels.PartitionKey = {
paths: [`/${SavedQueries.PartitionKeyProperty}`], paths: [`/${SavedQueries.PartitionKeyProperty}`],
kind: BackendDefaults.partitionKeyKind, kind: BackendDefaults.partitionKeyKind,
version: BackendDefaults.partitionKeyVersion version: BackendDefaults.partitionKeyVersion,
}; };
private static readonly FetchQuery: string = "SELECT * FROM c"; private static readonly FetchQuery: string = "SELECT * FROM c";
private static readonly FetchMongoQuery: string = "{}"; private static readonly FetchMongoQuery: string = "{}";
@@ -40,7 +40,7 @@ export class QueriesClient {
databaseId: SavedQueries.DatabaseName, databaseId: SavedQueries.DatabaseName,
partitionKey: QueriesClient.PartitionKey, partitionKey: QueriesClient.PartitionKey,
offerThroughput: SavedQueries.OfferThroughput, offerThroughput: SavedQueries.OfferThroughput,
databaseLevelThroughput: false databaseLevelThroughput: false,
}) })
.then( .then(
(collection: DataModels.Collection) => { (collection: DataModels.Collection) => {
@@ -120,7 +120,7 @@ export class QueriesClient {
resourceId: resourceId, resourceId: resourceId,
queryName: queryName, queryName: queryName,
query: query, query: query,
id: id id: id,
}; };
try { try {
this.validateQuery(parsedQuery); this.validateQuery(parsedQuery);
@@ -161,7 +161,7 @@ export class QueriesClient {
const documentId = new DocumentId( const documentId = new DocumentId(
{ {
partitionKey: QueriesClient.PartitionKey, partitionKey: QueriesClient.PartitionKey,
partitionKeyProperty: "id" partitionKeyProperty: "id",
} as DocumentsTab, } as DocumentsTab,
query, query,
query.queryName query.queryName

View File

@@ -4,7 +4,7 @@ import { SplitterMetrics } from "./Constants";
export enum SplitterDirection { export enum SplitterDirection {
Horizontal = "horizontal", Horizontal = "horizontal",
Vertical = "vertical" Vertical = "vertical",
} }
export interface SplitterBounds { export interface SplitterBounds {
@@ -23,10 +23,10 @@ export class Splitter {
public splitterId: string; public splitterId: string;
public leftSideId: string; public leftSideId: string;
public splitter: HTMLElement; public splitter!: HTMLElement;
public leftSide: HTMLElement; public leftSide!: HTMLElement;
public lastX: number; public lastX!: number;
public lastWidth: number; public lastWidth!: number;
private isCollapsed: ko.Observable<boolean>; private isCollapsed: ko.Observable<boolean>;
private bounds: SplitterBounds; private bounds: SplitterBounds;
@@ -42,15 +42,16 @@ export class Splitter {
} }
public initialize() { public initialize() {
this.splitter = document.getElementById(this.splitterId); if (document.getElementById(this.splitterId) !== null && document.getElementById(this.leftSideId) != null) {
this.leftSide = document.getElementById(this.leftSideId); this.splitter = <HTMLElement>document.getElementById(this.splitterId);
this.leftSide = <HTMLElement>document.getElementById(this.leftSideId);
}
const isVerticalSplitter: boolean = this.direction === SplitterDirection.Vertical; const isVerticalSplitter: boolean = this.direction === SplitterDirection.Vertical;
const splitterOptions: JQueryUI.ResizableOptions = { const splitterOptions: JQueryUI.ResizableOptions = {
animate: true, animate: true,
animateDuration: "fast", animateDuration: "fast",
start: this.onResizeStart, start: this.onResizeStart,
stop: this.onResizeStop stop: this.onResizeStop,
}; };
if (isVerticalSplitter) { if (isVerticalSplitter) {
@@ -90,9 +91,7 @@ export class Splitter {
this.lastWidth = $(this.leftSide).width(); this.lastWidth = $(this.leftSide).width();
$(this.splitter).css("left", SplitterMetrics.CollapsedPositionLeft); $(this.splitter).css("left", SplitterMetrics.CollapsedPositionLeft);
$(this.leftSide).css("width", ""); $(this.leftSide).css("width", "");
$(this.leftSide) $(this.leftSide).resizable("option", "disabled", true).removeClass("ui-resizable-disabled"); // remove class so splitter is visible
.resizable("option", "disabled", true)
.removeClass("ui-resizable-disabled"); // remove class so splitter is visible
$(this.splitter).removeClass("ui-resizable-e"); $(this.splitter).removeClass("ui-resizable-e");
this.isCollapsed(true); this.isCollapsed(true);
} }

View File

@@ -32,8 +32,8 @@ export default class UrlUtility {
type: type, type: type,
objectBody: { objectBody: {
id: id, id: id,
self: resourcePath self: resourcePath,
} },
}; };
return result; return result;

View File

@@ -14,15 +14,15 @@ describe("createCollection", () => {
collectionId: "testContainer", collectionId: "testContainer",
databaseId: "testDatabase", databaseId: "testDatabase",
databaseLevelThroughput: true, databaseLevelThroughput: true,
offerThroughput: 400 offerThroughput: 400,
}; };
beforeAll(() => { beforeAll(() => {
updateUserContext({ updateUserContext({
databaseAccount: { databaseAccount: {
name: "test" name: "test",
} as DatabaseAccount, } as DatabaseAccount,
defaultExperience: DefaultAccountExperienceType.DocumentDB defaultExperience: DefaultAccountExperienceType.DocumentDB,
}); });
}); });
@@ -40,12 +40,12 @@ describe("createCollection", () => {
return { return {
database: { database: {
containers: { containers: {
create: () => ({}) create: () => ({}),
} },
} },
}; };
} },
} },
}); });
await createCollection(createCollectionParams); await createCollection(createCollectionParams);
expect(client).toHaveBeenCalled(); expect(client).toHaveBeenCalled();
@@ -59,7 +59,7 @@ describe("createCollection", () => {
collectionId: "testContainer", collectionId: "testContainer",
databaseId: "testDatabase", databaseId: "testDatabase",
databaseLevelThroughput: false, databaseLevelThroughput: false,
offerThroughput: 400 offerThroughput: 400,
}; };
expect(constructRpOptions(manualThroughputParams)).toEqual({ throughput: 400 }); expect(constructRpOptions(manualThroughputParams)).toEqual({ throughput: 400 });
@@ -69,12 +69,12 @@ describe("createCollection", () => {
databaseId: "testDatabase", databaseId: "testDatabase",
databaseLevelThroughput: false, databaseLevelThroughput: false,
offerThroughput: 400, offerThroughput: 400,
autoPilotMaxThroughput: 4000 autoPilotMaxThroughput: 4000,
}; };
expect(constructRpOptions(autoPilotThroughputParams)).toEqual({ expect(constructRpOptions(autoPilotThroughputParams)).toEqual({
autoscaleSettings: { autoscaleSettings: {
maxThroughput: 4000 maxThroughput: 4000,
} },
}); });
}); });
}); });

View File

@@ -11,15 +11,15 @@ import { createMongoCollectionWithProxy } from "../MongoProxyClient";
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { import {
createUpdateCassandraTable, createUpdateCassandraTable,
getCassandraTable getCassandraTable,
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
import { import {
createUpdateMongoDBCollection, createUpdateMongoDBCollection,
getMongoDBCollection getMongoDBCollection,
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
import { import {
createUpdateGremlinGraph, createUpdateGremlinGraph,
getGremlinGraph getGremlinGraph,
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources"; import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
import { logConsoleProgress, logConsoleInfo } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
@@ -41,7 +41,7 @@ export const createCollection = async (params: DataModels.CreateCollectionParams
autoPilotMaxThroughput: params.autoPilotMaxThroughput, autoPilotMaxThroughput: params.autoPilotMaxThroughput,
databaseId: params.databaseId, databaseId: params.databaseId,
databaseLevelThroughput: params.databaseLevelThroughput, databaseLevelThroughput: params.databaseLevelThroughput,
offerThroughput: params.offerThroughput offerThroughput: params.offerThroughput,
}; };
await createDatabase(createDatabaseParams); await createDatabase(createDatabaseParams);
} }
@@ -100,7 +100,7 @@ const createSqlContainer = async (params: DataModels.CreateCollectionParams): Pr
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params); const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
const resource: ARMTypes.SqlContainerResource = { const resource: ARMTypes.SqlContainerResource = {
id: params.collectionId id: params.collectionId,
}; };
if (params.analyticalStorageTtl) { if (params.analyticalStorageTtl) {
resource.analyticalStorageTtl = params.analyticalStorageTtl; resource.analyticalStorageTtl = params.analyticalStorageTtl;
@@ -118,8 +118,8 @@ const createSqlContainer = async (params: DataModels.CreateCollectionParams): Pr
const rpPayload: ARMTypes.SqlDatabaseCreateUpdateParameters = { const rpPayload: ARMTypes.SqlDatabaseCreateUpdateParameters = {
properties: { properties: {
resource, resource,
options options,
} },
}; };
const createResponse = await createUpdateSqlContainer( const createResponse = await createUpdateSqlContainer(
@@ -154,7 +154,7 @@ const createMongoCollection = async (params: DataModels.CreateCollectionParams):
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params); const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
const resource: ARMTypes.MongoDBCollectionResource = { const resource: ARMTypes.MongoDBCollectionResource = {
id: params.collectionId id: params.collectionId,
}; };
if (params.analyticalStorageTtl) { if (params.analyticalStorageTtl) {
resource.analyticalStorageTtl = params.analyticalStorageTtl; resource.analyticalStorageTtl = params.analyticalStorageTtl;
@@ -170,8 +170,8 @@ const createMongoCollection = async (params: DataModels.CreateCollectionParams):
const rpPayload: ARMTypes.MongoDBCollectionCreateUpdateParameters = { const rpPayload: ARMTypes.MongoDBCollectionCreateUpdateParameters = {
properties: { properties: {
resource, resource,
options options,
} },
}; };
const createResponse = await createUpdateMongoDBCollection( const createResponse = await createUpdateMongoDBCollection(
@@ -185,7 +185,7 @@ const createMongoCollection = async (params: DataModels.CreateCollectionParams):
if (params.createMongoWildcardIndex) { if (params.createMongoWildcardIndex) {
TelemetryProcessor.trace(Action.CreateMongoCollectionWithWildcardIndex, ActionModifiers.Mark, { TelemetryProcessor.trace(Action.CreateMongoCollectionWithWildcardIndex, ActionModifiers.Mark, {
message: "Mongo Collection created with wildcard index on all fields." message: "Mongo Collection created with wildcard index on all fields.",
}); });
} }
@@ -212,7 +212,7 @@ const createCassandraTable = async (params: DataModels.CreateCollectionParams):
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params); const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
const resource: ARMTypes.CassandraTableResource = { const resource: ARMTypes.CassandraTableResource = {
id: params.collectionId id: params.collectionId,
}; };
if (params.analyticalStorageTtl) { if (params.analyticalStorageTtl) {
resource.analyticalStorageTtl = params.analyticalStorageTtl; resource.analyticalStorageTtl = params.analyticalStorageTtl;
@@ -221,8 +221,8 @@ const createCassandraTable = async (params: DataModels.CreateCollectionParams):
const rpPayload: ARMTypes.CassandraTableCreateUpdateParameters = { const rpPayload: ARMTypes.CassandraTableCreateUpdateParameters = {
properties: { properties: {
resource, resource,
options options,
} },
}; };
const createResponse = await createUpdateCassandraTable( const createResponse = await createUpdateCassandraTable(
@@ -256,7 +256,7 @@ const createGraph = async (params: DataModels.CreateCollectionParams): Promise<D
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params); const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
const resource: ARMTypes.GremlinGraphResource = { const resource: ARMTypes.GremlinGraphResource = {
id: params.collectionId id: params.collectionId,
}; };
if (params.indexingPolicy) { if (params.indexingPolicy) {
@@ -272,8 +272,8 @@ const createGraph = async (params: DataModels.CreateCollectionParams): Promise<D
const rpPayload: ARMTypes.GremlinGraphCreateUpdateParameters = { const rpPayload: ARMTypes.GremlinGraphCreateUpdateParameters = {
properties: { properties: {
resource, resource,
options options,
} },
}; };
const createResponse = await createUpdateGremlinGraph( const createResponse = await createUpdateGremlinGraph(
@@ -306,14 +306,14 @@ const createTable = async (params: DataModels.CreateCollectionParams): Promise<D
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params); const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
const resource: ARMTypes.TableResource = { const resource: ARMTypes.TableResource = {
id: params.collectionId id: params.collectionId,
}; };
const rpPayload: ARMTypes.TableCreateUpdateParameters = { const rpPayload: ARMTypes.TableCreateUpdateParameters = {
properties: { properties: {
resource, resource,
options options,
} },
}; };
const createResponse = await createUpdateTable( const createResponse = await createUpdateTable(
@@ -334,13 +334,13 @@ export const constructRpOptions = (params: DataModels.CreateDatabaseParams): ARM
if (params.autoPilotMaxThroughput) { if (params.autoPilotMaxThroughput) {
return { return {
autoscaleSettings: { autoscaleSettings: {
maxThroughput: params.autoPilotMaxThroughput maxThroughput: params.autoPilotMaxThroughput,
} },
}; };
} }
return { return {
throughput: params.offerThroughput throughput: params.offerThroughput,
}; };
}; };
@@ -350,7 +350,7 @@ const createCollectionWithSDK = async (params: DataModels.CreateCollectionParams
partitionKey: params.partitionKey || undefined, partitionKey: params.partitionKey || undefined,
indexingPolicy: params.indexingPolicy || undefined, indexingPolicy: params.indexingPolicy || undefined,
uniqueKeyPolicy: params.uniqueKeyPolicy || undefined, uniqueKeyPolicy: params.uniqueKeyPolicy || undefined,
analyticalStorageTtl: params.analyticalStorageTtl analyticalStorageTtl: params.analyticalStorageTtl,
} as ContainerRequest; // TODO: remove cast when https://github.com/Azure/azure-cosmos-js/issues/423 is fixed } as ContainerRequest; // TODO: remove cast when https://github.com/Azure/azure-cosmos-js/issues/423 is fixed
const collectionOptions: RequestOptions = {}; const collectionOptions: RequestOptions = {};
const createDatabaseBody: DatabaseRequest = { id: params.databaseId }; const createDatabaseBody: DatabaseRequest = { id: params.databaseId };

View File

@@ -8,21 +8,21 @@ import {
GremlinDatabaseCreateUpdateParameters, GremlinDatabaseCreateUpdateParameters,
MongoDBDatabaseCreateUpdateParameters, MongoDBDatabaseCreateUpdateParameters,
SqlDatabaseCreateUpdateParameters, SqlDatabaseCreateUpdateParameters,
CreateUpdateOptions CreateUpdateOptions,
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01/types";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { createUpdateSqlDatabase, getSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import { createUpdateSqlDatabase, getSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { import {
createUpdateCassandraKeyspace, createUpdateCassandraKeyspace,
getCassandraKeyspace getCassandraKeyspace,
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
import { import {
createUpdateMongoDBDatabase, createUpdateMongoDBDatabase,
getMongoDBDatabase getMongoDBDatabase,
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
import { import {
createUpdateGremlinDatabase, createUpdateGremlinDatabase,
getGremlinDatabase getGremlinDatabase,
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { handleError } from "../ErrorHandlingUtils"; import { handleError } from "../ErrorHandlingUtils";
import { logConsoleProgress, logConsoleInfo } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
@@ -85,10 +85,10 @@ async function createSqlDatabase(params: DataModels.CreateDatabaseParams): Promi
const rpPayload: SqlDatabaseCreateUpdateParameters = { const rpPayload: SqlDatabaseCreateUpdateParameters = {
properties: { properties: {
resource: { resource: {
id: params.databaseId id: params.databaseId,
}, },
options options,
} },
}; };
const createResponse = await createUpdateSqlDatabase( const createResponse = await createUpdateSqlDatabase(
userContext.subscriptionId, userContext.subscriptionId,
@@ -121,10 +121,10 @@ async function createMongoDatabase(params: DataModels.CreateDatabaseParams): Pro
const rpPayload: MongoDBDatabaseCreateUpdateParameters = { const rpPayload: MongoDBDatabaseCreateUpdateParameters = {
properties: { properties: {
resource: { resource: {
id: params.databaseId id: params.databaseId,
}, },
options options,
} },
}; };
const createResponse = await createUpdateMongoDBDatabase( const createResponse = await createUpdateMongoDBDatabase(
userContext.subscriptionId, userContext.subscriptionId,
@@ -157,10 +157,10 @@ async function createCassandraKeyspace(params: DataModels.CreateDatabaseParams):
const rpPayload: CassandraKeyspaceCreateUpdateParameters = { const rpPayload: CassandraKeyspaceCreateUpdateParameters = {
properties: { properties: {
resource: { resource: {
id: params.databaseId id: params.databaseId,
}, },
options options,
} },
}; };
const createResponse = await createUpdateCassandraKeyspace( const createResponse = await createUpdateCassandraKeyspace(
userContext.subscriptionId, userContext.subscriptionId,
@@ -193,10 +193,10 @@ async function createGremlineDatabase(params: DataModels.CreateDatabaseParams):
const rpPayload: GremlinDatabaseCreateUpdateParameters = { const rpPayload: GremlinDatabaseCreateUpdateParameters = {
properties: { properties: {
resource: { resource: {
id: params.databaseId id: params.databaseId,
}, },
options options,
} },
}; };
const createResponse = await createUpdateGremlinDatabase( const createResponse = await createUpdateGremlinDatabase(
userContext.subscriptionId, userContext.subscriptionId,
@@ -231,12 +231,12 @@ function constructRpOptions(params: DataModels.CreateDatabaseParams): CreateUpda
if (params.autoPilotMaxThroughput) { if (params.autoPilotMaxThroughput) {
return { return {
autoscaleSettings: { autoscaleSettings: {
maxThroughput: params.autoPilotMaxThroughput maxThroughput: params.autoPilotMaxThroughput,
} },
}; };
} }
return { return {
throughput: params.offerThroughput throughput: params.offerThroughput,
}; };
} }

View File

@@ -3,12 +3,12 @@ import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType
import { Resource, StoredProcedureDefinition } from "@azure/cosmos"; import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
import { import {
SqlStoredProcedureCreateUpdateParameters, SqlStoredProcedureCreateUpdateParameters,
SqlStoredProcedureResource SqlStoredProcedureResource,
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01/types";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { import {
createUpdateSqlStoredProcedure, createUpdateSqlStoredProcedure,
getSqlStoredProcedure getSqlStoredProcedure,
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { handleError } from "../ErrorHandlingUtils"; import { handleError } from "../ErrorHandlingUtils";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
@@ -49,8 +49,8 @@ export async function createStoredProcedure(
const createSprocParams: SqlStoredProcedureCreateUpdateParameters = { const createSprocParams: SqlStoredProcedureCreateUpdateParameters = {
properties: { properties: {
resource: storedProcedure as SqlStoredProcedureResource, resource: storedProcedure as SqlStoredProcedureResource,
options: {} options: {},
} },
}; };
const rpResponse = await createUpdateSqlStoredProcedure( const rpResponse = await createUpdateSqlStoredProcedure(
userContext.subscriptionId, userContext.subscriptionId,

View File

@@ -3,7 +3,7 @@ import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType
import { Resource, TriggerDefinition } from "@azure/cosmos"; import { Resource, TriggerDefinition } from "@azure/cosmos";
import { import {
SqlTriggerCreateUpdateParameters, SqlTriggerCreateUpdateParameters,
SqlTriggerResource SqlTriggerResource,
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01/types";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
@@ -44,8 +44,8 @@ export async function createTrigger(
const createTriggerParams: SqlTriggerCreateUpdateParameters = { const createTriggerParams: SqlTriggerCreateUpdateParameters = {
properties: { properties: {
resource: trigger as SqlTriggerResource, resource: trigger as SqlTriggerResource,
options: {} options: {},
} },
}; };
const rpResponse = await createUpdateSqlTrigger( const rpResponse = await createUpdateSqlTrigger(
userContext.subscriptionId, userContext.subscriptionId,
@@ -59,10 +59,7 @@ export async function createTrigger(
return rpResponse && (rpResponse.properties?.resource as TriggerDefinition & Resource); return rpResponse && (rpResponse.properties?.resource as TriggerDefinition & Resource);
} }
const response = await client() const response = await client().database(databaseId).container(collectionId).scripts.triggers.create(trigger);
.database(databaseId)
.container(collectionId)
.scripts.triggers.create(trigger);
return response.resource; return response.resource;
} catch (error) { } catch (error) {
handleError(error, "CreateTrigger", `Error while creating trigger ${trigger.id}`); handleError(error, "CreateTrigger", `Error while creating trigger ${trigger.id}`);

View File

@@ -3,12 +3,12 @@ import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos"; import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
import { import {
SqlUserDefinedFunctionCreateUpdateParameters, SqlUserDefinedFunctionCreateUpdateParameters,
SqlUserDefinedFunctionResource SqlUserDefinedFunctionResource,
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01/types";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { import {
createUpdateSqlUserDefinedFunction, createUpdateSqlUserDefinedFunction,
getSqlUserDefinedFunction getSqlUserDefinedFunction,
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { handleError } from "../ErrorHandlingUtils"; import { handleError } from "../ErrorHandlingUtils";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
@@ -49,8 +49,8 @@ export async function createUserDefinedFunction(
const createUDFParams: SqlUserDefinedFunctionCreateUpdateParameters = { const createUDFParams: SqlUserDefinedFunctionCreateUpdateParameters = {
properties: { properties: {
resource: userDefinedFunction as SqlUserDefinedFunctionResource, resource: userDefinedFunction as SqlUserDefinedFunctionResource,
options: {} options: {},
} },
}; };
const rpResponse = await createUpdateSqlUserDefinedFunction( const rpResponse = await createUpdateSqlUserDefinedFunction(
userContext.subscriptionId, userContext.subscriptionId,

View File

@@ -13,9 +13,9 @@ describe("deleteCollection", () => {
beforeAll(() => { beforeAll(() => {
updateUserContext({ updateUserContext({
databaseAccount: { databaseAccount: {
name: "test" name: "test",
} as DatabaseAccount, } as DatabaseAccount,
defaultExperience: DefaultAccountExperienceType.DocumentDB defaultExperience: DefaultAccountExperienceType.DocumentDB,
}); });
}); });
@@ -32,11 +32,11 @@ describe("deleteCollection", () => {
return { return {
container: () => { container: () => {
return { return {
delete: (): unknown => undefined delete: (): unknown => undefined,
}; };
} },
}; };
} },
}); });
await deleteCollection("database", "collection"); await deleteCollection("database", "collection");
expect(client).toHaveBeenCalled(); expect(client).toHaveBeenCalled();

View File

@@ -16,10 +16,7 @@ export async function deleteCollection(databaseId: string, collectionId: string)
if (window.authType === AuthType.AAD && !userContext.useSDKOperations) { if (window.authType === AuthType.AAD && !userContext.useSDKOperations) {
await deleteCollectionWithARM(databaseId, collectionId); await deleteCollectionWithARM(databaseId, collectionId);
} else { } else {
await client() await client().database(databaseId).container(collectionId).delete();
.database(databaseId)
.container(collectionId)
.delete();
} }
logConsoleInfo(`Successfully deleted container ${collectionId}`); logConsoleInfo(`Successfully deleted container ${collectionId}`);
} catch (error) { } catch (error) {

View File

@@ -10,7 +10,7 @@ export const deleteConflict = async (collection: CollectionBase, conflictId: Con
try { try {
const options = { const options = {
partitionKey: getPartitionKeyHeaderForConflict(conflictId) partitionKey: getPartitionKeyHeaderForConflict(conflictId),
}; };
await client() await client()

View File

@@ -13,9 +13,9 @@ describe("deleteDatabase", () => {
beforeAll(() => { beforeAll(() => {
updateUserContext({ updateUserContext({
databaseAccount: { databaseAccount: {
name: "test" name: "test",
} as DatabaseAccount, } as DatabaseAccount,
defaultExperience: DefaultAccountExperienceType.DocumentDB defaultExperience: DefaultAccountExperienceType.DocumentDB,
}); });
}); });
@@ -30,9 +30,9 @@ describe("deleteDatabase", () => {
(client as jest.Mock).mockReturnValue({ (client as jest.Mock).mockReturnValue({
database: () => { database: () => {
return { return {
delete: (): unknown => undefined delete: (): unknown => undefined,
}; };
} },
}); });
await deleteDatabase("database"); await deleteDatabase("database");
expect(client).toHaveBeenCalled(); expect(client).toHaveBeenCalled();

View File

@@ -19,9 +19,7 @@ export async function deleteDatabase(databaseId: string): Promise<void> {
if (window.authType === AuthType.AAD && !userContext.useSDKOperations) { if (window.authType === AuthType.AAD && !userContext.useSDKOperations) {
await deleteDatabaseWithARM(databaseId); await deleteDatabaseWithARM(databaseId);
} else { } else {
await client() await client().database(databaseId).delete();
.database(databaseId)
.delete();
} }
logConsoleInfo(`Successfully deleted database ${databaseId}`); logConsoleInfo(`Successfully deleted database ${databaseId}`);
} catch (error) { } catch (error) {

View File

@@ -27,11 +27,7 @@ export async function deleteStoredProcedure(
storedProcedureId storedProcedureId
); );
} else { } else {
await client() await client().database(databaseId).container(collectionId).scripts.storedProcedure(storedProcedureId).delete();
.database(databaseId)
.container(collectionId)
.scripts.storedProcedure(storedProcedureId)
.delete();
} }
} catch (error) { } catch (error) {
handleError(error, "DeleteStoredProcedure", `Error while deleting stored procedure ${storedProcedureId}`); handleError(error, "DeleteStoredProcedure", `Error while deleting stored procedure ${storedProcedureId}`);

View File

@@ -23,11 +23,7 @@ export async function deleteTrigger(databaseId: string, collectionId: string, tr
triggerId triggerId
); );
} else { } else {
await client() await client().database(databaseId).container(collectionId).scripts.trigger(triggerId).delete();
.database(databaseId)
.container(collectionId)
.scripts.trigger(triggerId)
.delete();
} }
} catch (error) { } catch (error) {
handleError(error, "DeleteTrigger", `Error while deleting trigger ${triggerId}`); handleError(error, "DeleteTrigger", `Error while deleting trigger ${triggerId}`);

View File

@@ -23,11 +23,7 @@ export async function deleteUserDefinedFunction(databaseId: string, collectionId
id id
); );
} else { } else {
await client() await client().database(databaseId).container(collectionId).scripts.userDefinedFunction(id).delete();
.database(databaseId)
.container(collectionId)
.scripts.userDefinedFunction(id)
.delete();
} }
} catch (error) { } catch (error) {
handleError(error, "DeleteUserDefinedFunction", `Error while deleting user defined function ${id}`); handleError(error, "DeleteUserDefinedFunction", `Error while deleting user defined function ${id}`);

View File

@@ -33,7 +33,7 @@ export const executeStoredProcedure = async (
); );
return { return {
result: response.resource, result: response.resource,
scriptLogs: response.headers[HttpHeaders.scriptLogResults] as string scriptLogs: response.headers[HttpHeaders.scriptLogResults] as string,
}; };
} catch (error) { } catch (error) {
handleError( handleError(

View File

@@ -60,8 +60,8 @@ export const getCollectionUsageSizeInKB = async (databaseName: string, container
apiVersion: "2018-01-01", apiVersion: "2018-01-01",
queryParams: { queryParams: {
filter, filter,
metricNames metricNames,
} },
}); });
if (metricsResponse?.value?.length !== 2) { if (metricsResponse?.value?.length !== 2) {
@@ -76,7 +76,7 @@ export const getCollectionUsageSizeInKB = async (databaseName: string, container
return dataUsageSizeInKb + indexUsageSizeInKb; return dataUsageSizeInKb + indexUsageSizeInKb;
} catch (error) { } catch (error) {
handleError(error, "getCollectionUsageSize"); handleError(error, "getCollectionUsageSize");
throw error; return undefined;
} }
}; };

View File

@@ -11,10 +11,7 @@ export async function getIndexTransformationProgress(databaseId: string, collect
let indexTransformationPercentage: number; let indexTransformationPercentage: number;
const clearMessage = logConsoleProgress(`Reading container ${collectionId}`); const clearMessage = logConsoleProgress(`Reading container ${collectionId}`);
try { try {
const response = await client() const response = await client().database(databaseId).container(collectionId).read({ populateQuotaInfo: true });
.database(databaseId)
.container(collectionId)
.read({ populateQuotaInfo: true });
indexTransformationPercentage = parseInt( indexTransformationPercentage = parseInt(
response.headers[Constants.HttpHeaders.collectionIndexTransformationProgress] as string response.headers[Constants.HttpHeaders.collectionIndexTransformationProgress] as string

View File

@@ -7,8 +7,5 @@ export const queryConflicts = (
query: string, query: string,
options: FeedOptions options: FeedOptions
): QueryIterator<ConflictDefinition & Resource> => { ): QueryIterator<ConflictDefinition & Resource> => {
return client() return client().database(databaseId).container(containerId).conflicts.query(query, options);
.database(databaseId)
.container(containerId)
.conflicts.query(query, options);
}; };

View File

@@ -10,10 +10,7 @@ export const queryDocuments = (
options: FeedOptions options: FeedOptions
): QueryIterator<ItemDefinition & Resource> => { ): QueryIterator<ItemDefinition & Resource> => {
options = getCommonQueryOptions(options); options = getCommonQueryOptions(options);
return client() return client().database(databaseId).container(containerId).items.query(query, options);
.database(databaseId)
.container(containerId)
.items.query(query, options);
}; };
export const getCommonQueryOptions = (options: FeedOptions): FeedOptions => { export const getCommonQueryOptions = (options: FeedOptions): FeedOptions => {

View File

@@ -10,9 +10,9 @@ describe("readCollection", () => {
beforeAll(() => { beforeAll(() => {
updateUserContext({ updateUserContext({
databaseAccount: { databaseAccount: {
name: "test" name: "test",
} as DatabaseAccount, } as DatabaseAccount,
defaultExperience: DefaultAccountExperienceType.DocumentDB defaultExperience: DefaultAccountExperienceType.DocumentDB,
}); });
}); });
@@ -23,11 +23,11 @@ describe("readCollection", () => {
return { return {
container: () => { container: () => {
return { return {
read: (): unknown => ({}) read: (): unknown => ({}),
}; };
} },
}; };
} },
}); });
await readCollection("database", "collection"); await readCollection("database", "collection");
expect(client).toHaveBeenCalled(); expect(client).toHaveBeenCalled();

View File

@@ -7,10 +7,7 @@ export async function readCollection(databaseId: string, collectionId: string):
let collection: DataModels.Collection; let collection: DataModels.Collection;
const clearMessage = logConsoleProgress(`Querying container ${collectionId}`); const clearMessage = logConsoleProgress(`Querying container ${collectionId}`);
try { try {
const response = await client() const response = await client().database(databaseId).container(collectionId).read();
.database(databaseId)
.container(collectionId)
.read();
collection = response.resource as DataModels.Collection; collection = response.resource as DataModels.Collection;
} catch (error) { } catch (error) {
handleError(error, "ReadCollection", `Error while querying container ${collectionId}`); handleError(error, "ReadCollection", `Error while querying container ${collectionId}`);

View File

@@ -106,7 +106,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
autoscaleMaxThroughput: autoscaleSettings.maxThroughput, autoscaleMaxThroughput: autoscaleSettings.maxThroughput,
manualThroughput: undefined, manualThroughput: undefined,
minimumThroughput, minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true" offerReplacePending: resource.offerReplacePending === "true",
}; };
} }
@@ -115,7 +115,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
autoscaleMaxThroughput: undefined, autoscaleMaxThroughput: undefined,
manualThroughput: resource.throughput, manualThroughput: resource.throughput,
minimumThroughput, minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true" offerReplacePending: resource.offerReplacePending === "true",
}; };
} }

View File

@@ -12,9 +12,9 @@ describe("readCollections", () => {
beforeAll(() => { beforeAll(() => {
updateUserContext({ updateUserContext({
databaseAccount: { databaseAccount: {
name: "test" name: "test",
} as DatabaseAccount, } as DatabaseAccount,
defaultExperience: DefaultAccountExperienceType.DocumentDB defaultExperience: DefaultAccountExperienceType.DocumentDB,
}); });
}); });
@@ -32,12 +32,12 @@ describe("readCollections", () => {
containers: { containers: {
readAll: () => { readAll: () => {
return { return {
fetchAll: (): unknown => [] fetchAll: (): unknown => [],
}; };
} },
} },
}; };
} },
}); });
await readCollections("database"); await readCollections("database");
expect(client).toHaveBeenCalled(); expect(client).toHaveBeenCalled();

View File

@@ -23,10 +23,7 @@ export async function readCollections(databaseId: string): Promise<DataModels.Co
return await readCollectionsWithARM(databaseId); return await readCollectionsWithARM(databaseId);
} }
const sdkResponse = await client() const sdkResponse = await client().database(databaseId).containers.readAll().fetchAll();
.database(databaseId)
.containers.readAll()
.fetchAll();
return sdkResponse.resources as DataModels.Collection[]; return sdkResponse.resources as DataModels.Collection[];
} catch (error) { } catch (error) {
handleError(error, "ReadCollections", `Error while querying containers for database ${databaseId}`); handleError(error, "ReadCollections", `Error while querying containers for database ${databaseId}`);
@@ -63,5 +60,5 @@ async function readCollectionsWithARM(databaseId: string): Promise<DataModels.Co
throw new Error(`Unsupported default experience type: ${defaultExperience}`); throw new Error(`Unsupported default experience type: ${defaultExperience}`);
} }
return rpResponse?.value?.map(collection => collection.properties?.resource as DataModels.Collection); return rpResponse?.value?.map((collection) => collection.properties?.resource as DataModels.Collection);
} }

View File

@@ -78,7 +78,7 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
autoscaleMaxThroughput: autoscaleSettings.maxThroughput, autoscaleMaxThroughput: autoscaleSettings.maxThroughput,
manualThroughput: undefined, manualThroughput: undefined,
minimumThroughput, minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true" offerReplacePending: resource.offerReplacePending === "true",
}; };
} }
@@ -87,7 +87,7 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
autoscaleMaxThroughput: undefined, autoscaleMaxThroughput: undefined,
manualThroughput: resource.throughput, manualThroughput: resource.throughput,
minimumThroughput, minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true" offerReplacePending: resource.offerReplacePending === "true",
}; };
} }

View File

@@ -12,9 +12,9 @@ describe("readDatabases", () => {
beforeAll(() => { beforeAll(() => {
updateUserContext({ updateUserContext({
databaseAccount: { databaseAccount: {
name: "test" name: "test",
} as DatabaseAccount, } as DatabaseAccount,
defaultExperience: DefaultAccountExperienceType.DocumentDB defaultExperience: DefaultAccountExperienceType.DocumentDB,
}); });
}); });
@@ -30,10 +30,10 @@ describe("readDatabases", () => {
databases: { databases: {
readAll: () => { readAll: () => {
return { return {
fetchAll: (): unknown => [] fetchAll: (): unknown => [],
}; };
} },
} },
}); });
await readDatabases(); await readDatabases();
expect(client).toHaveBeenCalled(); expect(client).toHaveBeenCalled();

View File

@@ -21,9 +21,7 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
) { ) {
databases = await readDatabasesWithARM(); databases = await readDatabasesWithARM();
} else { } else {
const sdkResponse = await client() const sdkResponse = await client().databases.readAll().fetchAll();
.databases.readAll()
.fetchAll();
databases = sdkResponse.resources as DataModels.Database[]; databases = sdkResponse.resources as DataModels.Database[];
} }
} catch (error) { } catch (error) {
@@ -58,5 +56,5 @@ async function readDatabasesWithARM(): Promise<DataModels.Database[]> {
throw new Error(`Unsupported default experience type: ${defaultExperience}`); throw new Error(`Unsupported default experience type: ${defaultExperience}`);
} }
return rpResponse?.value?.map(database => database.properties?.resource as DataModels.Database); return rpResponse?.value?.map((database) => database.properties?.resource as DataModels.Database);
} }

View File

@@ -8,7 +8,7 @@ import { readOffers } from "./readOffers";
export const readOfferWithSDK = async (offerId: string, resourceId: string): Promise<Offer> => { export const readOfferWithSDK = async (offerId: string, resourceId: string): Promise<Offer> => {
if (!offerId) { if (!offerId) {
const offers = await readOffers(); const offers = await readOffers();
const offer = offers.find(offer => offer.resource === resourceId); const offer = offers.find((offer) => offer.resource === resourceId);
if (!offer) { if (!offer) {
return undefined; return undefined;
@@ -18,12 +18,10 @@ export const readOfferWithSDK = async (offerId: string, resourceId: string): Pro
const options: RequestOptions = { const options: RequestOptions = {
initialHeaders: { initialHeaders: {
[HttpHeaders.populateCollectionThroughputInfo]: true [HttpHeaders.populateCollectionThroughputInfo]: true,
} },
}; };
const response = await client() const response = await client().offer(offerId).read(options);
.offer(offerId)
.read(options);
return parseSDKOfferResponse(response); return parseSDKOfferResponse(response);
}; };

View File

@@ -7,9 +7,7 @@ export const readOffers = async (): Promise<SDKOfferDefinition[]> => {
const clearMessage = logConsoleProgress(`Querying offers`); const clearMessage = logConsoleProgress(`Querying offers`);
try { try {
const response = await client() const response = await client().offers.readAll().fetchAll();
.offers.readAll()
.fetchAll();
return response?.resources; return response?.resources;
} catch (error) { } catch (error) {
// This should be removed when we can correctly identify if an account is serverless when connected using connection string too. // This should be removed when we can correctly identify if an account is serverless when connected using connection string too.

View File

@@ -25,7 +25,7 @@ export async function readStoredProcedures(
databaseId, databaseId,
collectionId collectionId
); );
return rpResponse?.value?.map(sproc => sproc.properties?.resource as StoredProcedureDefinition & Resource); return rpResponse?.value?.map((sproc) => sproc.properties?.resource as StoredProcedureDefinition & Resource);
} }
const response = await client() const response = await client()

View File

@@ -25,14 +25,10 @@ export async function readTriggers(
databaseId, databaseId,
collectionId collectionId
); );
return rpResponse?.value?.map(trigger => trigger.properties?.resource as TriggerDefinition & Resource); return rpResponse?.value?.map((trigger) => trigger.properties?.resource as TriggerDefinition & Resource);
} }
const response = await client() const response = await client().database(databaseId).container(collectionId).scripts.triggers.readAll().fetchAll();
.database(databaseId)
.container(collectionId)
.scripts.triggers.readAll()
.fetchAll();
return response?.resources; return response?.resources;
} catch (error) { } catch (error) {
handleError(error, "ReadTriggers", `Failed to query triggers for container ${collectionId}`); handleError(error, "ReadTriggers", `Failed to query triggers for container ${collectionId}`);

View File

@@ -25,7 +25,7 @@ export async function readUserDefinedFunctions(
databaseId, databaseId,
collectionId collectionId
); );
return rpResponse?.value?.map(udf => udf.properties?.resource as UserDefinedFunctionDefinition & Resource); return rpResponse?.value?.map((udf) => udf.properties?.resource as UserDefinedFunctionDefinition & Resource);
} }
const response = await client() const response = await client()

View File

@@ -8,22 +8,22 @@ import {
MongoDBCollectionCreateUpdateParameters, MongoDBCollectionCreateUpdateParameters,
MongoDBCollectionResource, MongoDBCollectionResource,
SqlContainerCreateUpdateParameters, SqlContainerCreateUpdateParameters,
SqlContainerResource SqlContainerResource,
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01/types";
import { RequestOptions } from "@azure/cosmos/dist-esm"; import { RequestOptions } from "@azure/cosmos/dist-esm";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { import {
createUpdateCassandraTable, createUpdateCassandraTable,
getCassandraTable getCassandraTable,
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
import { import {
createUpdateMongoDBCollection, createUpdateMongoDBCollection,
getMongoDBCollection getMongoDBCollection,
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
import { import {
createUpdateGremlinGraph, createUpdateGremlinGraph,
getGremlinGraph getGremlinGraph,
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources"; import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
import { handleError } from "../ErrorHandlingUtils"; import { handleError } from "../ErrorHandlingUtils";
@@ -130,8 +130,8 @@ export async function updateMongoDBCollectionThroughRP(
const updateParams: MongoDBCollectionCreateUpdateParameters = { const updateParams: MongoDBCollectionCreateUpdateParameters = {
properties: { properties: {
resource: newCollection, resource: newCollection,
options: updateOptions options: updateOptions,
} },
}; };
const updateResponse = await createUpdateMongoDBCollection( const updateResponse = await createUpdateMongoDBCollection(

View File

@@ -17,7 +17,7 @@ import {
migrateSqlDatabaseToManualThroughput, migrateSqlDatabaseToManualThroughput,
migrateSqlContainerToAutoscale, migrateSqlContainerToAutoscale,
migrateSqlContainerToManualThroughput, migrateSqlContainerToManualThroughput,
updateSqlContainerThroughput updateSqlContainerThroughput,
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { import {
updateCassandraKeyspaceThroughput, updateCassandraKeyspaceThroughput,
@@ -25,7 +25,7 @@ import {
migrateCassandraKeyspaceToManualThroughput, migrateCassandraKeyspaceToManualThroughput,
migrateCassandraTableToAutoscale, migrateCassandraTableToAutoscale,
migrateCassandraTableToManualThroughput, migrateCassandraTableToManualThroughput,
updateCassandraTableThroughput updateCassandraTableThroughput,
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources"; } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
import { import {
updateMongoDBDatabaseThroughput, updateMongoDBDatabaseThroughput,
@@ -33,7 +33,7 @@ import {
migrateMongoDBDatabaseToManualThroughput, migrateMongoDBDatabaseToManualThroughput,
migrateMongoDBCollectionToAutoscale, migrateMongoDBCollectionToAutoscale,
migrateMongoDBCollectionToManualThroughput, migrateMongoDBCollectionToManualThroughput,
updateMongoDBCollectionThroughput updateMongoDBCollectionThroughput,
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources"; } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
import { import {
updateGremlinDatabaseThroughput, updateGremlinDatabaseThroughput,
@@ -41,13 +41,13 @@ import {
migrateGremlinDatabaseToManualThroughput, migrateGremlinDatabaseToManualThroughput,
migrateGremlinGraphToAutoscale, migrateGremlinGraphToAutoscale,
migrateGremlinGraphToManualThroughput, migrateGremlinGraphToManualThroughput,
updateGremlinGraphThroughput updateGremlinGraphThroughput,
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources"; } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { userContext } from "../../UserContext"; import { userContext } from "../../UserContext";
import { import {
migrateTableToAutoscale, migrateTableToAutoscale,
migrateTableToManualThroughput, migrateTableToManualThroughput,
updateTableThroughput updateTableThroughput,
} from "../../Utils/arm/generatedClients/2020-04-01/tableResources"; } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
export const updateOffer = async (params: UpdateOfferParams): Promise<Offer> => { export const updateOffer = async (params: UpdateOfferParams): Promise<Offer> => {
@@ -110,7 +110,7 @@ const updateCollectionOfferWithARM = async (params: UpdateOfferParams): Promise<
return await readCollectionOffer({ return await readCollectionOffer({
collectionId: params.collectionId, collectionId: params.collectionId,
databaseId: params.databaseId, databaseId: params.databaseId,
offerId: params.currentOffer.id offerId: params.currentOffer.id,
}); });
}; };
@@ -140,7 +140,7 @@ const updateDatabaseOfferWithARM = async (params: UpdateOfferParams): Promise<Of
return await readDatabaseOffer({ return await readDatabaseOffer({
databaseId: params.databaseId, databaseId: params.databaseId,
offerId: params.currentOffer.id offerId: params.currentOffer.id,
}); });
}; };
@@ -358,13 +358,13 @@ const updateGremlinDatabaseOffer = async (params: UpdateOfferParams): Promise<vo
const createUpdateOfferBody = (params: UpdateOfferParams): ThroughputSettingsUpdateParameters => { const createUpdateOfferBody = (params: UpdateOfferParams): ThroughputSettingsUpdateParameters => {
const body: ThroughputSettingsUpdateParameters = { const body: ThroughputSettingsUpdateParameters = {
properties: { properties: {
resource: {} resource: {},
} },
}; };
if (params.autopilotThroughput) { if (params.autopilotThroughput) {
body.properties.resource.autoscaleSettings = { body.properties.resource.autoscaleSettings = {
maxThroughput: params.autopilotThroughput maxThroughput: params.autopilotThroughput,
}; };
} else { } else {
body.properties.resource.throughput = params.manualThroughput; body.properties.resource.throughput = params.manualThroughput;
@@ -378,7 +378,7 @@ const updateOfferWithSDK = async (params: UpdateOfferParams): Promise<Offer> =>
const newOffer: SDKOfferDefinition = { const newOffer: SDKOfferDefinition = {
content: { content: {
offerThroughput: undefined, offerThroughput: undefined,
offerIsRUPerMinuteThroughputEnabled: false offerIsRUPerMinuteThroughputEnabled: false,
}, },
_etag: undefined, _etag: undefined,
_ts: undefined, _ts: undefined,
@@ -388,12 +388,12 @@ const updateOfferWithSDK = async (params: UpdateOfferParams): Promise<Offer> =>
offerResourceId: sdkOfferDefinition.offerResourceId, offerResourceId: sdkOfferDefinition.offerResourceId,
offerVersion: sdkOfferDefinition.offerVersion, offerVersion: sdkOfferDefinition.offerVersion,
offerType: sdkOfferDefinition.offerType, offerType: sdkOfferDefinition.offerType,
resource: sdkOfferDefinition.resource resource: sdkOfferDefinition.resource,
}; };
if (params.autopilotThroughput) { if (params.autopilotThroughput) {
newOffer.content.offerAutopilotSettings = { newOffer.content.offerAutopilotSettings = {
maxThroughput: params.autopilotThroughput maxThroughput: params.autopilotThroughput,
}; };
} else { } else {
newOffer.content.offerThroughput = params.manualThroughput; newOffer.content.offerThroughput = params.manualThroughput;
@@ -402,12 +402,12 @@ const updateOfferWithSDK = async (params: UpdateOfferParams): Promise<Offer> =>
const options: RequestOptions = {}; const options: RequestOptions = {};
if (params.migrateToAutoPilot) { if (params.migrateToAutoPilot) {
options.initialHeaders = { options.initialHeaders = {
[HttpHeaders.migrateOfferToAutopilot]: "true" [HttpHeaders.migrateOfferToAutopilot]: "true",
}; };
delete newOffer.content.offerAutopilotSettings; delete newOffer.content.offerAutopilotSettings;
} else if (params.migrateToManual) { } else if (params.migrateToManual) {
options.initialHeaders = { options.initialHeaders = {
[HttpHeaders.migrateOfferToManualThroughput]: "true" [HttpHeaders.migrateOfferToManualThroughput]: "true",
}; };
newOffer.content.offerAutopilotSettings = { maxThroughput: 0 }; newOffer.content.offerAutopilotSettings = { maxThroughput: 0 };
} }

View File

@@ -3,12 +3,12 @@ import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType
import { Resource, StoredProcedureDefinition } from "@azure/cosmos"; import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
import { import {
SqlStoredProcedureCreateUpdateParameters, SqlStoredProcedureCreateUpdateParameters,
SqlStoredProcedureResource SqlStoredProcedureResource,
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01/types";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { import {
createUpdateSqlStoredProcedure, createUpdateSqlStoredProcedure,
getSqlStoredProcedure getSqlStoredProcedure,
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { handleError } from "../ErrorHandlingUtils"; import { handleError } from "../ErrorHandlingUtils";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
@@ -39,8 +39,8 @@ export async function updateStoredProcedure(
const createSprocParams: SqlStoredProcedureCreateUpdateParameters = { const createSprocParams: SqlStoredProcedureCreateUpdateParameters = {
properties: { properties: {
resource: storedProcedure as SqlStoredProcedureResource, resource: storedProcedure as SqlStoredProcedureResource,
options: {} options: {},
} },
}; };
const rpResponse = await createUpdateSqlStoredProcedure( const rpResponse = await createUpdateSqlStoredProcedure(
userContext.subscriptionId, userContext.subscriptionId,

View File

@@ -2,7 +2,7 @@ import { AuthType } from "../../AuthType";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType"; import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { import {
SqlTriggerCreateUpdateParameters, SqlTriggerCreateUpdateParameters,
SqlTriggerResource SqlTriggerResource,
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01/types";
import { TriggerDefinition } from "@azure/cosmos"; import { TriggerDefinition } from "@azure/cosmos";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
@@ -36,8 +36,8 @@ export async function updateTrigger(
const createTriggerParams: SqlTriggerCreateUpdateParameters = { const createTriggerParams: SqlTriggerCreateUpdateParameters = {
properties: { properties: {
resource: trigger as SqlTriggerResource, resource: trigger as SqlTriggerResource,
options: {} options: {},
} },
}; };
const rpResponse = await createUpdateSqlTrigger( const rpResponse = await createUpdateSqlTrigger(
userContext.subscriptionId, userContext.subscriptionId,

View File

@@ -3,12 +3,12 @@ import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos"; import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
import { import {
SqlUserDefinedFunctionCreateUpdateParameters, SqlUserDefinedFunctionCreateUpdateParameters,
SqlUserDefinedFunctionResource SqlUserDefinedFunctionResource,
} from "../../Utils/arm/generatedClients/2020-04-01/types"; } from "../../Utils/arm/generatedClients/2020-04-01/types";
import { client } from "../CosmosClient"; import { client } from "../CosmosClient";
import { import {
createUpdateSqlUserDefinedFunction, createUpdateSqlUserDefinedFunction,
getSqlUserDefinedFunction getSqlUserDefinedFunction,
} from "../../Utils/arm/generatedClients/2020-04-01/sqlResources"; } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { handleError } from "../ErrorHandlingUtils"; import { handleError } from "../ErrorHandlingUtils";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
@@ -39,8 +39,8 @@ export async function updateUserDefinedFunction(
const createUDFParams: SqlUserDefinedFunctionCreateUpdateParameters = { const createUDFParams: SqlUserDefinedFunctionCreateUpdateParameters = {
properties: { properties: {
resource: userDefinedFunction as SqlUserDefinedFunctionResource, resource: userDefinedFunction as SqlUserDefinedFunctionResource,
options: {} options: {},
} },
}; };
const rpResponse = await createUpdateSqlUserDefinedFunction( const rpResponse = await createUpdateSqlUserDefinedFunction(
userContext.subscriptionId, userContext.subscriptionId,

View File

@@ -1,10 +1,10 @@
export enum Platform { export enum Platform {
Portal = "Portal", Portal = "Portal",
Hosted = "Hosted", Hosted = "Hosted",
Emulator = "Emulator" Emulator = "Emulator",
} }
interface ConfigContext { export interface ConfigContext {
platform: Platform; platform: Platform;
allowedParentFrameOrigins: string[]; allowedParentFrameOrigins: string[];
gitSha?: string; gitSha?: string;
@@ -26,6 +26,7 @@ interface ConfigContext {
GITHUB_CLIENT_SECRET?: string; // No need to inject secret for prod. Juno already knows it. GITHUB_CLIENT_SECRET?: string; // No need to inject secret for prod. Juno already knows it.
hostedExplorerURL: string; hostedExplorerURL: string;
armAPIVersion?: string; armAPIVersion?: string;
ENABLE_GALLERY_PUBLISH?: boolean;
} }
// Default configuration // Default configuration
@@ -37,7 +38,7 @@ let configContext: Readonly<ConfigContext> = {
`^https:\\/\\/[\\.\\w]*portal\\.microsoftazure.de$`, `^https:\\/\\/[\\.\\w]*portal\\.microsoftazure.de$`,
`^https:\\/\\/[\\.\\w]*ext\\.azure\\.(com|cn|us)$`, `^https:\\/\\/[\\.\\w]*ext\\.azure\\.(com|cn|us)$`,
`^https:\\/\\/[\\.\\w]*\\.ext\\.microsoftazure\\.de$`, `^https:\\/\\/[\\.\\w]*\\.ext\\.microsoftazure\\.de$`,
`^https://cosmos-db-dataexplorer-germanycentral.azurewebsites.de$` `^https://cosmos-db-dataexplorer-germanycentral.azurewebsites.de$`,
], ],
// Webpack injects this at build time // Webpack injects this at build time
gitSha: process.env.GIT_SHA, gitSha: process.env.GIT_SHA,
@@ -52,7 +53,7 @@ let configContext: Readonly<ConfigContext> = {
ARCADIA_LIVY_ENDPOINT_DNS_ZONE: "dev.azuresynapse.net", ARCADIA_LIVY_ENDPOINT_DNS_ZONE: "dev.azuresynapse.net",
GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/settings/applications/1189306 GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/settings/applications/1189306
JUNO_ENDPOINT: "https://tools.cosmos.azure.com", JUNO_ENDPOINT: "https://tools.cosmos.azure.com",
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com" BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
}; };
export function resetConfigContext(): void { export function resetConfigContext(): void {
@@ -73,20 +74,24 @@ if (process.env.NODE_ENV === "development") {
BACKEND_ENDPOINT: "https://localhost:" + port, BACKEND_ENDPOINT: "https://localhost:" + port,
MONGO_BACKEND_ENDPOINT: "https://localhost:" + port, MONGO_BACKEND_ENDPOINT: "https://localhost:" + port,
PROXY_PATH: "/proxy", PROXY_PATH: "/proxy",
EMULATOR_ENDPOINT: "https://localhost:8081" EMULATOR_ENDPOINT: "https://localhost:8081",
}); });
} }
export async function initializeConfiguration(): Promise<ConfigContext> { export async function initializeConfiguration(): Promise<ConfigContext> {
try { try {
const response = await fetch("./config.json"); const response = await fetch("./config.json", {
headers: {
"If-None-Match": "", // disable client side cache
},
});
if (response.status === 200) { if (response.status === 200) {
try { try {
const { allowedParentFrameOrigins, ...externalConfig } = await response.json(); const { allowedParentFrameOrigins, ...externalConfig } = await response.json();
Object.assign(configContext, externalConfig); Object.assign(configContext, externalConfig);
if (allowedParentFrameOrigins && allowedParentFrameOrigins.length > 0) { if (allowedParentFrameOrigins && allowedParentFrameOrigins.length > 0) {
updateConfigContext({ updateConfigContext({
allowedParentFrameOrigins: [...configContext.allowedParentFrameOrigins, ...allowedParentFrameOrigins] allowedParentFrameOrigins: [...configContext.allowedParentFrameOrigins, ...allowedParentFrameOrigins],
}); });
} }
} catch (error) { } catch (error) {
@@ -104,7 +109,7 @@ export async function initializeConfiguration(): Promise<ConfigContext> {
const platform = params.get("platform"); const platform = params.get("platform");
switch (platform) { switch (platform) {
default: default:
console.log("Invalid platform query parameter given, ignoring"); console.error(`Invalid platform query parameter: ${platform}`);
break; break;
case Platform.Portal: case Platform.Portal:
case Platform.Hosted: case Platform.Hosted:
@@ -113,7 +118,7 @@ export async function initializeConfiguration(): Promise<ConfigContext> {
} }
} }
} catch (error) { } catch (error) {
console.log("No configuration file found using defaults"); console.error("No configuration file found using defaults");
} }
return configContext; return configContext;
} }

View File

@@ -7,7 +7,7 @@ export enum TabKind {
TableEntities, TableEntities,
Graph, Graph,
SQLQuery, SQLQuery,
ScaleSettings ScaleSettings,
} }
/** /**
@@ -20,7 +20,7 @@ export enum PaneKind {
DeleteDatabase, DeleteDatabase,
GlobalSettings, GlobalSettings,
AdHocAccess, AdHocAccess,
SwitchDirectory SwitchDirectory,
} }
/** /**
@@ -79,5 +79,5 @@ export enum ActionType {
OpenCollectionTab, OpenCollectionTab,
OpenPane, OpenPane,
TransmitCachedData, TransmitCachedData,
OpenSampleNotebook OpenSampleNotebook,
} }

View File

@@ -56,7 +56,7 @@ export enum ApiKind {
Table, Table,
Cassandra, Cassandra,
Graph, Graph,
MongoDBCompute MongoDBCompute,
} }
export interface GenerateTokenResponse { export interface GenerateTokenResponse {
@@ -210,9 +210,9 @@ export interface QueryMetrics {
export interface Offer { export interface Offer {
id: string; id: string;
autoscaleMaxThroughput: number; autoscaleMaxThroughput: number | undefined;
manualThroughput: number; manualThroughput: number | undefined;
minimumThroughput: number; minimumThroughput: number | undefined;
offerDefinition?: SDKOfferDefinition; offerDefinition?: SDKOfferDefinition;
offerReplacePending: boolean; offerReplacePending: boolean;
} }
@@ -334,7 +334,7 @@ export interface Notification {
export enum ConflictResolutionMode { export enum ConflictResolutionMode {
Custom = "Custom", Custom = "Custom",
LastWriterWins = "LastWriterWins" LastWriterWins = "LastWriterWins",
} }
/** /**
@@ -472,7 +472,7 @@ export interface SparkClusterEndpoint {
export enum SparkClusterEndpointKind { export enum SparkClusterEndpointKind {
SparkUI = "SparkUI", SparkUI = "SparkUI",
HistoryServerUI = "HistoryServerUI", HistoryServerUI = "HistoryServerUI",
Livy = "Livy" Livy = "Livy",
} }
export interface RpParameters { export interface RpParameters {
@@ -587,11 +587,3 @@ export interface MemoryUsageInfo {
freeKB: number; freeKB: number;
totalKB: number; totalKB: number;
} }
export interface resourceTokenConnectionStringProperties {
accountEndpoint: string;
collectionId: string;
databaseId: string;
partitionKey?: string;
resourceToken: string;
}

View File

@@ -21,7 +21,7 @@ export enum LogEntryLevel {
/** /**
* Error level. * Error level.
*/ */
Error = 2 Error = 2,
} }
/** /**
* Schema of a log entry. * Schema of a log entry.

View File

@@ -33,7 +33,6 @@ export enum MessageTypes {
CreateWorkspace, CreateWorkspace,
CreateSparkPool, CreateSparkPool,
RefreshDatabaseAccount, RefreshDatabaseAccount,
InitTestExplorer
} }
export { Versions, ActionContracts, Diagnostics }; export { Versions, ActionContracts, Diagnostics };

View File

@@ -3,5 +3,5 @@ export enum SubscriptionType {
EA, EA,
Free, Free,
Internal, Internal,
PAYG PAYG,
} }

View File

@@ -3,9 +3,8 @@ import {
Resource, Resource,
StoredProcedureDefinition, StoredProcedureDefinition,
TriggerDefinition, TriggerDefinition,
UserDefinedFunctionDefinition UserDefinedFunctionDefinition,
} from "@azure/cosmos"; } from "@azure/cosmos";
import Q from "q";
import { CommandButtonComponentProps } from "../Explorer/Controls/CommandButton/CommandButtonComponent"; import { CommandButtonComponentProps } from "../Explorer/Controls/CommandButton/CommandButtonComponent";
import Explorer from "../Explorer/Explorer"; import Explorer from "../Explorer/Explorer";
import { ConsoleData } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleData } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
@@ -15,6 +14,7 @@ import DocumentId from "../Explorer/Tree/DocumentId";
import StoredProcedure from "../Explorer/Tree/StoredProcedure"; import StoredProcedure from "../Explorer/Tree/StoredProcedure";
import Trigger from "../Explorer/Tree/Trigger"; import Trigger from "../Explorer/Tree/Trigger";
import UserDefinedFunction from "../Explorer/Tree/UserDefinedFunction"; import UserDefinedFunction from "../Explorer/Tree/UserDefinedFunction";
import { SelfServeType } from "../SelfServe/SelfServeUtils";
import { UploadDetails } from "../workers/upload/definitions"; import { UploadDetails } from "../workers/upload/definitions";
import * as DataModels from "./DataModels"; import * as DataModels from "./DataModels";
import { SubscriptionType } from "./SubscriptionType"; import { SubscriptionType } from "./SubscriptionType";
@@ -91,6 +91,7 @@ export interface Database extends TreeNode {
onDeleteDatabaseContextMenuClick(source: Database, event: MouseEvent | KeyboardEvent): void; onDeleteDatabaseContextMenuClick(source: Database, event: MouseEvent | KeyboardEvent): void;
onSettingsClick: () => void; onSettingsClick: () => void;
loadOffer(): Promise<void>; loadOffer(): Promise<void>;
getPendingThroughputSplitNotification(): Promise<DataModels.Notification>;
} }
export interface CollectionBase extends TreeNode { export interface CollectionBase extends TreeNode {
@@ -108,7 +109,7 @@ export interface CollectionBase extends TreeNode {
onDocumentDBDocumentsClick(): void; onDocumentDBDocumentsClick(): void;
onNewQueryClick(source: any, event: MouseEvent, queryText?: string): void; onNewQueryClick(source: any, event: MouseEvent, queryText?: string): void;
expandCollection(): Q.Promise<any>; expandCollection(): void;
collapseCollection(): void; collapseCollection(): void;
getDatabase(): Database; getDatabase(): Database;
} }
@@ -137,7 +138,6 @@ export interface Collection extends CollectionBase {
openTab(): void; openTab(): void;
onSettingsClick: () => Promise<void>; onSettingsClick: () => Promise<void>;
onDeleteCollectionContextMenuClick(source: Collection, event: MouseEvent): void;
onNewGraphClick(): void; onNewGraphClick(): void;
onNewMongoQueryClick(source: any, event: MouseEvent, queryText?: string): void; onNewMongoQueryClick(source: any, event: MouseEvent, queryText?: string): void;
@@ -175,9 +175,10 @@ export interface Collection extends CollectionBase {
onDragOver(source: Collection, event: { originalEvent: DragEvent }): void; onDragOver(source: Collection, event: { originalEvent: DragEvent }): void;
onDrop(source: Collection, event: { originalEvent: DragEvent }): void; onDrop(source: Collection, event: { originalEvent: DragEvent }): void;
uploadFiles(fileList: FileList): Q.Promise<UploadDetails>; uploadFiles(fileList: FileList): Promise<UploadDetails>;
getLabel(): string; getLabel(): string;
getPendingThroughputSplitNotification(): Promise<DataModels.Notification>;
} }
/** /**
@@ -195,7 +196,7 @@ export interface PaneOptions {
export enum NeighborType { export enum NeighborType {
SOURCES_ONLY, SOURCES_ONLY,
TARGETS_ONLY, TARGETS_ONLY,
BOTH BOTH,
} }
/** /**
@@ -292,10 +293,6 @@ export interface DocumentsTabOptions extends TabOptions {
resourceTokenPartitionKey?: string; resourceTokenPartitionKey?: string;
} }
export interface SettingsTabV2Options extends TabOptions {
getPendingNotification: Q.Promise<DataModels.Notification>;
}
export interface ConflictsTabOptions extends TabOptions { export interface ConflictsTabOptions extends TabOptions {
partitionKey: DataModels.PartitionKey; partitionKey: DataModels.PartitionKey;
conflictIds: ko.ObservableArray<ConflictId>; conflictIds: ko.ObservableArray<ConflictId>;
@@ -325,14 +322,14 @@ export enum DocumentExplorerState {
newDocumentInvalid, newDocumentInvalid,
exisitingDocumentNoEdits, exisitingDocumentNoEdits,
exisitingDocumentDirtyValid, exisitingDocumentDirtyValid,
exisitingDocumentDirtyInvalid exisitingDocumentDirtyInvalid,
} }
export enum IndexingPolicyEditorState { export enum IndexingPolicyEditorState {
noCollectionSelected, noCollectionSelected,
noEdits, noEdits,
dirtyValid, dirtyValid,
dirtyInvalid dirtyInvalid,
} }
export enum ScriptEditorState { export enum ScriptEditorState {
@@ -340,7 +337,7 @@ export enum ScriptEditorState {
newValid, newValid,
exisitingNoEdits, exisitingNoEdits,
exisitingDirtyValid, exisitingDirtyValid,
exisitingDirtyInvalid exisitingDirtyInvalid,
} }
export enum CollectionTabKind { export enum CollectionTabKind {
@@ -362,13 +359,14 @@ export enum CollectionTabKind {
Gallery = 17, Gallery = 17,
NotebookViewer = 18, NotebookViewer = 18,
Schema = 19, Schema = 19,
SettingsV2 = 20 CollectionSettingsV2 = 20,
DatabaseSettingsV2 = 21,
} }
export enum TerminalKind { export enum TerminalKind {
Default = 0, Default = 0,
Mongo = 1, Mongo = 1,
Cassandra = 2 Cassandra = 2,
} }
export interface DataExplorerInputsFrame { export interface DataExplorerInputsFrame {
@@ -395,6 +393,7 @@ export interface DataExplorerInputsFrame {
isAuthWithresourceToken?: boolean; isAuthWithresourceToken?: boolean;
defaultCollectionThroughput?: CollectionCreationDefaults; defaultCollectionThroughput?: CollectionCreationDefaults;
flights?: readonly string[]; flights?: readonly string[];
selfServeType?: SelfServeType;
} }
export interface CollectionCreationDefaults { export interface CollectionCreationDefaults {

View File

@@ -6,19 +6,19 @@ describe("The Heatmap Control", () => {
const dataPoints = { const dataPoints = {
"1": { "1": {
"2019-06-19T00:59:10Z": { "2019-06-19T00:59:10Z": {
"Normalized Throughput": 0.35 "Normalized Throughput": 0.35,
}, },
"2019-06-19T00:48:10Z": { "2019-06-19T00:48:10Z": {
"Normalized Throughput": 0.25 "Normalized Throughput": 0.25,
} },
} },
}; };
const chartCaptions = { const chartCaptions = {
chartTitle: "chart title", chartTitle: "chart title",
yAxisTitle: "YAxisTitle", yAxisTitle: "YAxisTitle",
tooltipText: "Tooltip text", tooltipText: "Tooltip text",
timeWindow: 123456789 timeWindow: 123456789,
}; };
let heatmap: Heatmap; let heatmap: Heatmap;
@@ -75,12 +75,12 @@ describe("The Heatmap Control", () => {
if (dayjs().utcOffset()) { if (dayjs().utcOffset()) {
expect(heatmap.generateMatrixFromMap(dataPoints).xAxisPoints).not.toEqual([ expect(heatmap.generateMatrixFromMap(dataPoints).xAxisPoints).not.toEqual([
"2019-06-19T00:48:10Z", "2019-06-19T00:48:10Z",
"2019-06-19T00:59:10Z" "2019-06-19T00:59:10Z",
]); ]);
} else { } else {
expect(heatmap.generateMatrixFromMap(dataPoints).xAxisPoints).toEqual([ expect(heatmap.generateMatrixFromMap(dataPoints).xAxisPoints).toEqual([
"2019-06-19T00:48:10Z", "2019-06-19T00:48:10Z",
"2019-06-19T00:59:10Z" "2019-06-19T00:59:10Z",
]); ]);
} }
}); });
@@ -106,9 +106,9 @@ describe("iframe rendering when there is no data", () => {
data: { data: {
chartData: {}, chartData: {},
chartSettings: {}, chartSettings: {},
theme: 4 theme: 4,
} },
} },
}; };
const divElement: string = `<div id="${Heatmap.elementId}"></div>`; const divElement: string = `<div id="${Heatmap.elementId}"></div>`;
@@ -126,9 +126,9 @@ describe("iframe rendering when there is no data", () => {
data: { data: {
chartData: {}, chartData: {},
chartSettings: {}, chartSettings: {},
theme: 2 theme: 2,
} },
} },
}; };
const divElement: string = `<div id="${Heatmap.elementId}"></div>`; const divElement: string = `<div id="${Heatmap.elementId}"></div>`;

View File

@@ -9,7 +9,7 @@ import {
HeatmapData, HeatmapData,
LayoutSettings, LayoutSettings,
PartitionTimeStampToData, PartitionTimeStampToData,
PortalTheme PortalTheme,
} from "./HeatmapDatatypes"; } from "./HeatmapDatatypes";
import { isInvalidParentFrameOrigin } from "../../Utils/MessageValidation"; import { isInvalidParentFrameOrigin } from "../../Utils/MessageValidation";
import { sendCachedDataMessage, sendMessage } from "../../Common/MessageHandler"; import { sendCachedDataMessage, sendMessage } from "../../Common/MessageHandler";
@@ -43,7 +43,7 @@ export class Heatmap {
return { return {
family: StyleConstants.DataExplorerFont, family: StyleConstants.DataExplorerFont,
size, size,
color color,
}; };
} }
@@ -73,7 +73,7 @@ export class Heatmap {
return 0; return 0;
} }
} }
}) }),
}; };
// go thru all rows and create 2d matrix for heatmap... // go thru all rows and create 2d matrix for heatmap...
for (let i = 0; i < rows.length; i++) { for (let i = 0; i < rows.length; i++) {
@@ -115,7 +115,7 @@ export class Heatmap {
[0.7, "#E46612"], [0.7, "#E46612"],
[0.8, "#E64914"], [0.8, "#E64914"],
[0.9, "#B80016"], [0.9, "#B80016"],
[1.0, "#B80016"] [1.0, "#B80016"],
], ],
name: "", name: "",
hovertemplate: this._heatmapCaptions.tooltipText, hovertemplate: this._heatmapCaptions.tooltipText,
@@ -123,11 +123,11 @@ export class Heatmap {
thickness: 15, thickness: 15,
outlinewidth: 0, outlinewidth: 0,
tickcolor: StyleConstants.BaseDark, tickcolor: StyleConstants.BaseDark,
tickfont: this._getFontStyles(10, this._defaultFontColor) tickfont: this._getFontStyles(10, this._defaultFontColor),
}, },
y: this._chartData.yAxisPoints, y: this._chartData.yAxisPoints,
x: this._chartData.xAxisPoints x: this._chartData.xAxisPoints,
} },
]; ];
} }
@@ -138,7 +138,7 @@ export class Heatmap {
r: 10, r: 10,
b: 35, b: 35,
t: 30, t: 30,
pad: 0 pad: 0,
}, },
paper_bgcolor: "transparent", paper_bgcolor: "transparent",
plot_bgcolor: "transparent", plot_bgcolor: "transparent",
@@ -154,7 +154,7 @@ export class Heatmap {
autotick: true, autotick: true,
fixedrange: true, fixedrange: true,
ticks: "", ticks: "",
showticklabels: false showticklabels: false,
}, },
xaxis: { xaxis: {
fixedrange: true, fixedrange: true,
@@ -167,13 +167,13 @@ export class Heatmap {
autotick: true, autotick: true,
tickformat: this._heatmapCaptions.timeWindow > 7 ? "%I:%M %p" : "%b %e", tickformat: this._heatmapCaptions.timeWindow > 7 ? "%I:%M %p" : "%b %e",
showticklabels: true, showticklabels: true,
tickfont: this._getFontStyles(10) tickfont: this._getFontStyles(10),
}, },
title: { title: {
text: this._heatmapCaptions.chartTitle, text: this._heatmapCaptions.chartTitle,
x: 0.01, x: 0.01,
font: this._getFontStyles(13, this._defaultFontColor) font: this._getFontStyles(13, this._defaultFontColor),
} },
}; };
} }
@@ -181,7 +181,7 @@ export class Heatmap {
return { return {
/* heatmap can be fully responsive however the min-height needed in that case is greater than the iframe portal height, hence explicit width + height have been set in _getLayoutSettings /* heatmap can be fully responsive however the min-height needed in that case is greater than the iframe portal height, hence explicit width + height have been set in _getLayoutSettings
responsive: true,*/ responsive: true,*/
displayModeBar: false displayModeBar: false,
}; };
} }

View File

@@ -8,7 +8,7 @@ export enum PortalTheme {
blue = 1, blue = 1,
azure, azure,
light, light,
dark dark,
} }
export interface HeatmapData { export interface HeatmapData {

View File

@@ -4,5 +4,5 @@ export enum DefaultAccountExperienceType {
MongoDB = "MongoDB", MongoDB = "MongoDB",
Table = "Table", Table = "Table",
Cassandra = "Cassandra", Cassandra = "Cassandra",
ApiForMongoDB = "Azure Cosmos DB for MongoDB API" ApiForMongoDB = "Azure Cosmos DB for MongoDB API",
} }

View File

@@ -45,7 +45,8 @@ describe("Component Registerer", () => {
}); });
it("should register settings-tab-v2 component", () => { it("should register settings-tab-v2 component", () => {
expect(ko.components.isRegistered("settings-tab-v2")).toBe(true); expect(ko.components.isRegistered("database-settings-tab-v2")).toBe(true);
expect(ko.components.isRegistered("collection-settings-tab-v2")).toBe(true);
}); });
it("should register query-tab component", () => { it("should register query-tab component", () => {

View File

@@ -31,7 +31,7 @@ ko.components.register("mongo-documents-tab", new TabComponents.MongoDocumentsTa
ko.components.register("stored-procedure-tab", new TabComponents.StoredProcedureTab()); ko.components.register("stored-procedure-tab", new TabComponents.StoredProcedureTab());
ko.components.register("trigger-tab", new TabComponents.TriggerTab()); ko.components.register("trigger-tab", new TabComponents.TriggerTab());
ko.components.register("user-defined-function-tab", new TabComponents.UserDefinedFunctionTab()); ko.components.register("user-defined-function-tab", new TabComponents.UserDefinedFunctionTab());
ko.components.register("settings-tab-v2", new TabComponents.SettingsTabV2()); ko.components.register("collection-settings-tab-v2", new TabComponents.SettingsTabV2());
ko.components.register("query-tab", new TabComponents.QueryTab()); ko.components.register("query-tab", new TabComponents.QueryTab());
ko.components.register("tables-query-tab", new TabComponents.QueryTablesTab()); ko.components.register("tables-query-tab", new TabComponents.QueryTablesTab());
ko.components.register("graph-tab", new TabComponents.GraphTab()); ko.components.register("graph-tab", new TabComponents.GraphTab());
@@ -45,6 +45,7 @@ ko.components.register("notebook-viewer-tab", new TabComponents.NotebookViewerTa
// Database Tabs // Database Tabs
ko.components.register("database-settings-tab", new TabComponents.DatabaseSettingsTab()); ko.components.register("database-settings-tab", new TabComponents.DatabaseSettingsTab());
ko.components.register("database-settings-tab-v2", new TabComponents.SettingsTabV2());
// Panes // Panes
ko.components.register("add-database-pane", new PaneComponents.AddDatabasePaneComponent()); ko.components.register("add-database-pane", new PaneComponents.AddDatabasePaneComponent());

View File

@@ -36,8 +36,8 @@ export class ResourceTreeContextMenuButtonFactory {
{ {
iconSrc: AddCollectionIcon, iconSrc: AddCollectionIcon,
onClick: () => container.onNewCollectionClicked(), onClick: () => container.onNewCollectionClicked(),
label: container.addCollectionText() label: container.addCollectionText(),
} },
]; ];
if (userContext.defaultExperience !== DefaultAccountExperienceType.Table) { if (userContext.defaultExperience !== DefaultAccountExperienceType.Table) {
@@ -45,7 +45,7 @@ export class ResourceTreeContextMenuButtonFactory {
iconSrc: DeleteDatabaseIcon, iconSrc: DeleteDatabaseIcon,
onClick: () => container.deleteDatabaseConfirmationPane.open(), onClick: () => container.deleteDatabaseConfirmationPane.open(),
label: container.deleteDatabaseText(), label: container.deleteDatabaseText(),
styleClass: "deleteDatabaseMenuItem" styleClass: "deleteDatabaseMenuItem",
}); });
} }
return items; return items;
@@ -60,7 +60,7 @@ export class ResourceTreeContextMenuButtonFactory {
items.push({ items.push({
iconSrc: AddSqlQueryIcon, iconSrc: AddSqlQueryIcon,
onClick: () => selectedCollection && selectedCollection.onNewQueryClick(selectedCollection, null), onClick: () => selectedCollection && selectedCollection.onNewQueryClick(selectedCollection, null),
label: "New SQL Query" label: "New SQL Query",
}); });
} }
@@ -68,7 +68,7 @@ export class ResourceTreeContextMenuButtonFactory {
items.push({ items.push({
iconSrc: AddSqlQueryIcon, iconSrc: AddSqlQueryIcon,
onClick: () => selectedCollection && selectedCollection.onNewMongoQueryClick(selectedCollection, null), onClick: () => selectedCollection && selectedCollection.onNewMongoQueryClick(selectedCollection, null),
label: "New Query" label: "New Query",
}); });
items.push({ items.push({
@@ -77,7 +77,7 @@ export class ResourceTreeContextMenuButtonFactory {
const selectedCollection: ViewModels.Collection = container.findSelectedCollection(); const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
selectedCollection && selectedCollection.onNewMongoShellClick(); selectedCollection && selectedCollection.onNewMongoShellClick();
}, },
label: "New Shell" label: "New Shell",
}); });
} }
@@ -88,7 +88,7 @@ export class ResourceTreeContextMenuButtonFactory {
const selectedCollection: ViewModels.Collection = container.findSelectedCollection(); const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
selectedCollection && selectedCollection.onNewStoredProcedureClick(selectedCollection, null); selectedCollection && selectedCollection.onNewStoredProcedureClick(selectedCollection, null);
}, },
label: "New Stored Procedure" label: "New Stored Procedure",
}); });
items.push({ items.push({
@@ -97,7 +97,7 @@ export class ResourceTreeContextMenuButtonFactory {
const selectedCollection: ViewModels.Collection = container.findSelectedCollection(); const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
selectedCollection && selectedCollection.onNewUserDefinedFunctionClick(selectedCollection, null); selectedCollection && selectedCollection.onNewUserDefinedFunctionClick(selectedCollection, null);
}, },
label: "New UDF" label: "New UDF",
}); });
items.push({ items.push({
@@ -106,18 +106,15 @@ export class ResourceTreeContextMenuButtonFactory {
const selectedCollection: ViewModels.Collection = container.findSelectedCollection(); const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
selectedCollection && selectedCollection.onNewTriggerClick(selectedCollection, null); selectedCollection && selectedCollection.onNewTriggerClick(selectedCollection, null);
}, },
label: "New Trigger" label: "New Trigger",
}); });
} }
items.push({ items.push({
iconSrc: DeleteCollectionIcon, iconSrc: DeleteCollectionIcon,
onClick: () => { onClick: () => container.openDeleteCollectionConfirmationPane(),
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
selectedCollection && selectedCollection.onDeleteCollectionContextMenuClick(selectedCollection, null);
},
label: container.deleteCollectionText(), label: container.deleteCollectionText(),
styleClass: "deleteCollectionMenuItem" styleClass: "deleteCollectionMenuItem",
}); });
return items; return items;
@@ -135,8 +132,8 @@ export class ResourceTreeContextMenuButtonFactory {
{ {
iconSrc: DeleteSprocIcon, iconSrc: DeleteSprocIcon,
onClick: () => storedProcedure.delete(), onClick: () => storedProcedure.delete(),
label: "Delete Store Procedure" label: "Delete Store Procedure",
} },
]; ];
} }
@@ -149,8 +146,8 @@ export class ResourceTreeContextMenuButtonFactory {
{ {
iconSrc: DeleteTriggerIcon, iconSrc: DeleteTriggerIcon,
onClick: () => trigger.delete(), onClick: () => trigger.delete(),
label: "Delete Trigger" label: "Delete Trigger",
} },
]; ];
} }
@@ -166,8 +163,8 @@ export class ResourceTreeContextMenuButtonFactory {
{ {
iconSrc: DeleteUDFIcon, iconSrc: DeleteUDFIcon,
onClick: () => userDefinedFunction.delete(), onClick: () => userDefinedFunction.delete(),
label: "Delete User Defined Function" label: "Delete User Defined Function",
} },
]; ];
} }
} }

View File

@@ -31,7 +31,7 @@ export class AccessibleElement extends React.Component<AccessibleElementProps> {
...elementProps, ...elementProps,
onKeyPress: this.onKeyPress, onKeyPress: this.onKeyPress,
onClick: this.props.onActivated, onClick: this.props.onActivated,
tabIndex tabIndex,
}); });
} }
} }

View File

@@ -38,7 +38,7 @@ export class AccordionItemComponent extends React.Component<AccordionItemCompone
super(props); super(props);
this.isExpanded = props.isExpanded; this.isExpanded = props.isExpanded;
this.state = { this.state = {
isExpanded: true isExpanded: true,
}; };
} }
@@ -46,7 +46,7 @@ export class AccordionItemComponent extends React.Component<AccordionItemCompone
if (this.props.isExpanded !== this.isExpanded) { if (this.props.isExpanded !== this.isExpanded) {
this.isExpanded = this.props.isExpanded; this.isExpanded = this.props.isExpanded;
this.setState({ this.setState({
isExpanded: this.props.isExpanded isExpanded: this.props.isExpanded,
}); });
} }
} }

View File

@@ -1,159 +0,0 @@
import React from "react";
import { shallow, mount } from "enzyme";
import { AccountSwitchComponent, AccountSwitchComponentProps } from "./AccountSwitchComponent";
import { AuthType } from "../../../AuthType";
import { DatabaseAccount, Subscription } from "../../../Contracts/DataModels";
import { AccountKind } from "../../../Common/Constants";
const createBlankProps = (): AccountSwitchComponentProps => {
return {
authType: null,
displayText: "",
accounts: [],
selectedAccountName: null,
isLoadingAccounts: false,
onAccountChange: jest.fn(),
subscriptions: [],
selectedSubscriptionId: null,
isLoadingSubscriptions: false,
onSubscriptionChange: jest.fn()
};
};
const createBlankAccount = (): DatabaseAccount => {
return {
id: "",
kind: AccountKind.Default,
name: "",
properties: null,
location: "",
tags: null,
type: ""
};
};
const createBlankSubscription = (): Subscription => {
return {
subscriptionId: "",
displayName: "",
authorizationSource: "",
state: "",
subscriptionPolicies: null,
tenantId: "",
uniqueDisplayName: ""
};
};
const createFullProps = (): AccountSwitchComponentProps => {
const props = createBlankProps();
props.authType = AuthType.AAD;
const account1 = createBlankAccount();
account1.name = "account1";
const account2 = createBlankAccount();
account2.name = "account2";
const account3 = createBlankAccount();
account3.name = "superlongaccountnamestringtest";
props.accounts = [account1, account2, account3];
props.selectedAccountName = "account2";
const sub1 = createBlankSubscription();
sub1.displayName = "sub1";
sub1.subscriptionId = "a6062a74-5d53-4b20-9545-000b95f22297";
const sub2 = createBlankSubscription();
sub2.displayName = "subsubsubsubsubsubsub2";
sub2.subscriptionId = "b20b3e93-0185-4326-8a9c-d44bac276b6b";
props.subscriptions = [sub1, sub2];
props.selectedSubscriptionId = "a6062a74-5d53-4b20-9545-000b95f22297";
return props;
};
describe("test render", () => {
it("renders no auth type -> handle error in code", () => {
const props = createBlankProps();
const wrapper = shallow(<AccountSwitchComponent {...props} />);
expect(wrapper).toMatchSnapshot();
});
// Encrypted Token
it("renders auth security token, with selected account name", () => {
const props = createBlankProps();
props.authType = AuthType.EncryptedToken;
props.selectedAccountName = "testaccount";
const wrapper = shallow(<AccountSwitchComponent {...props} />);
expect(wrapper).toMatchSnapshot();
});
// AAD
it("renders auth aad, with all information", () => {
const props = createFullProps();
const wrapper = shallow(<AccountSwitchComponent {...props} />);
expect(wrapper).toMatchSnapshot();
});
it("renders auth aad all dropdown menus", () => {
const props = createFullProps();
const wrapper = mount(<AccountSwitchComponent {...props} />);
expect(wrapper.exists("div.accountSwitchContextualMenu")).toBe(false);
wrapper.find("button.accountSwitchButton").simulate("click");
expect(wrapper.exists("div.accountSwitchContextualMenu")).toBe(true);
expect(wrapper.exists("div.accountSwitchSubscriptionDropdown")).toBe(true);
wrapper.find("DropdownBase.accountSwitchSubscriptionDropdown").simulate("click");
// Click will dismiss the first contextual menu in enzyme. Need to dig deeper to achieve below test
// expect(wrapper.exists("div.accountSwitchSubscriptionDropdownMenu")).toBe(true);
// expect(wrapper.find("button.ms-Dropdown-item").length).toBe(2);
// wrapper.find("div.accountSwitchSubscriptionDropdown").simulate("click");
// expect(wrapper.exists("div.accountSwitchSubscriptionDropdownMenu")).toBe(false);
// expect(wrapper.exists("div.accountSwitchAccountDropdown")).toBe(true);
// wrapper.find("div.accountSwitchAccountDropdown").simulate("click");
// expect(wrapper.exists("div.accountSwitchAccountDropdownMenu")).toBe(true);
// expect(wrapper.find("button.ms-Dropdown-item").length).toBe(3);
// wrapper.find("div.accountSwitchAccountDropdown").simulate("click");
// expect(wrapper.exists("div.accountSwitchAccountDropdownMenu")).toBe(false);
// wrapper.find("button.accountSwitchButton").simulate("click");
// expect(wrapper.exists("div.accountSwitchContextualMenu")).toBe(false);
wrapper.unmount();
});
});
// describe("test function", () => {
// it("switch subscription function", () => {
// const props = createFullProps();
// const wrapper = mount(<AccountSwitchComponent {...props} />);
// wrapper.find("button.accountSwitchButton").simulate("click");
// wrapper.find("div.accountSwitchSubscriptionDropdown").simulate("click");
// wrapper
// .find("button.ms-Dropdown-item")
// .at(1)
// .simulate("click");
// expect(props.onSubscriptionChange).toBeCalled();
// expect(props.onSubscriptionChange).toHaveBeenCalled();
// wrapper.unmount();
// });
// it("switch account", () => {
// const props = createFullProps();
// const wrapper = mount(<AccountSwitchComponent {...props} />);
// wrapper.find("button.accountSwitchButton").simulate("click");
// wrapper.find("div.accountSwitchAccountDropdown").simulate("click");
// wrapper
// .find("button.ms-Dropdown-item")
// .at(0)
// .simulate("click");
// expect(props.onAccountChange).toBeCalled();
// expect(props.onAccountChange).toHaveBeenCalled();
// wrapper.unmount();
// });
// });

View File

@@ -1,177 +0,0 @@
import { AuthType } from "../../../AuthType";
import { StyleConstants } from "../../../Common/Constants";
import { DatabaseAccount, Subscription } from "../../../Contracts/DataModels";
import * as React from "react";
import { DefaultButton, IButtonStyles, IButtonProps } from "office-ui-fabric-react/lib/Button";
import { IContextualMenuProps } from "office-ui-fabric-react/lib/ContextualMenu";
import { Dropdown, IDropdownOption, IDropdownProps } from "office-ui-fabric-react/lib/Dropdown";
export interface AccountSwitchComponentProps {
authType: AuthType;
selectedAccountName: string;
accounts: DatabaseAccount[];
isLoadingAccounts: boolean;
onAccountChange: (newAccount: DatabaseAccount) => void;
selectedSubscriptionId: string;
subscriptions: Subscription[];
isLoadingSubscriptions: boolean;
onSubscriptionChange: (newSubscription: Subscription) => void;
displayText?: string;
}
export class AccountSwitchComponent extends React.Component<AccountSwitchComponentProps> {
public render(): JSX.Element {
return this.props.authType === AuthType.AAD ? this._renderSwitchDropDown() : this._renderAccountName();
}
private _renderSwitchDropDown(): JSX.Element {
const { displayText, selectedAccountName } = this.props;
const menuProps: IContextualMenuProps = {
directionalHintFixed: true,
className: "accountSwitchContextualMenu",
items: [
{
key: "switchSubscription",
onRender: this._renderSubscriptionDropdown.bind(this)
},
{
key: "switchAccount",
onRender: this._renderAccountDropDown.bind(this)
}
]
};
const buttonStyles: IButtonStyles = {
root: {
fontSize: StyleConstants.DefaultFontSize,
height: 40,
padding: 0,
paddingLeft: 10,
marginRight: 5,
backgroundColor: StyleConstants.BaseDark,
color: StyleConstants.BaseLight
},
rootHovered: {
backgroundColor: StyleConstants.BaseHigh,
color: StyleConstants.BaseLight
},
rootFocused: {
backgroundColor: StyleConstants.BaseHigh,
color: StyleConstants.BaseLight
},
rootPressed: {
backgroundColor: StyleConstants.BaseHigh,
color: StyleConstants.BaseLight
},
rootExpanded: {
backgroundColor: StyleConstants.BaseHigh,
color: StyleConstants.BaseLight
},
textContainer: {
flexGrow: "initial"
}
};
const buttonProps: IButtonProps = {
text: displayText || selectedAccountName,
menuProps: menuProps,
styles: buttonStyles,
className: "accountSwitchButton",
id: "accountSwitchButton"
};
return <DefaultButton {...buttonProps} />;
}
private _renderSubscriptionDropdown(): JSX.Element {
const { subscriptions, selectedSubscriptionId, isLoadingSubscriptions } = this.props;
const options: IDropdownOption[] = subscriptions.map(sub => {
return {
key: sub.subscriptionId,
text: sub.displayName,
data: sub
};
});
const placeHolderText = isLoadingSubscriptions
? "Loading subscriptions"
: !options || !options.length
? "No subscriptions found in current directory"
: "Select subscription from list";
const dropdownProps: IDropdownProps = {
label: "Subscription",
className: "accountSwitchSubscriptionDropdown",
options: options,
onChange: this._onSubscriptionDropdownChange,
defaultSelectedKey: selectedSubscriptionId,
placeholder: placeHolderText,
styles: {
callout: "accountSwitchSubscriptionDropdownMenu"
}
};
return <Dropdown {...dropdownProps} />;
}
private _onSubscriptionDropdownChange = (e: React.FormEvent<HTMLDivElement>, option: IDropdownOption): void => {
if (!option) {
return;
}
this.props.onSubscriptionChange(option.data);
};
private _renderAccountDropDown(): JSX.Element {
const { accounts, selectedAccountName, isLoadingAccounts } = this.props;
const options: IDropdownOption[] = accounts.map(account => {
return {
key: account.name,
text: account.name,
data: account
};
});
// Fabric UI will also try to select the first non-disabled option from dropdown.
// Add a option to prevent pop the message when user click on dropdown on first time.
options.unshift({
key: "select from list",
text: "Select Cosmos DB account from list",
data: undefined
});
const placeHolderText = isLoadingAccounts
? "Loading Cosmos DB accounts"
: !options || !options.length
? "No Cosmos DB accounts found"
: "Select Cosmos DB account from list";
const dropdownProps: IDropdownProps = {
label: "Cosmos DB Account Name",
className: "accountSwitchAccountDropdown",
options: options,
onChange: this._onAccountDropdownChange,
defaultSelectedKey: selectedAccountName,
placeholder: placeHolderText,
styles: {
callout: "accountSwitchAccountDropdownMenu"
}
};
return <Dropdown {...dropdownProps} />;
}
private _onAccountDropdownChange = (e: React.FormEvent<HTMLDivElement>, option: IDropdownOption): void => {
if (!option) {
return;
}
this.props.onAccountChange(option.data);
};
private _renderAccountName(): JSX.Element {
const { displayText, selectedAccountName } = this.props;
return <span className="accountNameHeader">{displayText || selectedAccountName}</span>;
}
}

View File

@@ -1,11 +0,0 @@
import * as React from "react";
import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
import { AccountSwitchComponent, AccountSwitchComponentProps } from "./AccountSwitchComponent";
export class AccountSwitchComponentAdapter implements ReactAdapter {
public parameters: ko.Observable<AccountSwitchComponentProps>;
public renderComponent(): JSX.Element {
return <AccountSwitchComponent {...this.parameters()} />;
}
}

View File

@@ -1,71 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`test render renders auth aad, with all information 1`] = `
<CustomizedDefaultButton
className="accountSwitchButton"
id="accountSwitchButton"
menuProps={
Object {
"className": "accountSwitchContextualMenu",
"directionalHintFixed": true,
"items": Array [
Object {
"key": "switchSubscription",
"onRender": [Function],
},
Object {
"key": "switchAccount",
"onRender": [Function],
},
],
}
}
styles={
Object {
"root": Object {
"backgroundColor": undefined,
"color": undefined,
"fontSize": undefined,
"height": 40,
"marginRight": 5,
"padding": 0,
"paddingLeft": 10,
},
"rootExpanded": Object {
"backgroundColor": undefined,
"color": undefined,
},
"rootFocused": Object {
"backgroundColor": undefined,
"color": undefined,
},
"rootHovered": Object {
"backgroundColor": undefined,
"color": undefined,
},
"rootPressed": Object {
"backgroundColor": undefined,
"color": undefined,
},
"textContainer": Object {
"flexGrow": "initial",
},
}
}
text="account2"
/>
`;
exports[`test render renders auth security token, with selected account name 1`] = `
<span
className="accountNameHeader"
>
testaccount
</span>
`;
exports[`test render renders no auth type -> handle error in code 1`] = `
<span
className="accountNameHeader"
/>
`;

View File

@@ -30,7 +30,7 @@ export class ArcadiaMenuPicker extends React.Component<ArcadiaMenuPickerProps, A
constructor(props: ArcadiaMenuPickerProps) { constructor(props: ArcadiaMenuPickerProps) {
super(props); super(props);
this.state = { this.state = {
selectedSparkPool: props.selectedSparkPool selectedSparkPool: props.selectedSparkPool,
}; };
} }
@@ -41,7 +41,7 @@ export class ArcadiaMenuPicker extends React.Component<ArcadiaMenuPickerProps, A
try { try {
this.props.onSparkPoolSelect(e, item); this.props.onSparkPoolSelect(e, item);
this.setState({ this.setState({
selectedSparkPool: item.text selectedSparkPool: item.text,
}); });
} catch (error) { } catch (error) {
Logger.logError(getErrorMessage(error), "ArcadiaMenuPicker/_onSparkPoolClicked"); Logger.logError(getErrorMessage(error), "ArcadiaMenuPicker/_onSparkPoolClicked");
@@ -65,28 +65,28 @@ export class ArcadiaMenuPicker extends React.Component<ArcadiaMenuPickerProps, A
public render() { public render() {
const { workspaces } = this.props; const { workspaces } = this.props;
let workspaceMenuItems: IContextualMenuItem[] = workspaces.map(workspace => { let workspaceMenuItems: IContextualMenuItem[] = workspaces.map((workspace) => {
let sparkPoolsMenuProps: IContextualMenuProps = { let sparkPoolsMenuProps: IContextualMenuProps = {
items: workspace.sparkPools.map( items: workspace.sparkPools.map(
(sparkpool): IContextualMenuItem => ({ (sparkpool): IContextualMenuItem => ({
key: sparkpool.id, key: sparkpool.id,
text: sparkpool.name, text: sparkpool.name,
onClick: this._onSparkPoolClicked onClick: this._onSparkPoolClicked,
}) })
) ),
}; };
if (!sparkPoolsMenuProps.items.length) { if (!sparkPoolsMenuProps.items.length) {
sparkPoolsMenuProps.items.push({ sparkPoolsMenuProps.items.push({
key: workspace.id, key: workspace.id,
text: "Create new spark pool", text: "Create new spark pool",
onClick: this._onCreateNewSparkPoolClicked onClick: this._onCreateNewSparkPoolClicked,
}); });
} }
return { return {
key: workspace.id, key: workspace.id,
text: workspace.name, text: workspace.name,
subMenuProps: this.props.disableSubmenu ? undefined : sparkPoolsMenuProps subMenuProps: this.props.disableSubmenu ? undefined : sparkPoolsMenuProps,
}; };
}); });
@@ -94,7 +94,7 @@ export class ArcadiaMenuPicker extends React.Component<ArcadiaMenuPickerProps, A
workspaceMenuItems.push({ workspaceMenuItems.push({
key: "create_workspace", key: "create_workspace",
text: "Create new workspace", text: "Create new workspace",
onClick: this._onCreateNewWorkspaceClicked onClick: this._onCreateNewWorkspaceClicked,
}); });
} }
@@ -103,29 +103,29 @@ export class ArcadiaMenuPicker extends React.Component<ArcadiaMenuPickerProps, A
backgroundColor: "transparent", backgroundColor: "transparent",
margin: "auto 5px", margin: "auto 5px",
padding: "0", padding: "0",
border: "0" border: "0",
}, },
rootHovered: { rootHovered: {
backgroundColor: "transparent" backgroundColor: "transparent",
}, },
rootChecked: { rootChecked: {
backgroundColor: "transparent" backgroundColor: "transparent",
}, },
rootFocused: { rootFocused: {
backgroundColor: "transparent" backgroundColor: "transparent",
}, },
rootExpanded: { rootExpanded: {
backgroundColor: "transparent" backgroundColor: "transparent",
}, },
flexContainer: { flexContainer: {
height: "30px", height: "30px",
border: "1px solid #a6a6a6", border: "1px solid #a6a6a6",
padding: "0 8px" padding: "0 8px",
}, },
label: { label: {
fontWeight: "400", fontWeight: "400",
fontSize: "12px" fontSize: "12px",
} },
}; };
return ( return (
@@ -134,7 +134,7 @@ export class ArcadiaMenuPicker extends React.Component<ArcadiaMenuPickerProps, A
persistMenu={true} persistMenu={true}
className="arcadia-menu-picker" className="arcadia-menu-picker"
menuProps={{ menuProps={{
items: workspaceMenuItems items: workspaceMenuItems,
}} }}
styles={dropdownStyle} styles={dropdownStyle}
/> />

Some files were not shown because too many files have changed in this diff Show More