mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-24 11:21:23 +00:00
Compare commits
13 Commits
replace-co
...
arm-np-wor
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54e853ad9a | ||
|
|
53bedb1641 | ||
|
|
e6ac5a7043 | ||
|
|
faf923f647 | ||
|
|
d471cff77c | ||
|
|
0a24a0b73e | ||
|
|
ab4753fd1d | ||
|
|
6bc506b81f | ||
|
|
efff26dbe7 | ||
|
|
fae59d8754 | ||
|
|
c2cd383ece | ||
|
|
83c120a549 | ||
|
|
a28dede88d |
@@ -266,10 +266,6 @@ src/ResourceProvider/ResourceProviderClientFactory.ts
|
||||
src/RouteHandlers/RouteHandler.ts
|
||||
src/RouteHandlers/TabRouteHandler.test.ts
|
||||
src/RouteHandlers/TabRouteHandler.ts
|
||||
src/Shared/AddCollectionUtility.test.ts
|
||||
src/Shared/AddCollectionUtility.ts
|
||||
src/Shared/AddDatabaseUtility.test.ts
|
||||
src/Shared/AddDatabaseUtility.ts
|
||||
src/Shared/Constants.ts
|
||||
src/Shared/DefaultExperienceUtility.test.ts
|
||||
src/Shared/DefaultExperienceUtility.ts
|
||||
@@ -279,8 +275,6 @@ src/Shared/StorageUtility.test.ts
|
||||
src/Shared/StorageUtility.ts
|
||||
src/Shared/StringUtility.test.ts
|
||||
src/Shared/StringUtility.ts
|
||||
src/Shared/Telemetry/TelemetryConstants.ts
|
||||
src/Shared/Telemetry/TelemetryProcessor.ts
|
||||
src/Shared/appInsights.ts
|
||||
src/SparkClusterManager/ArcadiaResourceManager.ts
|
||||
src/SparkClusterManager/SparkClusterManager.ts
|
||||
@@ -418,6 +412,5 @@ cypress/integration/dataexplorer/SQL/addCollection.spec.ts
|
||||
cypress/integration/dataexplorer/TABLE/addCollection.spec.ts
|
||||
cypress/integration/notebook/newNotebook.spec.ts
|
||||
cypress/integration/notebook/resourceTree.spec.ts
|
||||
__mocks__/AddDatabaseUtility.ts
|
||||
__mocks__/monaco-editor.ts
|
||||
src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx
|
||||
@@ -1,5 +0,0 @@
|
||||
export class AddDbUtilities {
|
||||
createGremlinDatabase(params: any) {
|
||||
return Promise.resolve(1)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
"test": "cypress run",
|
||||
"wait-for-server": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/",
|
||||
"test:sql": "cypress run --browser chrome --spec \"./integration/dataexplorer/SQL/*\"",
|
||||
"test:ci": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/ https-get://0.0.0.0:8081/_explorer/index.html && cypress run --browser chrome --headless",
|
||||
"test:ci": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/ https-get://0.0.0.0:8081/_explorer/index.html && cypress run --browser edge --headless",
|
||||
"test:debug": "cypress open"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3017,4 +3017,8 @@ settings-pane {
|
||||
|
||||
.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.warningErrorContent a {
|
||||
color: @AccentMediumHigh
|
||||
}
|
||||
685
package-lock.json
generated
685
package-lock.json
generated
@@ -3430,19 +3430,78 @@
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
|
||||
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
|
||||
},
|
||||
"@fluentui/date-time-utilities": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-7.1.2.tgz",
|
||||
"integrity": "sha512-To3rv1y191LTE0HMncV0mPmrnDiuNiK2aN6jDEUXQ9OQcDHqa9/7wfN9DbWCqCR53aB7mapaPtRYM20yw2gGYA==",
|
||||
"@eslint/eslintrc": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
|
||||
"integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.1.1",
|
||||
"espree": "^7.3.0",
|
||||
"globals": "^12.1.0",
|
||||
"ignore": "^4.0.6",
|
||||
"import-fresh": "^3.2.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"lodash": "^4.17.19",
|
||||
"minimatch": "^3.0.4",
|
||||
"strip-json-comments": "^3.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.12.4",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
|
||||
"integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
"version": "12.4.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
|
||||
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"type-fest": "^0.8.1"
|
||||
}
|
||||
},
|
||||
"ignore": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@fluentui/date-time-utilities": {
|
||||
"version": "7.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-7.7.0.tgz",
|
||||
"integrity": "sha512-rgtGX5x1AeYUfilfkgP6ag+ZKx41BJcUs16k6iSxXxd/mt00DAPOGY8ODGikKFpjGKcUwjKfYBssyKkVHDucfA==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uifabric/set-version": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.15.tgz",
|
||||
"integrity": "sha512-A5/hdP8yv/fg7k5F2CfoZXZSexeOZd5JMLFiiwG0gkp/wHm8A025U4cXJQ5WfVDk5zcUpw/z5OZSdnflH2mv0A==",
|
||||
"version": "7.0.22",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
|
||||
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
@@ -3450,62 +3509,63 @@
|
||||
}
|
||||
},
|
||||
"@fluentui/keyboard-key": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.2.4.tgz",
|
||||
"integrity": "sha512-dkbVQBOtvUqx+B7Jd3mY+SV8SQcO9cy6BLATPkAqK5h5gMg9clb1ny4V2OYW9SZzoOGBojpe6JBN+FmqJT2jgQ==",
|
||||
"version": "0.2.11",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.2.11.tgz",
|
||||
"integrity": "sha512-4iG5vNlRD3PrLaMfDTimHNOP1x6V3Dad0fXOwtvBBMsfdySPE9zlY+G+0aqCFcgjymOriFOk0ANZVBpK7XrnTg==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@fluentui/react-focus": {
|
||||
"version": "7.12.17",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-7.12.17.tgz",
|
||||
"integrity": "sha512-58cL/vyKepUSXAv1Vnzymur8Y+ld17O97pi7+phVj78rM93zqSr+XAnGWy9DmxG4HcSIGUtUNBxIkqqP+WoxuA==",
|
||||
"version": "7.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-7.15.0.tgz",
|
||||
"integrity": "sha512-xbxB0cbyEoUfQZ19pAqBeWCYJ/4IOu1FG4bhVjDimqSD7qKwJbLlJSDNwmHr05SWprdhmqJe23KOwsHMgyvnrw==",
|
||||
"requires": {
|
||||
"@fluentui/keyboard-key": "^0.2.4",
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/styling": "^7.13.7",
|
||||
"@uifabric/utilities": "^7.23.0",
|
||||
"@fluentui/keyboard-key": "^0.2.11",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/styling": "^7.16.0",
|
||||
"@uifabric/utilities": "^7.31.0",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uifabric/merge-styles": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.16.0.tgz",
|
||||
"integrity": "sha512-ZVTki5hvPijpzD8snXAcc/aTSFn1vVDnPMgnr1jkuVvfIohLEaU6dvoefnYPFJ/KnRC5rHyb9Eb5HS9uLnTZ8A==",
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.18.0.tgz",
|
||||
"integrity": "sha512-805WIbN7lAJATXKxZjjRbIgN7raRMwWYWeDkJJ52PCPuCesOvbpdr0GkH8rC6GQ7EB0MB7YM2i6Fiye7SFewbw==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/set-version": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.15.tgz",
|
||||
"integrity": "sha512-A5/hdP8yv/fg7k5F2CfoZXZSexeOZd5JMLFiiwG0gkp/wHm8A025U4cXJQ5WfVDk5zcUpw/z5OZSdnflH2mv0A==",
|
||||
"version": "7.0.22",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
|
||||
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/styling": {
|
||||
"version": "7.13.7",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.13.7.tgz",
|
||||
"integrity": "sha512-XFaDkvQqhhHwlW9+Yd9LQogPq0a5TC4on2csRnJUwmlTJ4IQtgvbPdAxmxz+18HZMJezUXYn7/ubcQvNRMFSJQ==",
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.16.0.tgz",
|
||||
"integrity": "sha512-yO404ws8Wl4fjBwG4T58TFJjeU/K+SpWJ4w+WeNMDlJcYe4zXaWn2lbOJtKtQiMl324RAEjFSOuNkXzPb0uOGQ==",
|
||||
"requires": {
|
||||
"@fluentui/theme": "^0.2.0",
|
||||
"@microsoft/load-themed-styles": "^1.10.26",
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/utilities": "^7.23.0",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/utilities": "^7.31.0",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/utilities": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.23.0.tgz",
|
||||
"integrity": "sha512-BtPFIoCEyu6lKDLigHvo6AI96sZPdYdaX06RGS0iFiXddk2h8DK/5YqCuCXpnA4+HeDtfaJcDQZ0z23aQDTTkA==",
|
||||
"version": "7.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.31.0.tgz",
|
||||
"integrity": "sha512-m4Yeyn4gyW7xS8LvOnCesokPModYS2YuE9GQmO++MDZ/vC5RRNlvlyktUZDuxCZ84cNCiXyTQ8nImBaPGnxHVQ==",
|
||||
"requires": {
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"prop-types": "^15.7.2",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
@@ -3513,40 +3573,100 @@
|
||||
}
|
||||
},
|
||||
"@fluentui/react-icons": {
|
||||
"version": "0.1.34",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-0.1.34.tgz",
|
||||
"integrity": "sha512-ff67rO+X8EgTSOhbqgPANJxgF3KAYRaGv7u5jhrYj5gTehBWLh2bogD1/soO8Gm74L2M5YVHvnpguUYzG0q8+g==",
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-0.3.0.tgz",
|
||||
"integrity": "sha512-QDrIhLUpkxM5q5bFE4pkweJJsfaNswdfDoc+X6cmr22Dii+anDFTpOcePEJiTtILxdlEmH0968OcZ4BGZF/joQ==",
|
||||
"requires": {
|
||||
"@microsoft/load-themed-styles": "^1.10.26",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/utilities": "^7.23.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/utilities": "^7.31.0",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uifabric/merge-styles": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.16.0.tgz",
|
||||
"integrity": "sha512-ZVTki5hvPijpzD8snXAcc/aTSFn1vVDnPMgnr1jkuVvfIohLEaU6dvoefnYPFJ/KnRC5rHyb9Eb5HS9uLnTZ8A==",
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.18.0.tgz",
|
||||
"integrity": "sha512-805WIbN7lAJATXKxZjjRbIgN7raRMwWYWeDkJJ52PCPuCesOvbpdr0GkH8rC6GQ7EB0MB7YM2i6Fiye7SFewbw==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/set-version": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.15.tgz",
|
||||
"integrity": "sha512-A5/hdP8yv/fg7k5F2CfoZXZSexeOZd5JMLFiiwG0gkp/wHm8A025U4cXJQ5WfVDk5zcUpw/z5OZSdnflH2mv0A==",
|
||||
"version": "7.0.22",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
|
||||
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/utilities": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.23.0.tgz",
|
||||
"integrity": "sha512-BtPFIoCEyu6lKDLigHvo6AI96sZPdYdaX06RGS0iFiXddk2h8DK/5YqCuCXpnA4+HeDtfaJcDQZ0z23aQDTTkA==",
|
||||
"version": "7.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.31.0.tgz",
|
||||
"integrity": "sha512-m4Yeyn4gyW7xS8LvOnCesokPModYS2YuE9GQmO++MDZ/vC5RRNlvlyktUZDuxCZ84cNCiXyTQ8nImBaPGnxHVQ==",
|
||||
"requires": {
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"prop-types": "^15.7.2",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@fluentui/react-window-provider": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/react-window-provider/-/react-window-provider-0.3.0.tgz",
|
||||
"integrity": "sha512-zHeH1PAmoFB3OkgU8f51E3oGHrL/CjuvdPBlb1SGpByUGNihAgH/CwvJohV9z0yPDkq+chfNUmxWA/oDVpbh6Q==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uifabric/set-version": {
|
||||
"version": "7.0.22",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
|
||||
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@fluentui/theme": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fluentui/theme/-/theme-0.2.0.tgz",
|
||||
"integrity": "sha512-L5OwqymTdxTVwBa3ifkQLF1A3YU6WMkMTk6PFIMfOonjt8LJ3yMMqZgz+KQR3sF/tzgy4wzW4oBmrxtTfJS2EQ==",
|
||||
"requires": {
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/utilities": "^7.31.0",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uifabric/merge-styles": {
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.18.0.tgz",
|
||||
"integrity": "sha512-805WIbN7lAJATXKxZjjRbIgN7raRMwWYWeDkJJ52PCPuCesOvbpdr0GkH8rC6GQ7EB0MB7YM2i6Fiye7SFewbw==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/set-version": {
|
||||
"version": "7.0.22",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
|
||||
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/utilities": {
|
||||
"version": "7.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.31.0.tgz",
|
||||
"integrity": "sha512-m4Yeyn4gyW7xS8LvOnCesokPModYS2YuE9GQmO++MDZ/vC5RRNlvlyktUZDuxCZ84cNCiXyTQ8nImBaPGnxHVQ==",
|
||||
"requires": {
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"prop-types": "^15.7.2",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
@@ -5272,84 +5392,90 @@
|
||||
}
|
||||
},
|
||||
"@microsoft/applicationinsights-analytics-js": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.5.4.tgz",
|
||||
"integrity": "sha512-Eda0bcThQJA/zNVzmU3+Vo9WJT/55LzUxpEATOCB6BbN1uGGUp3hGOdlV/hRl652TPutXII/gvhg8Z4uqq+VsA==",
|
||||
"version": "2.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-analytics-js/-/applicationinsights-analytics-js-2.5.8.tgz",
|
||||
"integrity": "sha512-2RsftiXa5ojNXuHRIC7RybWbN+Z7TMrLK2XGTza1Wq/KHRJNB48WmQuxjd6SzsNguqxRoHsH0sUogIwlK+NO8A==",
|
||||
"requires": {
|
||||
"@microsoft/applicationinsights-common": "2.5.4",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.4",
|
||||
"@microsoft/dynamicproto-js": "^0.5.2",
|
||||
"tslib": "^1.11.1"
|
||||
"@microsoft/applicationinsights-common": "2.5.8",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-shims": "1.0.1",
|
||||
"@microsoft/dynamicproto-js": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@microsoft/applicationinsights-channel-js": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.5.4.tgz",
|
||||
"integrity": "sha512-xDgI+7LAT5xPdxbBu/fueufH/j7p+hqfPJkkyG9BYdLa77mp+UfnP1kKjthcsdrhJiVIAbx08hmZpo72espIng==",
|
||||
"version": "2.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.5.8.tgz",
|
||||
"integrity": "sha512-etVGzhNluflTikOpW9dlDxdg+B+8gt/nxmGeXqti9Hsqq0fTxcY9bmNklFIEKhOIwai4DodgJjflaDdgR0ObUQ==",
|
||||
"requires": {
|
||||
"@microsoft/applicationinsights-common": "2.5.4",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.4",
|
||||
"tslib": "^1.11.1"
|
||||
"@microsoft/applicationinsights-common": "2.5.8",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-shims": "1.0.1",
|
||||
"@microsoft/dynamicproto-js": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@microsoft/applicationinsights-common": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-2.5.4.tgz",
|
||||
"integrity": "sha512-lrLwBUKqK4SZq2nCegUs/O8Ew2KPtL+JUCARoo6YdT8vSiUSxVk+XvwnMOViv27+NWsM3HpqOcjMn+C3kwULZQ==",
|
||||
"version": "2.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-2.5.8.tgz",
|
||||
"integrity": "sha512-RIMAJTsF0H5wiRZxYIF9H8sbMe2W5Ig4yMuH0/lho69DcNZpHf8p6PSa4Qhhli0AnoWYfLE7/WlWO1eR5SkByw==",
|
||||
"requires": {
|
||||
"@microsoft/applicationinsights-core-js": "2.5.4",
|
||||
"tslib": "^1.11.1"
|
||||
"@microsoft/applicationinsights-core-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-shims": "1.0.1"
|
||||
}
|
||||
},
|
||||
"@microsoft/applicationinsights-core-js": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.5.4.tgz",
|
||||
"integrity": "sha512-U3spLDr99R8X7X7VH49RJhx7KhB8HZpKo7rb3ymFG6z6hB7eWQQyLyMsFnThNJI3sVqwEPCQd7dBs7viheLqjw==",
|
||||
"version": "2.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.5.8.tgz",
|
||||
"integrity": "sha512-NxxIViHKuqgpla+KdQk7Qy48Dm8lN4oy2mMEpv9kM5GW5MBJ8nZ4A5RV1kokF3kXuDmTUTHlWBXeLR8hauA3qQ==",
|
||||
"requires": {
|
||||
"@microsoft/dynamicproto-js": "^0.5.2",
|
||||
"tslib": "^1.11.1"
|
||||
"@microsoft/applicationinsights-shims": "1.0.1",
|
||||
"@microsoft/dynamicproto-js": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@microsoft/applicationinsights-dependencies-js": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-dependencies-js/-/applicationinsights-dependencies-js-2.5.4.tgz",
|
||||
"integrity": "sha512-C01PkF7nQSYFpHiTo4Ltz5VOJqyTaQMHk2fNLBnyxLF2VhSUlfowPhyS6mGU3miscd5sQuktrlYol7LqjiRCXw==",
|
||||
"version": "2.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-dependencies-js/-/applicationinsights-dependencies-js-2.5.8.tgz",
|
||||
"integrity": "sha512-jnXpjE/bnlLeew78OsN8aPTLOPZQJ4y1MOO8R3E+eUXdproD2TemynSk5kUfrMdry91DZOBZnrmJ2NCB+g5ArQ==",
|
||||
"requires": {
|
||||
"@microsoft/applicationinsights-common": "2.5.4",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.4",
|
||||
"@microsoft/dynamicproto-js": "^0.5.2",
|
||||
"tslib": "^1.11.1"
|
||||
"@microsoft/applicationinsights-common": "2.5.8",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-shims": "1.0.1",
|
||||
"@microsoft/dynamicproto-js": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@microsoft/applicationinsights-properties-js": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-properties-js/-/applicationinsights-properties-js-2.5.4.tgz",
|
||||
"integrity": "sha512-2ueiQYhMiNIf9Iua7zrUGIDBiO8zPLau1yBePqLvEQ2CewBE9ZrTbdqhzpBrUQUKFbmWlETXYsIWQNz+T2rRfw==",
|
||||
"version": "2.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-properties-js/-/applicationinsights-properties-js-2.5.8.tgz",
|
||||
"integrity": "sha512-BAOSguXe07ua6SqYmAW+8+vVvBZb4qmmUP6s5zc7kNMMgEoEGsCn2VHmM8wHHxq4J/TmYxIqwoufS+XKbUvCeQ==",
|
||||
"requires": {
|
||||
"@microsoft/applicationinsights-common": "2.5.4",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.4",
|
||||
"tslib": "^1.11.1"
|
||||
"@microsoft/applicationinsights-common": "2.5.8",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-shims": "1.0.1"
|
||||
}
|
||||
},
|
||||
"@microsoft/applicationinsights-shims": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-1.0.1.tgz",
|
||||
"integrity": "sha512-nPjUBSpvX5Dnkovp2lZzrg0/uSvYNtbAclWwVP7t8J1hy5OJ3xr3KPNaz79+b84G16Rj861ybau9Gbk7inXkTg=="
|
||||
},
|
||||
"@microsoft/applicationinsights-web": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web/-/applicationinsights-web-2.5.4.tgz",
|
||||
"integrity": "sha512-5nBgxEDkM61E0irdi78DcEwfiLvYueyU5tQsCxovPfhbt5Ub8KzzT8cvmrh6p9Rt9DcpKP/uHD8k6OqMvdgvVg==",
|
||||
"version": "2.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web/-/applicationinsights-web-2.5.8.tgz",
|
||||
"integrity": "sha512-ZxCUkBJrCFNHa0LgWWbtwqu4TxJPlukuSvDrdLv6XV1yX2ETq6Q1kw/IUEtKhbtNbTZQ8aJ+x8Nc/iqbssdXTA==",
|
||||
"requires": {
|
||||
"@microsoft/applicationinsights-analytics-js": "2.5.4",
|
||||
"@microsoft/applicationinsights-channel-js": "2.5.4",
|
||||
"@microsoft/applicationinsights-common": "2.5.4",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.4",
|
||||
"@microsoft/applicationinsights-dependencies-js": "2.5.4",
|
||||
"@microsoft/applicationinsights-properties-js": "2.5.4",
|
||||
"@microsoft/dynamicproto-js": "^0.5.2",
|
||||
"tslib": "^1.11.1"
|
||||
"@microsoft/applicationinsights-analytics-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-channel-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-common": "2.5.8",
|
||||
"@microsoft/applicationinsights-core-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-dependencies-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-properties-js": "2.5.8",
|
||||
"@microsoft/applicationinsights-shims": "1.0.1",
|
||||
"@microsoft/dynamicproto-js": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@microsoft/dynamicproto-js": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-0.5.2.tgz",
|
||||
"integrity": "sha512-tGwZJLtLVK96OKl5/pHeZFgi28rnKJB2DQ0V/28SVQnv9tC/OXCNOrvvvtIZM6wp1YJwqVSFnyp46w3azDjC0Q=="
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.0.0.tgz",
|
||||
"integrity": "sha512-iHD3WsLPsuVyBCUyVFYRjxPiie2jzzn7GQibnGhTkT2HLhEJHr6COg1vkQHHGEGYU4QCTBTffIK3NCOfSzHI6Q=="
|
||||
},
|
||||
"@microsoft/load-themed-styles": {
|
||||
"version": "1.10.45",
|
||||
@@ -7490,12 +7616,6 @@
|
||||
"@types/enzyme": "*"
|
||||
}
|
||||
},
|
||||
"@types/eslint-visitor-keys": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
|
||||
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/geojson": {
|
||||
"version": "7946.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
|
||||
@@ -7858,12 +7978,14 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.2.0.tgz",
|
||||
"integrity": "sha512-t9RTk/GyYilIXt6BmZurhBzuMT9kLKw3fQoJtK9ayv0tXTlznXEAnx07sCLXdkN3/tZDep1s1CEV95CWuARYWA==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.0.1.tgz",
|
||||
"integrity": "sha512-pQZtXupCn11O4AwpYVUX4PDFfmIJl90ZgrEBg0CEcqlwvPiG0uY81fimr1oMFblZnpKAq6prrT9a59pj1x58rw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/experimental-utils": "3.2.0",
|
||||
"@typescript-eslint/experimental-utils": "4.0.1",
|
||||
"@typescript-eslint/scope-manager": "4.0.1",
|
||||
"debug": "^4.1.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"regexpp": "^3.0.0",
|
||||
"semver": "^7.3.2",
|
||||
@@ -7871,26 +7993,29 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/experimental-utils": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.2.0.tgz",
|
||||
"integrity": "sha512-UbJBsk+xO9dIFKtj16+m42EvUvsjZbbgQ2O5xSTSfVT1Z3yGkL90DVu0Hd3029FZ5/uBgl+F3Vo8FAcEcqc6aQ==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.0.1.tgz",
|
||||
"integrity": "sha512-gAqOjLiHoED79iYTt3F4uSHrYmg/GPz/zGezdB0jAdr6S6gwNiR/j7cTZ8nREKVzMVKLd9G3xbg1sV9GClW3sw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.3",
|
||||
"@typescript-eslint/typescript-estree": "3.2.0",
|
||||
"@typescript-eslint/scope-manager": "4.0.1",
|
||||
"@typescript-eslint/types": "4.0.1",
|
||||
"@typescript-eslint/typescript-estree": "4.0.1",
|
||||
"eslint-scope": "^5.0.0",
|
||||
"eslint-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.2.0.tgz",
|
||||
"integrity": "sha512-uh+Y2QO7dxNrdLw7mVnjUqkwO/InxEqwN0wF+Za6eo3coxls9aH9kQ/5rSvW2GcNanebRTmsT5w1/92lAOb1bA==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.0.1.tgz",
|
||||
"integrity": "sha512-zGzleORFXrRWRJAMLTB2iJD1IZbCPkg4hsI8mGdpYlKaqzvKYSEWVAYh14eauaR+qIoZVWrXgYSXqLtTlxotiw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.0.1",
|
||||
"@typescript-eslint/visitor-keys": "4.0.1",
|
||||
"debug": "^4.1.1",
|
||||
"eslint-visitor-keys": "^1.1.0",
|
||||
"glob": "^7.1.6",
|
||||
"globby": "^11.0.1",
|
||||
"is-glob": "^4.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"semver": "^7.3.2",
|
||||
@@ -7917,38 +8042,27 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.2.0.tgz",
|
||||
"integrity": "sha512-Vhu+wwdevDLVDjK1lIcoD6ZbuOa93fzqszkaO3iCnmrScmKwyW/AGkzc2UvfE5TCoCXqq7Jyt6SOXjsIlpqF4A==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.0.1.tgz",
|
||||
"integrity": "sha512-1+qLmXHNAWSQ7RB6fdSQszAiA7JTwzakj5cNYjBTUmpH2cqilxMZEIV+DRKjVZs8NzP3ALmKexB0w/ExjcK9Iw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/eslint-visitor-keys": "^1.0.0",
|
||||
"@typescript-eslint/experimental-utils": "3.2.0",
|
||||
"@typescript-eslint/typescript-estree": "3.2.0",
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
"@typescript-eslint/scope-manager": "4.0.1",
|
||||
"@typescript-eslint/types": "4.0.1",
|
||||
"@typescript-eslint/typescript-estree": "4.0.1",
|
||||
"debug": "^4.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/experimental-utils": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.2.0.tgz",
|
||||
"integrity": "sha512-UbJBsk+xO9dIFKtj16+m42EvUvsjZbbgQ2O5xSTSfVT1Z3yGkL90DVu0Hd3029FZ5/uBgl+F3Vo8FAcEcqc6aQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.3",
|
||||
"@typescript-eslint/typescript-estree": "3.2.0",
|
||||
"eslint-scope": "^5.0.0",
|
||||
"eslint-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.2.0.tgz",
|
||||
"integrity": "sha512-uh+Y2QO7dxNrdLw7mVnjUqkwO/InxEqwN0wF+Za6eo3coxls9aH9kQ/5rSvW2GcNanebRTmsT5w1/92lAOb1bA==",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.0.1.tgz",
|
||||
"integrity": "sha512-zGzleORFXrRWRJAMLTB2iJD1IZbCPkg4hsI8mGdpYlKaqzvKYSEWVAYh14eauaR+qIoZVWrXgYSXqLtTlxotiw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.0.1",
|
||||
"@typescript-eslint/visitor-keys": "4.0.1",
|
||||
"debug": "^4.1.1",
|
||||
"eslint-visitor-keys": "^1.1.0",
|
||||
"glob": "^7.1.6",
|
||||
"globby": "^11.0.1",
|
||||
"is-glob": "^4.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"semver": "^7.3.2",
|
||||
@@ -7963,6 +8077,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.0.1.tgz",
|
||||
"integrity": "sha512-u3YEXVJ8jsj7QCJk3om0Y457fy2euEOkkzxIB/LKU3MdyI+FJ2gI0M4aKEaXzwCSfNDiZ13a3lDo5DVozc+XLQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.0.1",
|
||||
"@typescript-eslint/visitor-keys": "4.0.1"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.0.1.tgz",
|
||||
"integrity": "sha512-S+gD3fgbkZYW2rnbjugNMqibm9HpEjqZBZkTiI3PwbbNGWmAcxolWIUwZ0SKeG4Dy2ktpKKaI/6+HGYVH8Qrlg==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "2.34.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz",
|
||||
@@ -7984,6 +8114,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.0.1.tgz",
|
||||
"integrity": "sha512-yBSqd6FjnTzbg5RUy9J+9kJEyQjTI34JdGMJz+9ttlJzLCnGkBikxw+N5n2VDcc3CesbIEJ0MnZc5uRYnrEnCw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "4.0.1",
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
|
||||
"integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@uifabric/azure-themes": {
|
||||
"version": "7.1.37",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/azure-themes/-/azure-themes-7.1.37.tgz",
|
||||
@@ -8121,51 +8269,52 @@
|
||||
}
|
||||
},
|
||||
"@uifabric/icons": {
|
||||
"version": "7.3.59",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.3.59.tgz",
|
||||
"integrity": "sha512-g9dICazdYTs6ljmm/04T+vG07av/HTcd/p80XDI6aDhHVIWrNwlPS55clkfd1PSgoyGllRqJdSJvzNyZa1zYFw==",
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.5.0.tgz",
|
||||
"integrity": "sha512-RINA9VkajlCnlwEBbqiwLBaaGn38Bf9UvjOuwrrja4B9lclLeQzZuGrG/kp7CnDtIO+LC19OYl/7E3jW7yIihA==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/styling": "^7.13.7",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/styling": "^7.16.0",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uifabric/merge-styles": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.16.0.tgz",
|
||||
"integrity": "sha512-ZVTki5hvPijpzD8snXAcc/aTSFn1vVDnPMgnr1jkuVvfIohLEaU6dvoefnYPFJ/KnRC5rHyb9Eb5HS9uLnTZ8A==",
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.18.0.tgz",
|
||||
"integrity": "sha512-805WIbN7lAJATXKxZjjRbIgN7raRMwWYWeDkJJ52PCPuCesOvbpdr0GkH8rC6GQ7EB0MB7YM2i6Fiye7SFewbw==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/set-version": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.15.tgz",
|
||||
"integrity": "sha512-A5/hdP8yv/fg7k5F2CfoZXZSexeOZd5JMLFiiwG0gkp/wHm8A025U4cXJQ5WfVDk5zcUpw/z5OZSdnflH2mv0A==",
|
||||
"version": "7.0.22",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
|
||||
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/styling": {
|
||||
"version": "7.13.7",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.13.7.tgz",
|
||||
"integrity": "sha512-XFaDkvQqhhHwlW9+Yd9LQogPq0a5TC4on2csRnJUwmlTJ4IQtgvbPdAxmxz+18HZMJezUXYn7/ubcQvNRMFSJQ==",
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.16.0.tgz",
|
||||
"integrity": "sha512-yO404ws8Wl4fjBwG4T58TFJjeU/K+SpWJ4w+WeNMDlJcYe4zXaWn2lbOJtKtQiMl324RAEjFSOuNkXzPb0uOGQ==",
|
||||
"requires": {
|
||||
"@fluentui/theme": "^0.2.0",
|
||||
"@microsoft/load-themed-styles": "^1.10.26",
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/utilities": "^7.23.0",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/utilities": "^7.31.0",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/utilities": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.23.0.tgz",
|
||||
"integrity": "sha512-BtPFIoCEyu6lKDLigHvo6AI96sZPdYdaX06RGS0iFiXddk2h8DK/5YqCuCXpnA4+HeDtfaJcDQZ0z23aQDTTkA==",
|
||||
"version": "7.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.31.0.tgz",
|
||||
"integrity": "sha512-m4Yeyn4gyW7xS8LvOnCesokPModYS2YuE9GQmO++MDZ/vC5RRNlvlyktUZDuxCZ84cNCiXyTQ8nImBaPGnxHVQ==",
|
||||
"requires": {
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"prop-types": "^15.7.2",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
@@ -8241,39 +8390,39 @@
|
||||
}
|
||||
},
|
||||
"@uifabric/react-hooks": {
|
||||
"version": "7.4.12",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/react-hooks/-/react-hooks-7.4.12.tgz",
|
||||
"integrity": "sha512-9xWsMNdXeqNqDwWZSAFNUh64sl/Q1Fu7pS4GVcLQeNMY17KSbjABkKAjjgUV2Mf58OvaPZJ2s2or7JoWa45CZg==",
|
||||
"version": "7.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/react-hooks/-/react-hooks-7.11.0.tgz",
|
||||
"integrity": "sha512-iU7c+JR+rY5kBTPmrF8F6iJBQw309MX/MvOx6ElhmNceBaa8BqDuqR9+TVfkH+Bxp37bmZnCaQF5w4+QWHZ81g==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/utilities": "^7.23.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/utilities": "^7.31.0",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uifabric/merge-styles": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.16.0.tgz",
|
||||
"integrity": "sha512-ZVTki5hvPijpzD8snXAcc/aTSFn1vVDnPMgnr1jkuVvfIohLEaU6dvoefnYPFJ/KnRC5rHyb9Eb5HS9uLnTZ8A==",
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.18.0.tgz",
|
||||
"integrity": "sha512-805WIbN7lAJATXKxZjjRbIgN7raRMwWYWeDkJJ52PCPuCesOvbpdr0GkH8rC6GQ7EB0MB7YM2i6Fiye7SFewbw==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/set-version": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.15.tgz",
|
||||
"integrity": "sha512-A5/hdP8yv/fg7k5F2CfoZXZSexeOZd5JMLFiiwG0gkp/wHm8A025U4cXJQ5WfVDk5zcUpw/z5OZSdnflH2mv0A==",
|
||||
"version": "7.0.22",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
|
||||
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/utilities": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.23.0.tgz",
|
||||
"integrity": "sha512-BtPFIoCEyu6lKDLigHvo6AI96sZPdYdaX06RGS0iFiXddk2h8DK/5YqCuCXpnA4+HeDtfaJcDQZ0z23aQDTTkA==",
|
||||
"version": "7.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.31.0.tgz",
|
||||
"integrity": "sha512-m4Yeyn4gyW7xS8LvOnCesokPModYS2YuE9GQmO++MDZ/vC5RRNlvlyktUZDuxCZ84cNCiXyTQ8nImBaPGnxHVQ==",
|
||||
"requires": {
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"prop-types": "^15.7.2",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
@@ -12304,18 +12453,18 @@
|
||||
}
|
||||
},
|
||||
"enquirer": {
|
||||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.5.tgz",
|
||||
"integrity": "sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==",
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
|
||||
"integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-colors": "^3.2.1"
|
||||
"ansi-colors": "^4.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-colors": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
|
||||
"integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
|
||||
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@@ -12543,12 +12692,13 @@
|
||||
}
|
||||
},
|
||||
"eslint": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.3.1.tgz",
|
||||
"integrity": "sha512-cQC/xj9bhWUcyi/RuMbRtC3I0eW8MH0jhRELSvpKYkWep3C6YZ2OkvcvJVUeO6gcunABmzptbXBuDoXsjHmfTA==",
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.8.1.tgz",
|
||||
"integrity": "sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@eslint/eslintrc": "^0.1.3",
|
||||
"ajv": "^6.10.0",
|
||||
"chalk": "^4.0.0",
|
||||
"cross-spawn": "^7.0.2",
|
||||
@@ -12556,9 +12706,9 @@
|
||||
"doctrine": "^3.0.0",
|
||||
"enquirer": "^2.3.5",
|
||||
"eslint-scope": "^5.1.0",
|
||||
"eslint-utils": "^2.0.0",
|
||||
"eslint-visitor-keys": "^1.2.0",
|
||||
"espree": "^7.1.0",
|
||||
"eslint-utils": "^2.1.0",
|
||||
"eslint-visitor-keys": "^1.3.0",
|
||||
"espree": "^7.3.0",
|
||||
"esquery": "^1.2.0",
|
||||
"esutils": "^2.0.2",
|
||||
"file-entry-cache": "^5.0.1",
|
||||
@@ -12572,7 +12722,7 @@
|
||||
"js-yaml": "^3.13.1",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.4.1",
|
||||
"lodash": "^4.17.14",
|
||||
"lodash": "^4.17.19",
|
||||
"minimatch": "^3.0.4",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.9.1",
|
||||
@@ -12648,6 +12798,15 @@
|
||||
"estraverse": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"eslint-utils": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
|
||||
"integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
||||
@@ -12685,6 +12844,12 @@
|
||||
"type-check": "~0.4.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
|
||||
"dev": true
|
||||
},
|
||||
"optionator": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
|
||||
@@ -12742,15 +12907,15 @@
|
||||
}
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz",
|
||||
"integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
|
||||
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
@@ -12888,16 +13053,22 @@
|
||||
"integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A=="
|
||||
},
|
||||
"espree": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz",
|
||||
"integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==",
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz",
|
||||
"integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^7.2.0",
|
||||
"acorn": "^7.4.0",
|
||||
"acorn-jsx": "^5.2.0",
|
||||
"eslint-visitor-keys": "^1.2.0"
|
||||
"eslint-visitor-keys": "^1.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
|
||||
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
||||
@@ -12921,9 +13092,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"estraverse": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz",
|
||||
"integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
|
||||
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@@ -22073,61 +22244,75 @@
|
||||
"dev": true
|
||||
},
|
||||
"office-ui-fabric-react": {
|
||||
"version": "7.121.10",
|
||||
"resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.121.10.tgz",
|
||||
"integrity": "sha512-hX4P99Oz/w20zAopt+ujetJCfl/H8v5IiONp160x5ubQVS4PBBbAG3k0yy9gJss4easjLtv2NqzCvOyeRfJhEg==",
|
||||
"version": "7.134.1",
|
||||
"resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.134.1.tgz",
|
||||
"integrity": "sha512-yQhPdt5kQfzI/MQnqQMu9lf2mgdHSogEfVIYgfOjbvfMJoUzqA/hH3X2Z7RbncdJ/ca2H+GXVp5GvSgahCOs6g==",
|
||||
"requires": {
|
||||
"@fluentui/date-time-utilities": "^7.1.2",
|
||||
"@fluentui/react-focus": "^7.12.17",
|
||||
"@fluentui/react-icons": "^0.1.34",
|
||||
"@fluentui/date-time-utilities": "^7.7.0",
|
||||
"@fluentui/react-focus": "^7.15.0",
|
||||
"@fluentui/react-icons": "^0.3.0",
|
||||
"@fluentui/react-window-provider": "^0.3.0",
|
||||
"@microsoft/load-themed-styles": "^1.10.26",
|
||||
"@uifabric/foundation": "^7.7.33",
|
||||
"@uifabric/icons": "^7.3.59",
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/react-hooks": "^7.4.12",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/styling": "^7.13.7",
|
||||
"@uifabric/utilities": "^7.23.0",
|
||||
"@uifabric/foundation": "^7.9.0",
|
||||
"@uifabric/icons": "^7.5.0",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/react-hooks": "^7.11.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/styling": "^7.16.0",
|
||||
"@uifabric/utilities": "^7.31.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@uifabric/merge-styles": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.16.0.tgz",
|
||||
"integrity": "sha512-ZVTki5hvPijpzD8snXAcc/aTSFn1vVDnPMgnr1jkuVvfIohLEaU6dvoefnYPFJ/KnRC5rHyb9Eb5HS9uLnTZ8A==",
|
||||
"@uifabric/foundation": {
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.9.0.tgz",
|
||||
"integrity": "sha512-4gdPwx0HV59aWvPKIw6yIje60CYwJZmTJsdLRXqh8Np1tWp2EsbA8U/IHQL1V91rEN0DlQhASqCDFhfQoD1jUw==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/styling": "^7.16.0",
|
||||
"@uifabric/utilities": "^7.31.0",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/merge-styles": {
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.18.0.tgz",
|
||||
"integrity": "sha512-805WIbN7lAJATXKxZjjRbIgN7raRMwWYWeDkJJ52PCPuCesOvbpdr0GkH8rC6GQ7EB0MB7YM2i6Fiye7SFewbw==",
|
||||
"requires": {
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/set-version": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.15.tgz",
|
||||
"integrity": "sha512-A5/hdP8yv/fg7k5F2CfoZXZSexeOZd5JMLFiiwG0gkp/wHm8A025U4cXJQ5WfVDk5zcUpw/z5OZSdnflH2mv0A==",
|
||||
"version": "7.0.22",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
|
||||
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/styling": {
|
||||
"version": "7.13.7",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.13.7.tgz",
|
||||
"integrity": "sha512-XFaDkvQqhhHwlW9+Yd9LQogPq0a5TC4on2csRnJUwmlTJ4IQtgvbPdAxmxz+18HZMJezUXYn7/ubcQvNRMFSJQ==",
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.16.0.tgz",
|
||||
"integrity": "sha512-yO404ws8Wl4fjBwG4T58TFJjeU/K+SpWJ4w+WeNMDlJcYe4zXaWn2lbOJtKtQiMl324RAEjFSOuNkXzPb0uOGQ==",
|
||||
"requires": {
|
||||
"@fluentui/theme": "^0.2.0",
|
||||
"@microsoft/load-themed-styles": "^1.10.26",
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/utilities": "^7.23.0",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"@uifabric/utilities": "^7.31.0",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"@uifabric/utilities": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.23.0.tgz",
|
||||
"integrity": "sha512-BtPFIoCEyu6lKDLigHvo6AI96sZPdYdaX06RGS0iFiXddk2h8DK/5YqCuCXpnA4+HeDtfaJcDQZ0z23aQDTTkA==",
|
||||
"version": "7.31.0",
|
||||
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.31.0.tgz",
|
||||
"integrity": "sha512-m4Yeyn4gyW7xS8LvOnCesokPModYS2YuE9GQmO++MDZ/vC5RRNlvlyktUZDuxCZ84cNCiXyTQ8nImBaPGnxHVQ==",
|
||||
"requires": {
|
||||
"@uifabric/merge-styles": "^7.16.0",
|
||||
"@uifabric/set-version": "^7.0.15",
|
||||
"@uifabric/merge-styles": "^7.18.0",
|
||||
"@uifabric/set-version": "^7.0.22",
|
||||
"prop-types": "^15.7.2",
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
@@ -26196,9 +26381,9 @@
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.9.6",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz",
|
||||
"integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz",
|
||||
"integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"typestyle": {
|
||||
|
||||
12
package.json
12
package.json
@@ -8,7 +8,7 @@
|
||||
"@azure/cosmos-language-service": "0.0.4",
|
||||
"@jupyterlab/services": "4.2.0",
|
||||
"@jupyterlab/terminal": "1.2.1",
|
||||
"@microsoft/applicationinsights-web": "2.5.4",
|
||||
"@microsoft/applicationinsights-web": "2.5.8",
|
||||
"@nteract/commutable": "7.1.4",
|
||||
"@nteract/connected-components": "6.7.8",
|
||||
"@nteract/core": "13.0.0",
|
||||
@@ -66,7 +66,7 @@
|
||||
"mkdirp": "1.0.4",
|
||||
"monaco-editor": "0.15.6",
|
||||
"object.entries": "1.1.0",
|
||||
"office-ui-fabric-react": "7.121.10",
|
||||
"office-ui-fabric-react": "7.134.1",
|
||||
"p-retry": "4.2.0",
|
||||
"plotly.js-cartesian-dist-min": "1.52.3",
|
||||
"promise-polyfill": "8.1.0",
|
||||
@@ -118,8 +118,8 @@
|
||||
"@types/text-encoding": "0.0.33",
|
||||
"@types/underscore": "1.7.36",
|
||||
"@types/webfontloader": "1.6.29",
|
||||
"@typescript-eslint/eslint-plugin": "3.2.0",
|
||||
"@typescript-eslint/parser": "3.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "4.0.1",
|
||||
"@typescript-eslint/parser": "4.0.1",
|
||||
"adal-angular": "1.0.15",
|
||||
"axe-puppeteer": "1.1.0",
|
||||
"babel-jest": "24.9.0",
|
||||
@@ -132,7 +132,7 @@
|
||||
"enzyme": "3.10.0",
|
||||
"enzyme-adapter-react-16": "1.15.1",
|
||||
"enzyme-to-json": "3.4.3",
|
||||
"eslint": "7.3.1",
|
||||
"eslint": "7.8.1",
|
||||
"eslint-cli": "1.1.1",
|
||||
"eslint-plugin-no-null": "1.0.2",
|
||||
"eslint-plugin-prefer-arrow": "1.2.2",
|
||||
@@ -164,7 +164,7 @@
|
||||
"ts-loader": "6.2.2",
|
||||
"tslint": "5.11.0",
|
||||
"tslint-microsoft-contrib": "6.0.0",
|
||||
"typescript": "3.9.6",
|
||||
"typescript": "4.0.2",
|
||||
"url-loader": "1.1.1",
|
||||
"webpack": "4.43.0",
|
||||
"webpack-bundle-analyzer": "3.6.1",
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"offerThroughput": 400,
|
||||
"databaseLevelThroughput": false,
|
||||
"collectionId": "Persons",
|
||||
"rupmEnabled": false,
|
||||
"partitionKey": { "kind": "Hash", "paths": ["/firstname"] },
|
||||
"createNewDatabase": true,
|
||||
"partitionKey": { "kind": "Hash", "paths": ["/firstname"], "version": 1 },
|
||||
"data": [
|
||||
{
|
||||
"firstname": "Eva",
|
||||
@@ -23,4 +23,4 @@
|
||||
"age": 23
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,12 @@ import {
|
||||
ConflictDefinition,
|
||||
FeedOptions,
|
||||
ItemDefinition,
|
||||
PartitionKeyDefinition,
|
||||
QueryIterator,
|
||||
Resource,
|
||||
TriggerDefinition,
|
||||
OfferDefinition
|
||||
} from "@azure/cosmos";
|
||||
import { ContainerRequest } from "@azure/cosmos/dist-esm/client/Container/ContainerRequest";
|
||||
import { client } from "./CosmosClient";
|
||||
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
|
||||
import { LocalStorageUtility, StorageKey } from "../Shared/StorageUtility";
|
||||
import { sendCachedDataMessage } from "./MessageHandler";
|
||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
@@ -480,69 +477,6 @@ export function readOffer(requestedResource: DataModels.Offer, options: any): Q.
|
||||
);
|
||||
}
|
||||
|
||||
export function getOrCreateDatabaseAndCollection(
|
||||
request: DataModels.CreateDatabaseAndCollectionRequest,
|
||||
options: any
|
||||
): Q.Promise<DataModels.Collection> {
|
||||
const databaseOptions: any = options && _.omit(options, "sharedOfferThroughput");
|
||||
const {
|
||||
databaseId,
|
||||
databaseLevelThroughput,
|
||||
collectionId,
|
||||
partitionKey,
|
||||
indexingPolicy,
|
||||
uniqueKeyPolicy,
|
||||
offerThroughput,
|
||||
analyticalStorageTtl,
|
||||
hasAutoPilotV2FeatureFlag
|
||||
} = request;
|
||||
|
||||
const createBody: DatabaseRequest = {
|
||||
id: databaseId
|
||||
};
|
||||
|
||||
// TODO: replace when SDK support autopilot
|
||||
const initialHeaders = request.autoPilot
|
||||
? !hasAutoPilotV2FeatureFlag
|
||||
? {
|
||||
[Constants.HttpHeaders.autoPilotThroughputSDK]: JSON.stringify({
|
||||
maxThroughput: request.autoPilot.maxThroughput
|
||||
})
|
||||
}
|
||||
: {
|
||||
[Constants.HttpHeaders.autoPilotTier]: request.autoPilot.autopilotTier
|
||||
}
|
||||
: undefined;
|
||||
if (databaseLevelThroughput) {
|
||||
if (request.autoPilot) {
|
||||
databaseOptions.initialHeaders = initialHeaders;
|
||||
}
|
||||
createBody.throughput = offerThroughput;
|
||||
}
|
||||
|
||||
return Q(
|
||||
client()
|
||||
.databases.createIfNotExists(createBody, databaseOptions)
|
||||
.then(response => {
|
||||
return response.database.containers.create(
|
||||
{
|
||||
id: collectionId,
|
||||
partitionKey: (partitionKey || undefined) as PartitionKeyDefinition,
|
||||
indexingPolicy: indexingPolicy ? indexingPolicy : undefined,
|
||||
uniqueKeyPolicy: uniqueKeyPolicy ? uniqueKeyPolicy : undefined,
|
||||
analyticalStorageTtl: analyticalStorageTtl,
|
||||
throughput: databaseLevelThroughput || request.autoPilot ? undefined : offerThroughput
|
||||
} as ContainerRequest, // TODO: remove cast when https://github.com/Azure/azure-cosmos-js/issues/423 is fixed
|
||||
{
|
||||
initialHeaders: databaseLevelThroughput ? undefined : initialHeaders
|
||||
}
|
||||
);
|
||||
})
|
||||
.then(containerResponse => containerResponse.resource as DataModels.Collection)
|
||||
.finally(() => refreshCachedResources(options))
|
||||
);
|
||||
}
|
||||
|
||||
export function refreshCachedOffers(): Q.Promise<void> {
|
||||
if (configContext.platform === Platform.Portal) {
|
||||
return sendCachedDataMessage(MessageTypes.RefreshOffers, []);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as Constants from "./Constants";
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
import * as ErrorParserUtility from "./ErrorParserUtility";
|
||||
import * as ViewModels from "../Contracts/ViewModels";
|
||||
import Q from "q";
|
||||
import { ConflictDefinition, ItemDefinition, QueryIterator, Resource } from "@azure/cosmos";
|
||||
@@ -856,37 +855,3 @@ export function readOffer(
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
export function getOrCreateDatabaseAndCollection(
|
||||
request: DataModels.CreateDatabaseAndCollectionRequest,
|
||||
options: any = {}
|
||||
): Q.Promise<DataModels.Collection> {
|
||||
const deferred: Q.Deferred<DataModels.Collection> = Q.defer<DataModels.Collection>();
|
||||
const id = NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.InProgress,
|
||||
`Creating a new container ${request.collectionId} for database ${request.databaseId}`
|
||||
);
|
||||
|
||||
DataAccessUtilityBase.getOrCreateDatabaseAndCollection(request, options)
|
||||
.then(
|
||||
(collection: DataModels.Collection) => {
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Info,
|
||||
`Successfully created container ${request.collectionId}`
|
||||
);
|
||||
deferred.resolve(collection);
|
||||
},
|
||||
(error: any) => {
|
||||
const sanitizedError = ErrorParserUtility.replaceKnownError(JSON.stringify(error));
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Error while creating container ${request.collectionId}:\n ${sanitizedError}`
|
||||
);
|
||||
sendNotificationForError(error);
|
||||
deferred.reject(error);
|
||||
}
|
||||
)
|
||||
.finally(() => NotificationConsoleUtils.clearInProgressMessageWithId(id));
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
@@ -5,14 +5,7 @@ import { Collection } from "../Contracts/ViewModels";
|
||||
import DocumentId from "../Explorer/Tree/DocumentId";
|
||||
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
|
||||
import { updateUserContext } from "../UserContext";
|
||||
import {
|
||||
deleteDocument,
|
||||
getEndpoint,
|
||||
queryDocuments,
|
||||
readDocument,
|
||||
updateDocument,
|
||||
_createMongoCollectionWithARM
|
||||
} from "./MongoProxyClient";
|
||||
import { deleteDocument, getEndpoint, queryDocuments, readDocument, updateDocument } from "./MongoProxyClient";
|
||||
jest.mock("../ResourceProvider/ResourceProviderClient.ts");
|
||||
|
||||
const databaseId = "testDB";
|
||||
@@ -260,58 +253,4 @@ describe("MongoProxyClient", () => {
|
||||
expect(endpoint).toEqual("https://main.documentdb.ext.azure.com/api/guest/mongo/explorer");
|
||||
});
|
||||
});
|
||||
|
||||
describe("createMongoCollectionWithARM", () => {
|
||||
it("should create a collection with autopilot when autopilot is selected + shared throughput is false", () => {
|
||||
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
|
||||
const properties = {
|
||||
pk: "state",
|
||||
coll: "abc-collection",
|
||||
cd: true,
|
||||
db: "a1-db",
|
||||
st: false,
|
||||
sid: "a2",
|
||||
rg: "c1",
|
||||
dba: "main",
|
||||
is: false
|
||||
};
|
||||
_createMongoCollectionWithARM("management.azure.com", properties, { "x-ms-cosmos-offer-autopilot-tier": "1" });
|
||||
expect(resourceProviderClientPutAsyncSpy).toHaveBeenCalledWith(
|
||||
"subscriptions/a2/resourceGroups/c1/providers/Microsoft.DocumentDB/databaseAccounts/foo/mongodbDatabases/a1-db/collections/abc-collection",
|
||||
"2020-04-01",
|
||||
{
|
||||
properties: {
|
||||
options: { "x-ms-cosmos-offer-autopilot-tier": "1" },
|
||||
resource: { id: "abc-collection" }
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
it("should create a collection with provisioned throughput when provisioned throughput is selected + shared throughput is false", () => {
|
||||
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
|
||||
const properties = {
|
||||
pk: "state",
|
||||
coll: "abc-collection",
|
||||
cd: true,
|
||||
db: "a1-db",
|
||||
st: false,
|
||||
sid: "a2",
|
||||
rg: "c1",
|
||||
dba: "main",
|
||||
is: false,
|
||||
offerThroughput: 400
|
||||
};
|
||||
_createMongoCollectionWithARM("management.azure.com", properties, undefined);
|
||||
expect(resourceProviderClientPutAsyncSpy).toHaveBeenCalledWith(
|
||||
"subscriptions/a2/resourceGroups/c1/providers/Microsoft.DocumentDB/databaseAccounts/foo/mongodbDatabases/a1-db/collections/abc-collection",
|
||||
"2020-04-01",
|
||||
{
|
||||
properties: {
|
||||
options: { throughput: "400" },
|
||||
resource: { id: "abc-collection" }
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
import { Constants as CosmosSDKConstants } from "@azure/cosmos";
|
||||
import queryString from "querystring";
|
||||
import { AuthType } from "../AuthType";
|
||||
import * as Constants from "../Common/Constants";
|
||||
import * as DataExplorerConstants from "../Common/Constants";
|
||||
import { configContext } from "../ConfigContext";
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
import { Collection } from "../Contracts/ViewModels";
|
||||
import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import DocumentId from "../Explorer/Tree/DocumentId";
|
||||
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
|
||||
import { AddDbUtilities } from "../Shared/AddDatabaseUtility";
|
||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||
import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants";
|
||||
import { userContext } from "../UserContext";
|
||||
@@ -285,43 +281,35 @@ export function deleteDocument(databaseId: string, collection: Collection, docum
|
||||
}
|
||||
|
||||
export function createMongoCollectionWithProxy(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
offerThroughput: number,
|
||||
shardKey: string,
|
||||
createDatabase: boolean,
|
||||
sharedThroughput: boolean,
|
||||
isSharded: boolean,
|
||||
autopilotOptions?: DataModels.RpOptions
|
||||
params: DataModels.CreateCollectionParams
|
||||
): Promise<DataModels.Collection> {
|
||||
const databaseAccount = userContext.databaseAccount;
|
||||
const params: DataModels.MongoParameters = {
|
||||
const shardKey: string = params.partitionKey?.paths[0];
|
||||
const mongoParams: DataModels.MongoParameters = {
|
||||
resourceUrl: databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint,
|
||||
db: databaseId,
|
||||
coll: collectionId,
|
||||
db: params.databaseId,
|
||||
coll: params.collectionId,
|
||||
pk: shardKey,
|
||||
offerThroughput,
|
||||
cd: createDatabase,
|
||||
st: sharedThroughput,
|
||||
is: isSharded,
|
||||
offerThroughput: params.offerThroughput,
|
||||
cd: params.createNewDatabase,
|
||||
st: params.databaseLevelThroughput,
|
||||
is: !!shardKey,
|
||||
rid: "",
|
||||
rtype: "colls",
|
||||
sid: userContext.subscriptionId,
|
||||
rg: userContext.resourceGroup,
|
||||
dba: databaseAccount.name,
|
||||
isAutoPilot: false
|
||||
isAutoPilot: !!params.autoPilotMaxThroughput,
|
||||
autoPilotThroughput: params.autoPilotMaxThroughput?.toString()
|
||||
};
|
||||
|
||||
if (autopilotOptions) {
|
||||
params.isAutoPilot = true;
|
||||
params.autoPilotTier = autopilotOptions[Constants.HttpHeaders.autoPilotTier] as string;
|
||||
}
|
||||
|
||||
const endpoint = getEndpoint(databaseAccount);
|
||||
|
||||
return window
|
||||
.fetch(
|
||||
`${endpoint}/createCollection?${queryString.stringify((params as unknown) as queryString.ParsedUrlQueryInput)}`,
|
||||
`${endpoint}/createCollection?${queryString.stringify(
|
||||
(mongoParams as unknown) as queryString.ParsedUrlQueryInput
|
||||
)}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
@@ -335,52 +323,10 @@ export function createMongoCollectionWithProxy(
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return errorHandling(response, "creating collection", params);
|
||||
return errorHandling(response, "creating collection", mongoParams);
|
||||
});
|
||||
}
|
||||
|
||||
export function createMongoCollectionWithARM(
|
||||
armEndpoint: string,
|
||||
databaseId: string,
|
||||
analyticalStorageTtl: number,
|
||||
collectionId: string,
|
||||
offerThroughput: number,
|
||||
shardKey: string,
|
||||
createDatabase: boolean,
|
||||
sharedThroughput: boolean,
|
||||
isSharded: boolean,
|
||||
additionalOptions?: DataModels.RpOptions
|
||||
): Promise<DataModels.CreateCollectionWithRpResponse> {
|
||||
const databaseAccount = userContext.databaseAccount;
|
||||
const params: DataModels.MongoParameters = {
|
||||
resourceUrl: databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint,
|
||||
db: databaseId,
|
||||
coll: collectionId,
|
||||
pk: shardKey,
|
||||
offerThroughput,
|
||||
cd: createDatabase,
|
||||
st: sharedThroughput,
|
||||
is: isSharded,
|
||||
rid: "",
|
||||
rtype: "colls",
|
||||
sid: userContext.subscriptionId,
|
||||
rg: userContext.resourceGroup,
|
||||
dba: databaseAccount.name,
|
||||
analyticalStorageTtl
|
||||
};
|
||||
|
||||
if (createDatabase) {
|
||||
return AddDbUtilities.createMongoDatabaseWithARM(
|
||||
armEndpoint,
|
||||
params,
|
||||
sharedThroughput ? additionalOptions : {}
|
||||
).then(() => {
|
||||
return _createMongoCollectionWithARM(armEndpoint, params, sharedThroughput ? {} : additionalOptions);
|
||||
});
|
||||
}
|
||||
return _createMongoCollectionWithARM(armEndpoint, params, additionalOptions);
|
||||
}
|
||||
|
||||
export function getEndpoint(databaseAccount: DataModels.DatabaseAccount): string {
|
||||
const serverId = window.dataExplorer.serverId();
|
||||
const extensionEndpoint = window.dataExplorer.extensionEndpoint();
|
||||
@@ -413,46 +359,3 @@ async function errorHandling(response: Response, action: string, params: unknown
|
||||
export function getARMCreateCollectionEndpoint(params: DataModels.MongoParameters): string {
|
||||
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/mongodbDatabases/${params.db}/collections/${params.coll}`;
|
||||
}
|
||||
|
||||
export async function _createMongoCollectionWithARM(
|
||||
armEndpoint: string,
|
||||
params: DataModels.MongoParameters,
|
||||
rpOptions: DataModels.RpOptions
|
||||
): Promise<DataModels.CreateCollectionWithRpResponse> {
|
||||
const rpPayloadToCreateCollection: DataModels.MongoCreationRequest = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.coll
|
||||
},
|
||||
options: {}
|
||||
}
|
||||
};
|
||||
|
||||
if (params.is) {
|
||||
rpPayloadToCreateCollection.properties.resource["shardKey"] = { [params.pk]: "Hash" };
|
||||
}
|
||||
|
||||
if (!params.st) {
|
||||
if (rpOptions) {
|
||||
rpPayloadToCreateCollection.properties.options = rpOptions;
|
||||
} else {
|
||||
rpPayloadToCreateCollection.properties.options["throughput"] =
|
||||
params.offerThroughput && params.offerThroughput.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (params.analyticalStorageTtl) {
|
||||
rpPayloadToCreateCollection.properties.resource.analyticalStorageTtl = params.analyticalStorageTtl;
|
||||
}
|
||||
|
||||
try {
|
||||
return new ResourceProviderClient<DataModels.CreateCollectionWithRpResponse>(armEndpoint).putAsync(
|
||||
getARMCreateCollectionEndpoint(params),
|
||||
DataExplorerConstants.ArmApiVersions.publicVersion,
|
||||
rpPayloadToCreateCollection
|
||||
);
|
||||
} catch (response) {
|
||||
errorHandling(response, "creating collection", undefined);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,8 @@ import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||
import { QueryUtils } from "../Utils/QueryUtils";
|
||||
import { BackendDefaults, HttpStatusCodes, SavedQueries } from "./Constants";
|
||||
import { userContext } from "../UserContext";
|
||||
import {
|
||||
createDocument,
|
||||
deleteDocument,
|
||||
getOrCreateDatabaseAndCollection,
|
||||
queryDocuments,
|
||||
queryDocumentsPage
|
||||
} from "./DocumentClientUtilityBase";
|
||||
import { createDocument, deleteDocument, queryDocuments, queryDocumentsPage } from "./DocumentClientUtilityBase";
|
||||
import { createCollection } from "./dataAccess/createCollection";
|
||||
import * as ErrorParserUtility from "./ErrorParserUtility";
|
||||
import * as Logger from "./Logger";
|
||||
|
||||
@@ -41,12 +36,13 @@ export class QueriesClient {
|
||||
ConsoleDataType.InProgress,
|
||||
"Setting up account for saving queries"
|
||||
);
|
||||
return getOrCreateDatabaseAndCollection({
|
||||
return createCollection({
|
||||
collectionId: SavedQueries.CollectionName,
|
||||
createNewDatabase: true,
|
||||
databaseId: SavedQueries.DatabaseName,
|
||||
partitionKey: QueriesClient.PartitionKey,
|
||||
offerThroughput: SavedQueries.OfferThroughput,
|
||||
databaseLevelThroughput: undefined
|
||||
databaseLevelThroughput: false
|
||||
})
|
||||
.then(
|
||||
(collection: DataModels.Collection) => {
|
||||
|
||||
81
src/Common/dataAccess/createCollection.test.ts
Normal file
81
src/Common/dataAccess/createCollection.test.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
jest.mock("../../Utils/arm/request");
|
||||
jest.mock("../CosmosClient");
|
||||
jest.mock("../DataAccessUtilityBase");
|
||||
import { AuthType } from "../../AuthType";
|
||||
import { CreateCollectionParams, DatabaseAccount } from "../../Contracts/DataModels";
|
||||
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||
import { armRequest } from "../../Utils/arm/request";
|
||||
import { client } from "../CosmosClient";
|
||||
import { createCollection, constructRpOptions } from "./createCollection";
|
||||
import { updateUserContext } from "../../UserContext";
|
||||
|
||||
describe("createCollection", () => {
|
||||
const createCollectionParams: CreateCollectionParams = {
|
||||
createNewDatabase: false,
|
||||
collectionId: "testContainer",
|
||||
databaseId: "testDatabase",
|
||||
databaseLevelThroughput: true,
|
||||
offerThroughput: 400
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
updateUserContext({
|
||||
databaseAccount: {
|
||||
name: "test"
|
||||
} as DatabaseAccount,
|
||||
defaultExperience: DefaultAccountExperienceType.DocumentDB
|
||||
});
|
||||
});
|
||||
|
||||
it("should call ARM if logged in with AAD", async () => {
|
||||
window.authType = AuthType.AAD;
|
||||
await createCollection(createCollectionParams);
|
||||
expect(armRequest).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call SDK if not logged in with non-AAD method", async () => {
|
||||
window.authType = AuthType.MasterKey;
|
||||
(client as jest.Mock).mockReturnValue({
|
||||
databases: {
|
||||
createIfNotExists: () => {
|
||||
return {
|
||||
database: {
|
||||
containers: {
|
||||
create: () => ({})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
await createCollection(createCollectionParams);
|
||||
expect(client).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("constructRpOptions should return the correct options", () => {
|
||||
expect(constructRpOptions(createCollectionParams)).toEqual({});
|
||||
|
||||
const manualThroughputParams: CreateCollectionParams = {
|
||||
createNewDatabase: false,
|
||||
collectionId: "testContainer",
|
||||
databaseId: "testDatabase",
|
||||
databaseLevelThroughput: false,
|
||||
offerThroughput: 400
|
||||
};
|
||||
expect(constructRpOptions(manualThroughputParams)).toEqual({ throughput: 400 });
|
||||
|
||||
const autoPilotThroughputParams: CreateCollectionParams = {
|
||||
createNewDatabase: false,
|
||||
collectionId: "testContainer",
|
||||
databaseId: "testDatabase",
|
||||
databaseLevelThroughput: false,
|
||||
offerThroughput: 400,
|
||||
autoPilotMaxThroughput: 4000
|
||||
};
|
||||
expect(constructRpOptions(autoPilotThroughputParams)).toEqual({
|
||||
autoscaleSettings: {
|
||||
maxThroughput: 4000
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
371
src/Common/dataAccess/createCollection.ts
Normal file
371
src/Common/dataAccess/createCollection.ts
Normal file
@@ -0,0 +1,371 @@
|
||||
import * as DataModels from "../../Contracts/DataModels";
|
||||
import * as ErrorParserUtility from "../ErrorParserUtility";
|
||||
import { AuthType } from "../../AuthType";
|
||||
import { ContainerResponse, DatabaseResponse } from "@azure/cosmos";
|
||||
import { ContainerRequest } from "@azure/cosmos/dist-esm/client/Container/ContainerRequest";
|
||||
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
|
||||
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||
import * as ARMTypes from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||
import { client } from "../CosmosClient";
|
||||
import { createMongoCollectionWithProxy } from "../MongoProxyClient";
|
||||
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
|
||||
import {
|
||||
createUpdateCassandraTable,
|
||||
getCassandraTable
|
||||
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||
import {
|
||||
createUpdateMongoDBCollection,
|
||||
getMongoDBCollection
|
||||
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||
import {
|
||||
createUpdateGremlinGraph,
|
||||
getGremlinGraph
|
||||
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
|
||||
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
|
||||
import { logConsoleProgress, logConsoleError, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
|
||||
import { logError } from "../Logger";
|
||||
import { refreshCachedResources } from "../DataAccessUtilityBase";
|
||||
import { sendNotificationForError } from "./sendNotificationForError";
|
||||
import { userContext } from "../../UserContext";
|
||||
import { createDatabase } from "./createDatabase";
|
||||
|
||||
export const createCollection = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||
let collection: DataModels.Collection;
|
||||
const clearMessage = logConsoleProgress(
|
||||
`Creating a new container ${params.collectionId} for database ${params.databaseId}`
|
||||
);
|
||||
try {
|
||||
if (window.authType === AuthType.AAD && !userContext.useSDKOperations) {
|
||||
if (params.createNewDatabase) {
|
||||
const createDatabaseParams: DataModels.CreateDatabaseParams = {
|
||||
autoPilotMaxThroughput: params.autoPilotMaxThroughput,
|
||||
databaseId: params.databaseId,
|
||||
databaseLevelThroughput: params.databaseLevelThroughput,
|
||||
offerThroughput: params.offerThroughput
|
||||
};
|
||||
await createDatabase(createDatabaseParams);
|
||||
}
|
||||
collection = await createCollectionWithARM(params);
|
||||
} else if (userContext.defaultExperience === DefaultAccountExperienceType.MongoDB) {
|
||||
collection = await createMongoCollectionWithProxy(params);
|
||||
} else {
|
||||
collection = await createCollectionWithSDK(params);
|
||||
}
|
||||
} catch (error) {
|
||||
const sanitizedError = ErrorParserUtility.replaceKnownError(JSON.stringify(error));
|
||||
logConsoleError(`Error while creating container ${params.collectionId}:\n ${sanitizedError}`);
|
||||
logError(JSON.stringify(error), "CreateCollection", error.code);
|
||||
sendNotificationForError(error);
|
||||
clearMessage();
|
||||
throw error;
|
||||
}
|
||||
logConsoleInfo(`Successfully created container ${params.collectionId}`);
|
||||
await refreshCachedResources();
|
||||
clearMessage();
|
||||
return collection;
|
||||
};
|
||||
|
||||
const createCollectionWithARM = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||
const defaultExperience = userContext.defaultExperience;
|
||||
switch (defaultExperience) {
|
||||
case DefaultAccountExperienceType.DocumentDB:
|
||||
return createSqlContainer(params);
|
||||
case DefaultAccountExperienceType.MongoDB:
|
||||
return createMongoCollection(params);
|
||||
case DefaultAccountExperienceType.Cassandra:
|
||||
return createCassandraTable(params);
|
||||
case DefaultAccountExperienceType.Graph:
|
||||
return createGraph(params);
|
||||
case DefaultAccountExperienceType.Table:
|
||||
return createTable(params);
|
||||
default:
|
||||
throw new Error(`Unsupported default experience type: ${defaultExperience}`);
|
||||
}
|
||||
};
|
||||
|
||||
const createSqlContainer = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||
try {
|
||||
const getResponse = await getSqlContainer(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId
|
||||
);
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(`Create container failed: container with id ${params.collectionId} already exists`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code !== "NotFound") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
|
||||
const resource: ARMTypes.SqlContainerResource = {
|
||||
id: params.collectionId
|
||||
};
|
||||
if (params.analyticalStorageTtl) {
|
||||
resource.analyticalStorageTtl = params.analyticalStorageTtl;
|
||||
}
|
||||
if (params.indexingPolicy) {
|
||||
resource.indexingPolicy = params.indexingPolicy;
|
||||
}
|
||||
if (params.partitionKey) {
|
||||
resource.partitionKey = params.partitionKey;
|
||||
}
|
||||
if (params.uniqueKeyPolicy) {
|
||||
resource.uniqueKeyPolicy = params.uniqueKeyPolicy;
|
||||
}
|
||||
|
||||
const rpPayload: ARMTypes.SqlDatabaseCreateUpdateParameters = {
|
||||
properties: {
|
||||
resource,
|
||||
options
|
||||
}
|
||||
};
|
||||
|
||||
const createResponse = await createUpdateSqlContainer(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Collection);
|
||||
};
|
||||
|
||||
const createMongoCollection = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||
try {
|
||||
const getResponse = await getMongoDBCollection(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId
|
||||
);
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(`Create collection failed: collection with id ${params.collectionId} already exists`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code !== "NotFound") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
|
||||
const resource: ARMTypes.MongoDBCollectionResource = {
|
||||
id: params.collectionId
|
||||
};
|
||||
if (params.analyticalStorageTtl) {
|
||||
resource.analyticalStorageTtl = params.analyticalStorageTtl;
|
||||
}
|
||||
if (params.partitionKey) {
|
||||
const partitionKeyPath: string = params.partitionKey.paths[0];
|
||||
resource.shardKey = { [partitionKeyPath]: "Hash" };
|
||||
}
|
||||
|
||||
const rpPayload: ARMTypes.MongoDBCollectionCreateUpdateParameters = {
|
||||
properties: {
|
||||
resource,
|
||||
options
|
||||
}
|
||||
};
|
||||
|
||||
const createResponse = await createUpdateMongoDBCollection(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Collection);
|
||||
};
|
||||
|
||||
const createCassandraTable = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||
try {
|
||||
const getResponse = await getCassandraTable(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId
|
||||
);
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(`Create table failed: table with id ${params.collectionId} already exists`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code !== "NotFound") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
|
||||
const resource: ARMTypes.CassandraTableResource = {
|
||||
id: params.collectionId
|
||||
};
|
||||
if (params.analyticalStorageTtl) {
|
||||
resource.analyticalStorageTtl = params.analyticalStorageTtl;
|
||||
}
|
||||
|
||||
const rpPayload: ARMTypes.CassandraTableCreateUpdateParameters = {
|
||||
properties: {
|
||||
resource,
|
||||
options
|
||||
}
|
||||
};
|
||||
|
||||
const createResponse = await createUpdateCassandraTable(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Collection);
|
||||
};
|
||||
|
||||
const createGraph = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||
try {
|
||||
const getResponse = await getGremlinGraph(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId
|
||||
);
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(`Create graph failed: graph with id ${params.collectionId} already exists`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code !== "NotFound") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
|
||||
const resource: ARMTypes.GremlinGraphResource = {
|
||||
id: params.collectionId
|
||||
};
|
||||
|
||||
if (params.indexingPolicy) {
|
||||
resource.indexingPolicy = params.indexingPolicy;
|
||||
}
|
||||
if (params.partitionKey) {
|
||||
resource.partitionKey = params.partitionKey;
|
||||
}
|
||||
if (params.uniqueKeyPolicy) {
|
||||
resource.uniqueKeyPolicy = params.uniqueKeyPolicy;
|
||||
}
|
||||
|
||||
const rpPayload: ARMTypes.GremlinGraphCreateUpdateParameters = {
|
||||
properties: {
|
||||
resource,
|
||||
options
|
||||
}
|
||||
};
|
||||
|
||||
const createResponse = await createUpdateGremlinGraph(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Collection);
|
||||
};
|
||||
|
||||
const createTable = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||
try {
|
||||
const getResponse = await getTable(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.collectionId
|
||||
);
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(`Create table failed: table with id ${params.collectionId} already exists`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code !== "NotFound") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const options: ARMTypes.CreateUpdateOptions = constructRpOptions(params);
|
||||
const resource: ARMTypes.TableResource = {
|
||||
id: params.collectionId
|
||||
};
|
||||
|
||||
const rpPayload: ARMTypes.TableCreateUpdateParameters = {
|
||||
properties: {
|
||||
resource,
|
||||
options
|
||||
}
|
||||
};
|
||||
|
||||
const createResponse = await createUpdateTable(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.collectionId,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Collection);
|
||||
};
|
||||
|
||||
export const constructRpOptions = (params: DataModels.CreateDatabaseParams): ARMTypes.CreateUpdateOptions => {
|
||||
if (params.databaseLevelThroughput) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (params.autoPilotMaxThroughput) {
|
||||
return {
|
||||
autoscaleSettings: {
|
||||
maxThroughput: params.autoPilotMaxThroughput
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
throughput: params.offerThroughput
|
||||
};
|
||||
};
|
||||
|
||||
const createCollectionWithSDK = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||
const createCollectionBody: ContainerRequest = {
|
||||
id: params.collectionId,
|
||||
partitionKey: params.partitionKey || undefined,
|
||||
indexingPolicy: params.indexingPolicy || undefined,
|
||||
uniqueKeyPolicy: params.uniqueKeyPolicy || undefined,
|
||||
analyticalStorageTtl: params.analyticalStorageTtl
|
||||
} as ContainerRequest; // TODO: remove cast when https://github.com/Azure/azure-cosmos-js/issues/423 is fixed
|
||||
const collectionOptions: RequestOptions = {};
|
||||
const createDatabaseBody: DatabaseRequest = { id: params.databaseId };
|
||||
|
||||
if (params.databaseLevelThroughput) {
|
||||
if (params.autoPilotMaxThroughput) {
|
||||
createDatabaseBody.maxThroughput = params.autoPilotMaxThroughput;
|
||||
} else {
|
||||
createDatabaseBody.throughput = params.offerThroughput;
|
||||
}
|
||||
} else {
|
||||
if (params.autoPilotMaxThroughput) {
|
||||
createCollectionBody.maxThroughput = params.autoPilotMaxThroughput;
|
||||
} else {
|
||||
createCollectionBody.throughput = params.offerThroughput;
|
||||
}
|
||||
}
|
||||
|
||||
const databaseResponse: DatabaseResponse = await client().databases.createIfNotExists(createDatabaseBody);
|
||||
const collectionResponse: ContainerResponse = await databaseResponse?.database.containers.create(
|
||||
createCollectionBody,
|
||||
collectionOptions
|
||||
);
|
||||
return collectionResponse?.resource as DataModels.Collection;
|
||||
};
|
||||
@@ -3,8 +3,10 @@ import { AuthType } from "../../AuthType";
|
||||
import { DatabaseResponse } from "@azure/cosmos";
|
||||
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
|
||||
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
|
||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||
import {
|
||||
CassandraKeyspaceCreateUpdateParameters,
|
||||
GremlinDatabaseCreateUpdateParameters,
|
||||
MongoDBDatabaseCreateUpdateParameters,
|
||||
SqlDatabaseCreateUpdateParameters,
|
||||
CreateUpdateOptions
|
||||
} from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||
@@ -79,7 +81,7 @@ async function createSqlDatabase(params: DataModels.CreateDatabaseParams): Promi
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId
|
||||
);
|
||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(`Create database failed: database with id ${params.databaseId} already exists`);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -115,7 +117,7 @@ async function createMongoDatabase(params: DataModels.CreateDatabaseParams): Pro
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId
|
||||
);
|
||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(`Create database failed: database with id ${params.databaseId} already exists`);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -125,7 +127,7 @@ async function createMongoDatabase(params: DataModels.CreateDatabaseParams): Pro
|
||||
}
|
||||
|
||||
const options: CreateUpdateOptions = constructRpOptions(params);
|
||||
const rpPayload: SqlDatabaseCreateUpdateParameters = {
|
||||
const rpPayload: MongoDBDatabaseCreateUpdateParameters = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.databaseId
|
||||
@@ -161,7 +163,7 @@ async function createCassandraKeyspace(params: DataModels.CreateDatabaseParams):
|
||||
}
|
||||
|
||||
const options: CreateUpdateOptions = constructRpOptions(params);
|
||||
const rpPayload: SqlDatabaseCreateUpdateParameters = {
|
||||
const rpPayload: CassandraKeyspaceCreateUpdateParameters = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.databaseId
|
||||
@@ -187,7 +189,7 @@ async function createGremlineDatabase(params: DataModels.CreateDatabaseParams):
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId
|
||||
);
|
||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(`Create database failed: database with id ${params.databaseId} already exists`);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -197,7 +199,7 @@ async function createGremlineDatabase(params: DataModels.CreateDatabaseParams):
|
||||
}
|
||||
|
||||
const options: CreateUpdateOptions = constructRpOptions(params);
|
||||
const rpPayload: SqlDatabaseCreateUpdateParameters = {
|
||||
const rpPayload: GremlinDatabaseCreateUpdateParameters = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.databaseId
|
||||
@@ -217,8 +219,7 @@ async function createGremlineDatabase(params: DataModels.CreateDatabaseParams):
|
||||
|
||||
async function createDatabaseWithSDK(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
|
||||
const createBody: DatabaseRequest = { id: params.databaseId };
|
||||
const databaseOptions: RequestOptions = {};
|
||||
// TODO: replace when SDK support autopilot
|
||||
|
||||
if (params.databaseLevelThroughput) {
|
||||
if (params.autoPilotMaxThroughput) {
|
||||
createBody.maxThroughput = params.autoPilotMaxThroughput;
|
||||
@@ -227,7 +228,7 @@ async function createDatabaseWithSDK(params: DataModels.CreateDatabaseParams): P
|
||||
}
|
||||
}
|
||||
|
||||
const response: DatabaseResponse = await client().databases.create(createBody, databaseOptions);
|
||||
const response: DatabaseResponse = await client().databases.create(createBody);
|
||||
return response.resource;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ async function readCollectionsWithARM(databaseId: string): Promise<DataModels.Co
|
||||
switch (defaultExperience) {
|
||||
case DefaultAccountExperienceType.DocumentDB:
|
||||
rpResponse = await listSqlContainers(subscriptionId, resourceGroup, accountName, databaseId);
|
||||
rpResponse?.value?.map(collection => collection.properties.resource.partitionKey ??= { paths: ["/_partitionKey"], kind: "Hash", version: 2, systemKey: true });
|
||||
break;
|
||||
case DefaultAccountExperienceType.MongoDB:
|
||||
rpResponse = await listMongoDBCollections(subscriptionId, resourceGroup, accountName, databaseId);
|
||||
|
||||
@@ -334,6 +334,19 @@ export interface CreateDatabaseParams {
|
||||
offerThroughput?: number;
|
||||
}
|
||||
|
||||
export interface CreateCollectionParams {
|
||||
createNewDatabase: boolean;
|
||||
collectionId: string;
|
||||
databaseId: string;
|
||||
databaseLevelThroughput: boolean;
|
||||
offerThroughput: number;
|
||||
analyticalStorageTtl?: number;
|
||||
autoPilotMaxThroughput?: number;
|
||||
indexingPolicy?: IndexingPolicy;
|
||||
partitionKey?: PartitionKey;
|
||||
uniqueKeyPolicy?: UniqueKeyPolicy;
|
||||
}
|
||||
|
||||
export interface SharedThroughputRange {
|
||||
minimumRU: number;
|
||||
maximumRU: number;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { StringUtils } from "../../../Utils/StringUtils";
|
||||
import { KeyCodes } from "../../../Common/Constants";
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||
import CollapseChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png";
|
||||
|
||||
|
||||
@@ -265,6 +265,9 @@ exports[`test render renders with filters 1`] = `
|
||||
"buttonTextDisabled": "#a19f9d",
|
||||
"buttonTextHovered": "#201f1e",
|
||||
"buttonTextPressed": "#201f1e",
|
||||
"cardShadow": "0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)",
|
||||
"cardShadowHovered": "0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)",
|
||||
"cardStandoutBackground": "#ffffff",
|
||||
"defaultStateBackground": "#faf9f8",
|
||||
"disabledBackground": "#f3f2f1",
|
||||
"disabledBodySubtext": "#c8c6c4",
|
||||
@@ -604,6 +607,9 @@ exports[`test render renders with filters 1`] = `
|
||||
"buttonTextDisabled": "#a19f9d",
|
||||
"buttonTextHovered": "#201f1e",
|
||||
"buttonTextPressed": "#201f1e",
|
||||
"cardShadow": "0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)",
|
||||
"cardShadowHovered": "0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)",
|
||||
"cardStandoutBackground": "#ffffff",
|
||||
"defaultStateBackground": "#faf9f8",
|
||||
"disabledBackground": "#f3f2f1",
|
||||
"disabledBodySubtext": "#c8c6c4",
|
||||
@@ -997,6 +1003,9 @@ exports[`test render renders with filters 1`] = `
|
||||
"buttonTextDisabled": "#a19f9d",
|
||||
"buttonTextHovered": "#201f1e",
|
||||
"buttonTextPressed": "#201f1e",
|
||||
"cardShadow": "0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)",
|
||||
"cardShadowHovered": "0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)",
|
||||
"cardStandoutBackground": "#ffffff",
|
||||
"defaultStateBackground": "#faf9f8",
|
||||
"disabledBackground": "#f3f2f1",
|
||||
"disabledBodySubtext": "#c8c6c4",
|
||||
@@ -1113,6 +1122,11 @@ exports[`test render renders with filters 1`] = `
|
||||
},
|
||||
"iconDisabled": Object {
|
||||
"color": "#a19f9d",
|
||||
"selectors": Object {
|
||||
"@media screen and (-ms-high-contrast: active)": Object {
|
||||
"color": "GrayText",
|
||||
},
|
||||
},
|
||||
},
|
||||
"label": Array [
|
||||
Object {
|
||||
@@ -1134,6 +1148,11 @@ exports[`test render renders with filters 1`] = `
|
||||
},
|
||||
"menuIconDisabled": Object {
|
||||
"color": "#a19f9d",
|
||||
"selectors": Object {
|
||||
"@media screen and (-ms-high-contrast: active)": Object {
|
||||
"color": "GrayText",
|
||||
},
|
||||
},
|
||||
},
|
||||
"root": Array [
|
||||
Object {
|
||||
@@ -1150,7 +1169,6 @@ exports[`test render renders with filters 1`] = `
|
||||
"right": 2,
|
||||
"selectors": Object {
|
||||
"@media screen and (-ms-high-contrast: active)": Object {
|
||||
"border": "none",
|
||||
"bottom": -2,
|
||||
"left": -2,
|
||||
"outlineColor": "ButtonText",
|
||||
@@ -1230,7 +1248,6 @@ exports[`test render renders with filters 1`] = `
|
||||
"right": 2,
|
||||
"selectors": Object {
|
||||
"@media screen and (-ms-high-contrast: active)": Object {
|
||||
"border": "none",
|
||||
"bottom": -2,
|
||||
"left": -2,
|
||||
"outlineColor": "ButtonText",
|
||||
@@ -1259,10 +1276,6 @@ exports[`test render renders with filters 1`] = `
|
||||
":hover": Object {
|
||||
"outline": 0,
|
||||
},
|
||||
"@media screen and (-ms-high-contrast: active)": Object {
|
||||
"borderColor": "grayText",
|
||||
"color": "grayText",
|
||||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
@@ -1362,13 +1375,21 @@ exports[`test render renders with filters 1`] = `
|
||||
"selectors": Object {
|
||||
"@media screen and (-ms-high-contrast: active)": Object {
|
||||
"MsHighContrastAdjust": "none",
|
||||
"backgroundColor": "WindowText",
|
||||
"color": "Window",
|
||||
"backgroundColor": "Window",
|
||||
"border": "1px solid WindowText",
|
||||
"borderRightWidth": "0",
|
||||
"color": "WindowText",
|
||||
},
|
||||
},
|
||||
},
|
||||
".ms-Button--primary + .ms-Button": Object {
|
||||
"border": "none",
|
||||
"selectors": Object {
|
||||
"@media screen and (-ms-high-contrast: active)": Object {
|
||||
"border": "1px solid WindowText",
|
||||
"borderLeftWidth": "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1408,6 +1429,9 @@ exports[`test render renders with filters 1`] = `
|
||||
"borderColor": "GrayText",
|
||||
"color": "GrayText",
|
||||
},
|
||||
"@media screen and (forced-colors: active)": Object {
|
||||
"forcedColorAdjust": "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
"splitButtonContainerFocused": Object {
|
||||
@@ -1554,6 +1578,13 @@ exports[`test render renders with filters 1`] = `
|
||||
},
|
||||
},
|
||||
},
|
||||
".ms-Button-menuIcon": Object {
|
||||
"selectors": Object {
|
||||
"@media screen and (-ms-high-contrast: active)": Object {
|
||||
"color": "GrayText",
|
||||
},
|
||||
},
|
||||
},
|
||||
":hover": Object {
|
||||
"cursor": "default",
|
||||
},
|
||||
@@ -1775,6 +1806,9 @@ exports[`test render renders with filters 1`] = `
|
||||
"buttonTextDisabled": "#a19f9d",
|
||||
"buttonTextHovered": "#201f1e",
|
||||
"buttonTextPressed": "#201f1e",
|
||||
"cardShadow": "0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)",
|
||||
"cardShadowHovered": "0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)",
|
||||
"cardStandoutBackground": "#ffffff",
|
||||
"defaultStateBackground": "#faf9f8",
|
||||
"disabledBackground": "#f3f2f1",
|
||||
"disabledBodySubtext": "#c8c6c4",
|
||||
|
||||
@@ -6,7 +6,7 @@ import { RepoListItem } from "./GitHubReposComponent";
|
||||
import { ChildrenMargin } from "./GitHubStyleConstants";
|
||||
import * as GitHubUtils from "../../../Utils/GitHubUtils";
|
||||
import { IGitHubRepo } from "../../../GitHub/GitHubClient";
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import UrlUtility from "../../../Common/UrlUtility";
|
||||
import Explorer from "../../Explorer";
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
} from "office-ui-fabric-react/lib/utilities/selection/index";
|
||||
import { StyleConstants } from "../../../Common/Constants";
|
||||
import { TextField, ITextFieldProps, ITextField } from "office-ui-fabric-react/lib/TextField";
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
|
||||
import SaveQueryBannerIcon from "../../../../images/save_query_banner.png";
|
||||
import { QueriesClient } from "../../../Common/QueriesClient";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
jest.mock("../../Common/DocumentClientUtilityBase");
|
||||
jest.mock("../../Common/dataAccess/createCollection");
|
||||
import * as ko from "knockout";
|
||||
import * as sinon from "sinon";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
@@ -33,8 +34,8 @@ describe("ContainerSampleGenerator", () => {
|
||||
databaseId: sampleDatabaseId,
|
||||
offerThroughput: 400,
|
||||
databaseLevelThroughput: false,
|
||||
createNewDatabase: true,
|
||||
collectionId: sampleCollectionId,
|
||||
rupmEnabled: false,
|
||||
data: [
|
||||
{
|
||||
firstname: "Eva",
|
||||
@@ -99,8 +100,8 @@ describe("ContainerSampleGenerator", () => {
|
||||
databaseId: sampleDatabaseId,
|
||||
offerThroughput: 400,
|
||||
databaseLevelThroughput: false,
|
||||
createNewDatabase: true,
|
||||
collectionId: sampleCollectionId,
|
||||
rupmEnabled: false,
|
||||
data: [
|
||||
"g.addV('person').property(id, '1').property('_partitionKey','pk').property('name', 'Eva').property('age', 44)"
|
||||
]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as Constants from "../../Common/Constants";
|
||||
import * as DataModels from "../../Contracts/DataModels";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import GraphTab from ".././Tabs/GraphTab";
|
||||
@@ -6,10 +5,11 @@ import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsol
|
||||
import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient";
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import Explorer from "../Explorer";
|
||||
import { createDocument, getOrCreateDatabaseAndCollection } from "../../Common/DocumentClientUtilityBase";
|
||||
import { createDocument } from "../../Common/DocumentClientUtilityBase";
|
||||
import { createCollection } from "../../Common/dataAccess/createCollection";
|
||||
import { userContext } from "../../UserContext";
|
||||
|
||||
interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest {
|
||||
interface SampleDataFile extends DataModels.CreateCollectionParams {
|
||||
data: any[];
|
||||
}
|
||||
|
||||
@@ -54,18 +54,11 @@ export class ContainerSampleGenerator {
|
||||
}
|
||||
|
||||
private async createContainerAsync(): Promise<ViewModels.Collection> {
|
||||
const createRequest: DataModels.CreateDatabaseAndCollectionRequest = {
|
||||
const createRequest: DataModels.CreateCollectionParams = {
|
||||
...this.sampleDataFile
|
||||
};
|
||||
|
||||
const options: any = {};
|
||||
if (this.container.isPreferredApiMongoDB()) {
|
||||
options.initialHeaders = options.initialHeaders || {};
|
||||
options.initialHeaders[Constants.HttpHeaders.supportSpatialLegacyCoordinates] = true;
|
||||
options.initialHeaders[Constants.HttpHeaders.usePolygonsSmallerThanAHemisphere] = true;
|
||||
}
|
||||
|
||||
await getOrCreateDatabaseAndCollection(createRequest, options);
|
||||
await createCollection(createRequest);
|
||||
await this.container.refreshAllDatabases();
|
||||
const database = this.container.findDatabaseWithId(this.sampleDataFile.databaseId);
|
||||
if (!database) {
|
||||
|
||||
@@ -26,7 +26,7 @@ import NewVertexPane from "./Panes/NewVertexPane";
|
||||
import NotebookV2Tab, { NotebookTabOptions } from "./Tabs/NotebookV2Tab";
|
||||
import Q from "q";
|
||||
import ResourceTokenCollection from "./Tree/ResourceTokenCollection";
|
||||
import TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor";
|
||||
import TerminalTab from "./Tabs/TerminalTab";
|
||||
import { Action, ActionModifiers } from "../Shared/Telemetry/TelemetryConstants";
|
||||
import { ActionContracts, MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
@@ -3117,12 +3117,6 @@ export default class Explorer {
|
||||
} else {
|
||||
loadingTitle.innerHTML = title;
|
||||
}
|
||||
|
||||
TelemetryProcessor.trace(
|
||||
Action.LoadingStatus,
|
||||
ActionModifiers.Mark,
|
||||
title !== "Welcome to Azure Cosmos DB" ? `Title: ${title}, Text: ${text}` : text
|
||||
);
|
||||
}
|
||||
|
||||
private _openSetupNotebooksPaneForQuickstart(): void {
|
||||
|
||||
@@ -23,7 +23,7 @@ import { GraphConfig } from "../../Tabs/GraphTab";
|
||||
import { EditorReact } from "../../Controls/Editor/EditorReact";
|
||||
import LoadGraphIcon from "../../../../images/LoadGraph.png";
|
||||
import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as Constants from "../../../Common/Constants";
|
||||
import { InputProperty } from "../../../Contracts/ViewModels";
|
||||
import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos";
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import { PlatformType } from "../../../PlatformType";
|
||||
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||
import { Areas } from "../../../Common/Constants";
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
|
||||
import AddDatabaseIcon from "../../../../images/AddDatabase.svg";
|
||||
import AddCollectionIcon from "../../../../images/AddCollection.svg";
|
||||
|
||||
@@ -32,7 +32,7 @@ import { Store, AnyAction, MiddlewareAPI, Middleware, Dispatch } from "redux";
|
||||
import configureStore from "./NotebookComponent/store";
|
||||
|
||||
import { Notification } from "react-notification-system";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
|
||||
export type KernelSpecsDisplay = { name: string; displayName: string };
|
||||
|
||||
@@ -37,7 +37,7 @@ import * as Constants from "../../../Common/Constants";
|
||||
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
|
||||
import { ConsoleDataType } from "../../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import * as CdbActions from "./actions";
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action as TelemetryAction } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||
import { CdbAppState } from "./types";
|
||||
import { decryptJWTToken } from "../../../Utils/AuthorizationUtils";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { actions, CoreRecord, reducers as nteractReducers } from "@nteract/core";
|
||||
import { Action } from "redux";
|
||||
import { Areas } from "../../../Common/Constants";
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as cdbActions from "./actions";
|
||||
import { CdbRecord } from "./types";
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as Logger from "../../Common/Logger";
|
||||
import { HttpStatusCodes, Areas } from "../../Common/Constants";
|
||||
import { GitHubReposPane } from "../Panes/GitHubReposPane";
|
||||
import ko from "knockout";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { IContentProvider } from "@nteract/core";
|
||||
import { NotebookContentProvider } from "./NotebookComponent/NotebookContentProvider";
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<!-- Add collection header - Start -->
|
||||
<div class="firstdivbg headerline">
|
||||
<span id="containerTitle" data-bind="text: title"></span>
|
||||
<div class="closeImg" id="closeBtnAddCollection" role="button" aria-label="Close pane"
|
||||
<div class="closeImg" id="closeBtnAddCollection" role="button" aria-label="Add collection close pane"
|
||||
data-bind="click: cancel, event: { keypress: onCloseKeyPress }" tabindex="0">
|
||||
<img src="../../../images/close-black.svg" title="Close" alt="Close" />
|
||||
</div>
|
||||
|
||||
@@ -9,18 +9,15 @@ import * as PricingUtils from "../../Utils/PricingUtils";
|
||||
import * as SharedConstants from "../../Shared/Constants";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import editable from "../../Common/EditableUtility";
|
||||
import EnvironmentUtility from "../../Common/EnvironmentUtility";
|
||||
import Q from "q";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { configContext, Platform } from "../../ConfigContext";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import { createMongoCollectionWithARM, createMongoCollectionWithProxy } from "../../Common/MongoProxyClient";
|
||||
import { DynamicListItem } from "../Controls/DynamicList/DynamicListComponent";
|
||||
import { HashMap } from "../../Common/HashMap";
|
||||
import { PlatformType } from "../../PlatformType";
|
||||
import { refreshCachedResources, getOrCreateDatabaseAndCollection } from "../../Common/DocumentClientUtilityBase";
|
||||
import { userContext } from "../../UserContext";
|
||||
import { refreshCachedResources } from "../../Common/DocumentClientUtilityBase";
|
||||
import { createCollection } from "../../Common/dataAccess/createCollection";
|
||||
|
||||
export interface AddCollectionPaneOptions extends ViewModels.PaneOptions {
|
||||
isPreferredApiTable: ko.Computed<boolean>;
|
||||
@@ -811,7 +808,6 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
||||
|
||||
let databaseId: string = this.databaseCreateNew() ? this.databaseId().trim() : this.databaseId();
|
||||
let collectionId: string = this.collectionId().trim();
|
||||
let rupm: boolean = this.rupm() === Constants.RUPMStates.on;
|
||||
|
||||
let indexingPolicy: DataModels.IndexingPolicy;
|
||||
// todo - remove mongo indexing policy ticket # 616274
|
||||
@@ -828,130 +824,28 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
||||
}
|
||||
|
||||
this.formErrors("");
|
||||
|
||||
this.isExecuting(true);
|
||||
|
||||
const createRequest: DataModels.CreateDatabaseAndCollectionRequest = {
|
||||
const databaseLevelThroughput: boolean = this.databaseCreateNew()
|
||||
? this.databaseCreateNewShared()
|
||||
: this.databaseHasSharedOffer() && !this.collectionWithThroughputInShared();
|
||||
const autoPilotMaxThroughput: number = databaseLevelThroughput
|
||||
? this.isSharedAutoPilotSelected() && this.sharedAutoPilotThroughput()
|
||||
: this.isAutoPilotSelected() && this.autoPilotThroughput();
|
||||
const createCollectionParams: DataModels.CreateCollectionParams = {
|
||||
createNewDatabase: this.databaseCreateNew(),
|
||||
collectionId,
|
||||
databaseId,
|
||||
databaseLevelThroughput,
|
||||
offerThroughput,
|
||||
databaseLevelThroughput: this.databaseHasSharedOffer() && !this.collectionWithThroughputInShared(),
|
||||
rupmEnabled: rupm,
|
||||
partitionKey,
|
||||
indexingPolicy,
|
||||
uniqueKeyPolicy,
|
||||
autoPilot,
|
||||
analyticalStorageTtl: this._getAnalyticalStorageTtl(),
|
||||
hasAutoPilotV2FeatureFlag: this.hasAutoPilotV2FeatureFlag()
|
||||
autoPilotMaxThroughput,
|
||||
indexingPolicy,
|
||||
partitionKey,
|
||||
uniqueKeyPolicy
|
||||
};
|
||||
|
||||
const options: any = {};
|
||||
if (this.container.isPreferredApiMongoDB()) {
|
||||
options.initialHeaders = options.initialHeaders || {};
|
||||
options.initialHeaders[Constants.HttpHeaders.supportSpatialLegacyCoordinates] = true;
|
||||
options.initialHeaders[Constants.HttpHeaders.usePolygonsSmallerThanAHemisphere] = true;
|
||||
}
|
||||
|
||||
const databaseCreateNew = this.databaseCreateNew();
|
||||
const useDatabaseSharedOffer = this.shouldUseDatabaseThroughput();
|
||||
const isSharded: boolean = !!partitionKeyPath;
|
||||
const autopilotSettings: DataModels.RpOptions = this._getAutopilotSettings();
|
||||
|
||||
let createCollectionFunc: () => Q.Promise<DataModels.Collection | DataModels.CreateCollectionWithRpResponse>;
|
||||
|
||||
if (this.container.isPreferredApiMongoDB()) {
|
||||
const isFixedCollectionWithSharedThroughputBeingCreated =
|
||||
this.container.isFixedCollectionWithSharedThroughputSupported() &&
|
||||
!this.isUnlimitedStorageSelected() &&
|
||||
this.databaseHasSharedOffer();
|
||||
const isAadUser = EnvironmentUtility.isAadUser();
|
||||
|
||||
// note: v3 autopilot not supported yet for Mongo fixed collections (only tier supported)
|
||||
if (!isAadUser || isFixedCollectionWithSharedThroughputBeingCreated) {
|
||||
createCollectionFunc = () =>
|
||||
Q(
|
||||
createMongoCollectionWithProxy(
|
||||
databaseId,
|
||||
collectionId,
|
||||
offerThroughput,
|
||||
partitionKeyPath,
|
||||
databaseCreateNew,
|
||||
useDatabaseSharedOffer,
|
||||
isSharded,
|
||||
autopilotSettings
|
||||
)
|
||||
);
|
||||
} else {
|
||||
createCollectionFunc = () =>
|
||||
Q(
|
||||
createMongoCollectionWithARM(
|
||||
this.container.armEndpoint(),
|
||||
databaseId,
|
||||
this._getAnalyticalStorageTtl(),
|
||||
collectionId,
|
||||
offerThroughput,
|
||||
partitionKeyPath,
|
||||
databaseCreateNew,
|
||||
useDatabaseSharedOffer,
|
||||
isSharded,
|
||||
autopilotSettings
|
||||
)
|
||||
);
|
||||
}
|
||||
} else if (this.container.isPreferredApiTable() && EnvironmentUtility.isAadUser()) {
|
||||
createCollectionFunc = () =>
|
||||
Q(
|
||||
AddCollectionUtility.Utilities.createAzureTableWithARM(
|
||||
this.container.armEndpoint(),
|
||||
createRequest,
|
||||
autopilotSettings
|
||||
)
|
||||
);
|
||||
} else if (this.container.isPreferredApiGraph() && EnvironmentUtility.isAadUser()) {
|
||||
createCollectionFunc = () =>
|
||||
Q(
|
||||
AddCollectionUtility.CreateCollectionUtilities.createGremlinGraph(
|
||||
this.container.armEndpoint(),
|
||||
databaseId,
|
||||
collectionId,
|
||||
indexingPolicy,
|
||||
offerThroughput,
|
||||
partitionKeyPath,
|
||||
partitionKey.version,
|
||||
databaseCreateNew,
|
||||
useDatabaseSharedOffer,
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
autopilotSettings
|
||||
)
|
||||
);
|
||||
} else if (this.container.isPreferredApiDocumentDB() && EnvironmentUtility.isAadUser()) {
|
||||
createCollectionFunc = () =>
|
||||
Q(
|
||||
AddCollectionUtility.CreateSqlCollectionUtilities.createSqlCollection(
|
||||
this.container.armEndpoint(),
|
||||
databaseId,
|
||||
this._getAnalyticalStorageTtl(),
|
||||
collectionId,
|
||||
indexingPolicy,
|
||||
offerThroughput,
|
||||
partitionKeyPath,
|
||||
partitionKey.version,
|
||||
databaseCreateNew,
|
||||
useDatabaseSharedOffer,
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
uniqueKeyPolicy,
|
||||
autopilotSettings
|
||||
)
|
||||
);
|
||||
} else {
|
||||
createCollectionFunc = () => getOrCreateDatabaseAndCollection(createRequest, options);
|
||||
}
|
||||
|
||||
createCollectionFunc().then(
|
||||
createCollection(createCollectionParams).then(
|
||||
() => {
|
||||
this.isExecuting(false);
|
||||
this.close();
|
||||
@@ -1049,7 +943,7 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
||||
const defaultThroughput = this.container.collectionCreationDefaults.throughput;
|
||||
this.throughputSinglePartition(defaultThroughput.fixed);
|
||||
this.throughputMultiPartition(
|
||||
AddCollectionUtility.Utilities.getMaxThroughput(this.container.collectionCreationDefaults, this.container)
|
||||
AddCollectionUtility.getMaxThroughput(this.container.collectionCreationDefaults, this.container)
|
||||
);
|
||||
|
||||
this.throughputDatabase(defaultThroughput.shared);
|
||||
@@ -1234,35 +1128,6 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
||||
|
||||
return undefined;
|
||||
}
|
||||
private _getAutopilotSettings(): DataModels.RpOptions {
|
||||
if (
|
||||
(!this.hasAutoPilotV2FeatureFlag() &&
|
||||
this.databaseCreateNewShared() &&
|
||||
this.isSharedAutoPilotSelected() &&
|
||||
this.sharedAutoPilotThroughput()) ||
|
||||
(this.hasAutoPilotV2FeatureFlag() &&
|
||||
this.databaseCreateNewShared() &&
|
||||
this.isSharedAutoPilotSelected() &&
|
||||
this.selectedSharedAutoPilotTier())
|
||||
) {
|
||||
return !this.hasAutoPilotV2FeatureFlag()
|
||||
? {
|
||||
[Constants.HttpHeaders.autoPilotThroughput]: { maxThroughput: this.sharedAutoPilotThroughput() * 1 }
|
||||
}
|
||||
: { [Constants.HttpHeaders.autoPilotTier]: this.selectedSharedAutoPilotTier().toString() };
|
||||
}
|
||||
if (
|
||||
(!this.hasAutoPilotV2FeatureFlag() && this.isAutoPilotSelected() && this.autoPilotThroughput()) ||
|
||||
(this.hasAutoPilotV2FeatureFlag() && this.isAutoPilotSelected() && this.selectedAutoPilotTier())
|
||||
) {
|
||||
return !this.hasAutoPilotV2FeatureFlag()
|
||||
? {
|
||||
[Constants.HttpHeaders.autoPilotThroughput]: { maxThroughput: this.autoPilotThroughput() * 1 }
|
||||
}
|
||||
: { [Constants.HttpHeaders.autoPilotTier]: this.selectedAutoPilotTier().toString() };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private _calculateNumberOfPartitions(): number {
|
||||
// Note: this will not validate properly on accounts that have been set up for custom partitioning,
|
||||
@@ -1302,17 +1167,19 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
||||
|
||||
private _updateThroughputLimitByCollectionStorage() {
|
||||
const storage = this.storage();
|
||||
const minThroughputRU = AddCollectionUtility.Utilities.getMinRUForStorageOption(
|
||||
this.container.collectionCreationDefaults,
|
||||
storage
|
||||
);
|
||||
const minThroughputRU =
|
||||
storage === SharedConstants.CollectionCreation.storage10Gb
|
||||
? SharedConstants.CollectionCreation.DefaultCollectionRUs400
|
||||
: this.container.collectionCreationDefaults.throughput.unlimitedmin;
|
||||
|
||||
let maxThroughputRU = AddCollectionUtility.Utilities.getMaxRUForStorageOption(
|
||||
this.container.collectionCreationDefaults,
|
||||
storage
|
||||
);
|
||||
let maxThroughputRU;
|
||||
if (this.isTryCosmosDBSubscription()) {
|
||||
maxThroughputRU = Constants.TryCosmosExperience.maxRU;
|
||||
} else {
|
||||
maxThroughputRU =
|
||||
storage === SharedConstants.CollectionCreation.storage10Gb
|
||||
? SharedConstants.CollectionCreation.DefaultCollectionRUs10K
|
||||
: this.container.collectionCreationDefaults.throughput.unlimitedmax;
|
||||
}
|
||||
|
||||
this.minThroughputRU(minThroughputRU);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as AddCollectionUtility from "../../Shared/AddCollectionUtility";
|
||||
import * as AutoPilotUtils from "../../Utils/AutoPilotUtils";
|
||||
import * as Constants from "../../Common/Constants";
|
||||
import * as DataModels from "../../Contracts/DataModels";
|
||||
@@ -8,15 +7,11 @@ import * as PricingUtils from "../../Utils/PricingUtils";
|
||||
import * as SharedConstants from "../../Shared/Constants";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import editable from "../../Common/EditableUtility";
|
||||
import EnvironmentUtility from "../../Common/EnvironmentUtility";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { AddDbUtilities } from "../../Shared/AddDatabaseUtility";
|
||||
import { CassandraAPIDataClient } from "../Tables/TableDataClient";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import { createDatabase } from "../../Common/dataAccess/createDatabase";
|
||||
import { PlatformType } from "../../PlatformType";
|
||||
import { userContext } from "../../UserContext";
|
||||
|
||||
export default class AddDatabasePane extends ContextualPaneBase {
|
||||
public defaultExperience: ko.Computed<string>;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Areas } from "../../Common/Constants";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import * as Logger from "../../Common/Logger";
|
||||
import { QueriesGridComponentAdapter } from "../Controls/QueriesGridReactComponent/QueriesGridComponentAdapter";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import QueryTab from "../Tabs/QueryTab";
|
||||
|
||||
export class BrowseQueriesPane extends ContextualPaneBase {
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as ko from "knockout";
|
||||
import * as PricingUtils from "../../Utils/PricingUtils";
|
||||
import * as SharedConstants from "../../Shared/Constants";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { CassandraAPIDataClient } from "../Tables/TableDataClient";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
@@ -494,9 +494,7 @@ export default class CassandraAddCollectionPane extends ContextualPaneBase {
|
||||
this.selectedSharedAutoPilotTier(null);
|
||||
this.selectedAutoPilotThroughput(AutoPilotUtils.minAutoPilotThroughput);
|
||||
this.sharedAutoPilotThroughput(AutoPilotUtils.minAutoPilotThroughput);
|
||||
this.throughput(
|
||||
AddCollectionUtility.Utilities.getMaxThroughput(this.container.collectionCreationDefaults, this.container)
|
||||
);
|
||||
this.throughput(AddCollectionUtility.getMaxThroughput(this.container.collectionCreationDefaults, this.container));
|
||||
this.keyspaceThroughput(throughputDefaults.shared);
|
||||
this.maxThroughputRU(throughputDefaults.unlimitedmax);
|
||||
this.minThroughputRU(throughputDefaults.unlimitedmin);
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as Constants from "../../Common/Constants";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { KeyCodes } from "../../Common/Constants";
|
||||
import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import Explorer from "../Explorer";
|
||||
|
||||
// TODO: Use specific actions for logging telemetry data
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
|
||||
import DeleteCollectionConfirmationPane from "./DeleteCollectionConfirmationPane";
|
||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
||||
import Explorer from "../Explorer";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { TreeNode } from "../../Contracts/ViewModels";
|
||||
import { deleteCollection } from "../../Common/dataAccess/deleteCollection";
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility";
|
||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { deleteCollection } from "../../Common/dataAccess/deleteCollection";
|
||||
|
||||
export default class DeleteCollectionConfirmationPane extends ContextualPaneBase {
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import DeleteDatabaseConfirmationPane from "./DeleteDatabaseConfirmationPane";
|
||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
||||
import Explorer from "../Explorer";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { TreeNode } from "../../Contracts/ViewModels";
|
||||
import { TabsManager } from "../Tabs/TabsManager";
|
||||
import { deleteDatabase } from "../../Common/dataAccess/deleteDatabase";
|
||||
|
||||
@@ -11,7 +11,7 @@ import { DefaultExperienceUtility } from "../../Shared/DefaultExperienceUtility"
|
||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
||||
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { deleteDatabase } from "../../Common/dataAccess/deleteDatabase";
|
||||
|
||||
export default class DeleteDatabaseConfirmationPane extends ContextualPaneBase {
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { GitHubClient, IGitHubPageInfo, IGitHubRepo } from "../../GitHub/GitHubClient";
|
||||
import { IPinnedRepo, JunoClient } from "../../Juno/JunoClient";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as GitHubUtils from "../../Utils/GitHubUtils";
|
||||
import { JunoUtils } from "../../Utils/JunoUtils";
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import QueryTab from "../Tabs/QueryTab";
|
||||
|
||||
export class SaveQueryPane extends ContextualPaneBase {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Areas, KeyCodes } from "../../Common/Constants";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as ko from "knockout";
|
||||
|
||||
export class SetupNotebooksPane extends ContextualPaneBase {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { DirectoryListProps } from "../Controls/Directory/DirectoryListComponent
|
||||
import { DefaultDirectoryDropdownProps } from "../Controls/Directory/DefaultDirectoryDropdownComponent";
|
||||
import { DirectoryComponentAdapter } from "../Controls/Directory/DirectoryComponentAdapter";
|
||||
import SwitchDirectoryPaneTemplate from "./SwitchDirectoryPane.html";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
|
||||
class PaneComponent {
|
||||
constructor(data: any) {
|
||||
|
||||
@@ -45,7 +45,7 @@ export class SplashScreenComponent extends React.Component<SplashScreenComponent
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
>
|
||||
<img src={item.iconSrc} alt={item.title} />
|
||||
<img src={item.iconSrc} alt="" />
|
||||
<div className="legendContainer">
|
||||
<div className="legend">{item.title}</div>
|
||||
<div className="description">{item.description}</div>
|
||||
@@ -66,7 +66,7 @@ export class SplashScreenComponent extends React.Component<SplashScreenComponent
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
>
|
||||
<img src={item.iconSrc} alt={item.title} />
|
||||
<img src={item.iconSrc} alt="" />
|
||||
<span className="oneLineContent" title={item.info}>
|
||||
{item.title}
|
||||
</span>
|
||||
@@ -79,7 +79,7 @@ export class SplashScreenComponent extends React.Component<SplashScreenComponent
|
||||
<ul>
|
||||
{this.props.recentItems.map((item: SplashScreenItem, index: number) => (
|
||||
<li key={`${item.title}${item.description}${index}`}>
|
||||
<img src={item.iconSrc} alt={item.title} />
|
||||
<img src={item.iconSrc} alt="" />
|
||||
<span className="twoLineContent">
|
||||
<Link onClick={item.onClick} title={item.info}>
|
||||
{item.title}
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as CommonConstants from "../../../Common/Constants";
|
||||
import * as Constants from "../Constants";
|
||||
import * as Entities from "../Entities";
|
||||
import QueryTablesTab from "../../Tabs/QueryTablesTab";
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { QueryIterator, ItemDefinition, Resource } from "@azure/cosmos";
|
||||
|
||||
// This is the format of the data we will have to pass to Datatable render callback,
|
||||
|
||||
@@ -15,7 +15,7 @@ import * as Utilities from "../Utilities";
|
||||
import * as Entities from "../Entities";
|
||||
import QueryTablesTab from "../../Tabs/QueryTablesTab";
|
||||
import * as TableEntityProcessor from "../TableEntityProcessor";
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as ErrorParserUtility from "../../../Common/ErrorParserUtility";
|
||||
import * as DataModels from "../../../Contracts/DataModels";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
|
||||
@@ -13,7 +13,7 @@ import * as HeadersUtility from "../../Common/HeadersUtility";
|
||||
import TabsBase from "./TabsBase";
|
||||
import { DocumentsGridMetrics } from "../../Common/Constants";
|
||||
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import SaveIcon from "../../../images/save-cosmos.svg";
|
||||
import DiscardIcon from "../../../images/discard.svg";
|
||||
import DeleteIcon from "../../../images/delete.svg";
|
||||
|
||||
@@ -11,7 +11,7 @@ import editable from "../../Common/EditableUtility";
|
||||
import Q from "q";
|
||||
import SaveIcon from "../../../images/save-cosmos.svg";
|
||||
import TabsBase from "./TabsBase";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { PlatformType } from "../../PlatformType";
|
||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||
|
||||
@@ -14,7 +14,7 @@ import TabsBase from "./TabsBase";
|
||||
import { DocumentsGridMetrics } from "../../Common/Constants";
|
||||
import { QueryUtils } from "../../Utils/QueryUtils";
|
||||
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import NewDocumentIcon from "../../../images/NewDocument.svg";
|
||||
import SaveIcon from "../../../images/save-cosmos.svg";
|
||||
import DiscardIcon from "../../../images/discard.svg";
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as ErrorParserUtility from "../../Common/ErrorParserUtility";
|
||||
import MongoUtility from "../../Common/MongoUtility";
|
||||
import ObjectId from "../Tree/ObjectId";
|
||||
import Q from "q";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import {
|
||||
createDocument,
|
||||
|
||||
@@ -6,7 +6,7 @@ import EnvironmentUtility from "../../Common/EnvironmentUtility";
|
||||
import { isInvalidParentFrameOrigin } from "../../Utils/MessageValidation";
|
||||
import Q from "q";
|
||||
import TabsBase from "./TabsBase";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { HashMap } from "../../Common/HashMap";
|
||||
|
||||
@@ -17,7 +17,7 @@ import SaveIcon from "../../../images/save-cosmos.svg";
|
||||
import ClearAllOutputsIcon from "../../../images/notebook/Notebook-clear-all-outputs.svg";
|
||||
import InterruptKernelIcon from "../../../images/notebook/Notebook-stop.svg";
|
||||
import KillKernelIcon from "../../../images/notebook/Notebook-stop.svg";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { Areas, ArmApiVersions } from "../../Common/Constants";
|
||||
import { CommandBarComponentButtonFactory } from "../Menus/CommandBar/CommandBarComponentButtonFactory";
|
||||
|
||||
@@ -10,7 +10,7 @@ import { HashMap } from "../../Common/HashMap";
|
||||
import * as HeadersUtility from "../../Common/HeadersUtility";
|
||||
import * as Logger from "../../Common/Logger";
|
||||
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg";
|
||||
import { QueryUtils } from "../../Utils/QueryUtils";
|
||||
import SaveQueryIcon from "../../../images/save-cosmos.svg";
|
||||
|
||||
@@ -12,7 +12,7 @@ import editable from "../../Common/EditableUtility";
|
||||
import Q from "q";
|
||||
import SaveIcon from "../../../images/save-cosmos.svg";
|
||||
import TabsBase from "./TabsBase";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { PlatformType } from "../../PlatformType";
|
||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import editable from "../../Common/EditableUtility";
|
||||
import ScriptTabBase from "./ScriptTabBase";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg";
|
||||
import StoredProcedure from "../Tree/StoredProcedure";
|
||||
import { createStoredProcedure, updateStoredProcedure } from "../../Common/DocumentClientUtilityBase";
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { RouteHandler } from "../../RouteHandlers/RouteHandler";
|
||||
import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import ThemeUtility from "../../Common/ThemeUtility";
|
||||
import Explorer from "../Explorer";
|
||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import ScriptTabBase from "./ScriptTabBase";
|
||||
import editable from "../../Common/EditableUtility";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import Trigger from "../Tree/Trigger";
|
||||
import { createTrigger, updateTrigger } from "../../Common/DocumentClientUtilityBase";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as DataModels from "../../Contracts/DataModels";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import ScriptTabBase from "./ScriptTabBase";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import UserDefinedFunction from "../Tree/UserDefinedFunction";
|
||||
import { createUserDefinedFunction, updateUserDefinedFunction } from "../../Common/DocumentClientUtilityBase";
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as DataModels from "../../Contracts/DataModels";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { PlatformType } from "../../PlatformType";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import { OfferUtils } from "../../Utils/OfferUtils";
|
||||
import { StartUploadMessageParams, UploadDetails, UploadDetailsRecord } from "../../workers/upload/definitions";
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as DataModels from "../../Contracts/DataModels";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import DatabaseSettingsTab from "../Tabs/DatabaseSettingsTab";
|
||||
import Collection from "./Collection";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import * as Logger from "../../Common/Logger";
|
||||
|
||||
@@ -7,7 +7,7 @@ import DocumentId from "./DocumentId";
|
||||
import DocumentsTab from "../Tabs/DocumentsTab";
|
||||
import Q from "q";
|
||||
import QueryTab from "../Tabs/QueryTab";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import Explorer from "../Explorer";
|
||||
import TabsBase from "../Tabs/TabsBase";
|
||||
|
||||
|
||||
112
src/Explorer/Tree/ResourceTreeAdapter.test.ts
Normal file
112
src/Explorer/Tree/ResourceTreeAdapter.test.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import Explorer from "../Explorer";
|
||||
import * as ko from "knockout";
|
||||
import { ResourceTreeAdapter } from "./ResourceTreeAdapter";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import TabsBase from "../Tabs/TabsBase";
|
||||
|
||||
describe("ResourceTreeAdapter", () => {
|
||||
const mockContainer = (): Explorer =>
|
||||
(({
|
||||
selectedNode: ko.observable<ViewModels.TreeNode>({
|
||||
nodeKind: "nodeKind",
|
||||
rid: "rid",
|
||||
id: ko.observable<string>("id")
|
||||
}),
|
||||
tabsManager: {
|
||||
activeTab: ko.observable<TabsBase>({
|
||||
tabKind: ViewModels.CollectionTabKind.Documents
|
||||
} as TabsBase)
|
||||
},
|
||||
isNotebookEnabled: ko.observable<boolean>(true),
|
||||
nonSystemDatabases: ko.observable<ViewModels.Database[]>([])
|
||||
} as unknown) as Explorer);
|
||||
|
||||
// TODO isDataNodeSelected needs a better design and refactor, but for now, we protect some of the code paths
|
||||
describe("isDataNodeSelected", () => {
|
||||
it("it should not select if no selected node", () => {
|
||||
const explorer = mockContainer();
|
||||
explorer.selectedNode(undefined);
|
||||
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
|
||||
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("foo", "bar", undefined);
|
||||
expect(isDataNodeSelected).toBeFalsy();
|
||||
});
|
||||
|
||||
it("it should not select incorrect subnodekinds", () => {
|
||||
const resourceTreeAdapter = new ResourceTreeAdapter(mockContainer());
|
||||
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("foo", "bar", undefined);
|
||||
expect(isDataNodeSelected).toBeFalsy();
|
||||
});
|
||||
|
||||
it("it should not select if no active tab", () => {
|
||||
const explorer = mockContainer();
|
||||
explorer.tabsManager.activeTab(undefined);
|
||||
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
|
||||
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("foo", "bar", undefined);
|
||||
expect(isDataNodeSelected).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should select if correct database node regardless of subnodekinds", () => {
|
||||
const subNodeKind = ViewModels.CollectionTabKind.Documents;
|
||||
const explorer = mockContainer();
|
||||
explorer.selectedNode(({
|
||||
nodeKind: "Database",
|
||||
rid: "dbrid",
|
||||
id: ko.observable<string>("id"),
|
||||
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind)
|
||||
} as unknown) as ViewModels.TreeNode);
|
||||
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
|
||||
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("dbrid", "Database", [
|
||||
ViewModels.CollectionTabKind.Documents
|
||||
]);
|
||||
expect(isDataNodeSelected).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should select correct collection node (documents or graph node)", () => {
|
||||
let subNodeKind = ViewModels.CollectionTabKind.Documents;
|
||||
const explorer = mockContainer();
|
||||
explorer.tabsManager.activeTab({
|
||||
tabKind: subNodeKind
|
||||
} as TabsBase);
|
||||
explorer.selectedNode(({
|
||||
nodeKind: "Collection",
|
||||
rid: "collrid",
|
||||
id: ko.observable<string>("id"),
|
||||
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind)
|
||||
} as unknown) as ViewModels.TreeNode);
|
||||
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
|
||||
let isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("collrid", "Collection", [subNodeKind]);
|
||||
expect(isDataNodeSelected).toBeTruthy();
|
||||
|
||||
subNodeKind = ViewModels.CollectionTabKind.Graph;
|
||||
explorer.tabsManager.activeTab({
|
||||
tabKind: subNodeKind
|
||||
} as TabsBase);
|
||||
explorer.selectedNode(({
|
||||
nodeKind: "Collection",
|
||||
rid: "collrid",
|
||||
id: ko.observable<string>("id"),
|
||||
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(subNodeKind)
|
||||
} as unknown) as ViewModels.TreeNode);
|
||||
isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("collrid", "Collection", [subNodeKind]);
|
||||
expect(isDataNodeSelected).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should not select incorrect collection node (e.g. Settings)", () => {
|
||||
const explorer = mockContainer();
|
||||
explorer.selectedNode(({
|
||||
nodeKind: "Collection",
|
||||
rid: "collrid",
|
||||
id: ko.observable<string>("id"),
|
||||
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(ViewModels.CollectionTabKind.Documents)
|
||||
} as unknown) as ViewModels.TreeNode);
|
||||
explorer.tabsManager.activeTab({
|
||||
tabKind: ViewModels.CollectionTabKind.Documents
|
||||
} as TabsBase);
|
||||
const resourceTreeAdapter = new ResourceTreeAdapter(explorer);
|
||||
const isDataNodeSelected = resourceTreeAdapter.isDataNodeSelected("collrid", "Collection", [
|
||||
ViewModels.CollectionTabKind.Settings
|
||||
]);
|
||||
expect(isDataNodeSelected).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -19,7 +19,7 @@ import { ArrayHashMap } from "../../Common/ArrayHashMap";
|
||||
import { NotebookUtil } from "../Notebook/NotebookUtil";
|
||||
import _ from "underscore";
|
||||
import { IPinnedRepo } from "../../Juno/JunoClient";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { Areas } from "../../Common/Constants";
|
||||
import * as GitHubUtils from "../../Utils/GitHubUtils";
|
||||
@@ -191,7 +191,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
databaseNode.children.push({
|
||||
label: "Scale",
|
||||
isSelected: () =>
|
||||
this.isDataNodeSelected(database.rid, "Database", ViewModels.CollectionTabKind.DatabaseSettings),
|
||||
this.isDataNodeSelected(database.rid, "Database", [ViewModels.CollectionTabKind.DatabaseSettings]),
|
||||
onClick: database.onSettingsClick.bind(database)
|
||||
});
|
||||
}
|
||||
@@ -235,14 +235,18 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
data: collection.rid
|
||||
});
|
||||
},
|
||||
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Documents),
|
||||
isSelected: () =>
|
||||
this.isDataNodeSelected(collection.rid, "Collection", [
|
||||
ViewModels.CollectionTabKind.Documents,
|
||||
ViewModels.CollectionTabKind.Graph
|
||||
]),
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createCollectionContextMenuButton(this.container, collection)
|
||||
});
|
||||
|
||||
children.push({
|
||||
label: database.isDatabaseShared() || this.container.isServerlessEnabled() ? "Settings" : "Scale & Settings",
|
||||
onClick: collection.onSettingsClick.bind(collection),
|
||||
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Settings)
|
||||
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.Settings])
|
||||
});
|
||||
|
||||
if (ResourceTreeAdapter.showScriptNodes(this.container)) {
|
||||
@@ -264,7 +268,8 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
children.push({
|
||||
label: "Conflicts",
|
||||
onClick: collection.onConflictsClick.bind(collection),
|
||||
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Conflicts)
|
||||
isSelected: () =>
|
||||
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.Conflicts])
|
||||
});
|
||||
}
|
||||
|
||||
@@ -302,7 +307,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
label: sp.id(),
|
||||
onClick: sp.open.bind(sp),
|
||||
isSelected: () =>
|
||||
this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.StoredProcedures),
|
||||
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.StoredProcedures]),
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createStoreProcedureContextMenuItems(this.container, sp)
|
||||
})),
|
||||
onClick: () => {
|
||||
@@ -321,7 +326,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
label: udf.id(),
|
||||
onClick: udf.open.bind(udf),
|
||||
isSelected: () =>
|
||||
this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.UserDefinedFunctions),
|
||||
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.UserDefinedFunctions]),
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createUserDefinedFunctionContextMenuItems(this.container, udf)
|
||||
})),
|
||||
onClick: () => {
|
||||
@@ -339,7 +344,8 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
children: collection.triggers().map((trigger: Trigger) => ({
|
||||
label: trigger.id(),
|
||||
onClick: trigger.open.bind(trigger),
|
||||
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Triggers),
|
||||
isSelected: () =>
|
||||
this.isDataNodeSelected(collection.rid, "Collection", [ViewModels.CollectionTabKind.Triggers]),
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createTriggerContextMenuItems(this.container, trigger)
|
||||
})),
|
||||
onClick: () => {
|
||||
@@ -697,13 +703,19 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
window.requestAnimationFrame(() => this.parameters(Date.now()));
|
||||
}
|
||||
|
||||
private isDataNodeSelected(rid: string, nodeKind: string, subnodeKind: ViewModels.CollectionTabKind): boolean {
|
||||
/**
|
||||
* public for testing purposes
|
||||
* @param rid
|
||||
* @param nodeKind
|
||||
* @param subnodeKinds
|
||||
*/
|
||||
public isDataNodeSelected(rid: string, nodeKind: string, subnodeKinds: ViewModels.CollectionTabKind[]): boolean {
|
||||
if (!this.container.selectedNode || !this.container.selectedNode()) {
|
||||
return false;
|
||||
}
|
||||
const selectedNode = this.container.selectedNode();
|
||||
|
||||
if (subnodeKind === undefined) {
|
||||
if (subnodeKinds === undefined || !Array.isArray(subnodeKinds)) {
|
||||
return selectedNode.rid === rid && selectedNode.nodeKind === nodeKind;
|
||||
} else {
|
||||
const activeTab = this.container.tabsManager.activeTab();
|
||||
@@ -716,10 +728,10 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
|
||||
return (
|
||||
activeTab &&
|
||||
activeTab.tabKind === subnodeKind &&
|
||||
subnodeKinds.includes(activeTab.tabKind) &&
|
||||
selectedNode.rid === rid &&
|
||||
selectedSubnodeKind !== undefined &&
|
||||
selectedSubnodeKind === subnodeKind
|
||||
subnodeKinds.includes(selectedSubnodeKind)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as DataModels from "../../Contracts/DataModels";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
|
||||
import StoredProcedureTab from "../Tabs/StoredProcedureTab";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import Explorer from "../Explorer";
|
||||
import { deleteStoredProcedure, executeStoredProcedure } from "../../Common/DocumentClientUtilityBase";
|
||||
import TabsBase from "../Tabs/TabsBase";
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as Constants from "../../Common/Constants";
|
||||
import * as DataModels from "../../Contracts/DataModels";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import TriggerTab from "../Tabs/TriggerTab";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import Explorer from "../Explorer";
|
||||
import { deleteTrigger } from "../../Common/DocumentClientUtilityBase";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as Constants from "../../Common/Constants";
|
||||
import * as DataModels from "../../Contracts/DataModels";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import UserDefinedFunctionTab from "../Tabs/UserDefinedFunctionTab";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import Explorer from "../Explorer";
|
||||
import { deleteUserDefinedFunction } from "../../Common/DocumentClientUtilityBase";
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import { MeControlComponentAdapter } from "./Explorer/Menus/NavBar/MeControlComp
|
||||
import { MessageTypes } from "./Contracts/ExplorerContracts";
|
||||
import * as ReactBindingHandler from "./Bindings/ReactBindingHandler";
|
||||
import { SwitchDirectoryPane, SwitchDirectoryPaneComponent } from "./Explorer/Panes/SwitchDirectoryPane";
|
||||
import TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor";
|
||||
import { isInvalidParentFrameOrigin } from "./Utils/MessageValidation";
|
||||
import "../less/hostedexplorer.less";
|
||||
import "./Explorer/Menus/NavBar/MeControlComponent.less";
|
||||
|
||||
@@ -60,7 +60,7 @@ import "url-polyfill/url-polyfill.min";
|
||||
// import "./ReactDevTools"
|
||||
|
||||
import * as ko from "knockout";
|
||||
import TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor";
|
||||
import * as TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor";
|
||||
import * as ViewModels from "./Contracts/ViewModels";
|
||||
import { Action, ActionModifiers } from "./Shared/Telemetry/TelemetryConstants";
|
||||
|
||||
|
||||
@@ -1,162 +1,64 @@
|
||||
import * as SharedConstants from "../Shared/Constants";
|
||||
import { AddDbUtilities } from "../Shared/AddDatabaseUtility";
|
||||
import { CreateCollectionUtilities, CreateSqlCollectionUtilities, Utilities } from "./AddCollectionUtility";
|
||||
jest.mock("AddDatabaseUtility");
|
||||
import * as ko from "knockout";
|
||||
import { Collection, Database } from "../Contracts/ViewModels";
|
||||
import { getMaxThroughput } from "./AddCollectionUtility";
|
||||
import Explorer from "../Explorer/Explorer";
|
||||
|
||||
const armEndpoint = "https://management.azure.com";
|
||||
describe("getMaxThroughput", () => {
|
||||
it("default unlimited throughput setting", () => {
|
||||
const defaults = {
|
||||
storage: "100",
|
||||
throughput: {
|
||||
fixed: 400,
|
||||
unlimited: 400,
|
||||
unlimitedmax: 1000000,
|
||||
unlimitedmin: 400,
|
||||
shared: 400
|
||||
}
|
||||
};
|
||||
|
||||
describe("Add Collection Utitlity", () => {
|
||||
describe("createSqlCollection", () => {
|
||||
it("should invoke createSqlCollectionWithARM if create database is false", () => {
|
||||
const properties = {
|
||||
uniqueKeyPolicy: { uniqueKeys: [{ paths: [""] }] },
|
||||
cd: false,
|
||||
coll: "abc-collection",
|
||||
db: "a1-db",
|
||||
dba: "main",
|
||||
offerThroughput: 50000,
|
||||
pk: "state",
|
||||
sid: "a1",
|
||||
rg: "b1",
|
||||
st: true,
|
||||
defaultTtl: -1,
|
||||
indexingPolicy: SharedConstants.IndexingPolicies.AllPropertiesIndexed,
|
||||
partitionKeyVersion: 2
|
||||
};
|
||||
const additionalOptions = {};
|
||||
const createSqlCollectionWithARMSpy = jest.spyOn(CreateSqlCollectionUtilities, "createSqlCollectionWithARM");
|
||||
CreateSqlCollectionUtilities.createSqlCollection(
|
||||
armEndpoint,
|
||||
properties.db,
|
||||
properties.defaultTtl,
|
||||
properties.coll,
|
||||
properties.indexingPolicy,
|
||||
properties.offerThroughput,
|
||||
properties.pk,
|
||||
properties.partitionKeyVersion,
|
||||
properties.cd,
|
||||
properties.st,
|
||||
properties.sid,
|
||||
properties.rg,
|
||||
properties.dba,
|
||||
properties.uniqueKeyPolicy,
|
||||
additionalOptions
|
||||
expect(getMaxThroughput(defaults, {} as Explorer)).toEqual(defaults.throughput.unlimited);
|
||||
});
|
||||
|
||||
describe("no unlimited throughput setting", () => {
|
||||
const defaults = {
|
||||
storage: "100",
|
||||
throughput: {
|
||||
fixed: 400,
|
||||
unlimited: {
|
||||
collectionThreshold: 3,
|
||||
lessThanOrEqualToThreshold: 400,
|
||||
greatThanThreshold: 500
|
||||
},
|
||||
unlimitedmax: 1000000,
|
||||
unlimitedmin: 400,
|
||||
shared: 400
|
||||
}
|
||||
};
|
||||
|
||||
const mockCollection1 = { id: ko.observable("collection1") } as Collection;
|
||||
const mockCollection2 = { id: ko.observable("collection2") } as Collection;
|
||||
const mockCollection3 = { id: ko.observable("collection3") } as Collection;
|
||||
const mockCollection4 = { id: ko.observable("collection4") } as Collection;
|
||||
const mockDatabase = {} as Database;
|
||||
const mockContainer = {
|
||||
databases: ko.observableArray([mockDatabase])
|
||||
} as Explorer;
|
||||
|
||||
it("less than or equal to collection threshold", () => {
|
||||
mockDatabase.collections = ko.observableArray([mockCollection1, mockCollection2]);
|
||||
expect(getMaxThroughput(defaults, mockContainer)).toEqual(
|
||||
defaults.throughput.unlimited.lessThanOrEqualToThreshold
|
||||
);
|
||||
expect(createSqlCollectionWithARMSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should invoke createSqlDatabase + createSqlCollectionWithARM if create database is true", () => {
|
||||
const properties = {
|
||||
uniqueKeyPolicy: { uniqueKeys: [{ paths: [""] }] },
|
||||
cd: true,
|
||||
coll: "abc-collection",
|
||||
db: "a1-db",
|
||||
dba: "main",
|
||||
offerThroughput: 50000,
|
||||
pk: "state",
|
||||
sid: "a1",
|
||||
rg: "b1",
|
||||
st: true,
|
||||
analyticalStorageTtl: -1,
|
||||
indexingPolicy: SharedConstants.IndexingPolicies.AllPropertiesIndexed,
|
||||
partitionKeyVersion: 2
|
||||
};
|
||||
const additionalOptions = {};
|
||||
const createSqlCollectionWithARMSpy = jest.spyOn(CreateSqlCollectionUtilities, "createSqlCollectionWithARM");
|
||||
const createSqlDatabaseSpy = jest.spyOn(AddDbUtilities, "createSqlDatabase");
|
||||
CreateSqlCollectionUtilities.createSqlCollection(
|
||||
armEndpoint,
|
||||
properties.db,
|
||||
properties.analyticalStorageTtl,
|
||||
properties.coll,
|
||||
properties.indexingPolicy,
|
||||
properties.offerThroughput,
|
||||
properties.pk,
|
||||
properties.partitionKeyVersion,
|
||||
properties.cd,
|
||||
properties.st,
|
||||
properties.sid,
|
||||
properties.rg,
|
||||
properties.dba,
|
||||
properties.uniqueKeyPolicy,
|
||||
additionalOptions
|
||||
);
|
||||
expect(createSqlCollectionWithARMSpy).toHaveBeenCalled();
|
||||
expect(createSqlDatabaseSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Add Collection Utitlity", () => {
|
||||
describe("createGremlinGraph", () => {
|
||||
it("should invoke createGremlinGraphWithARM if create database is false", () => {
|
||||
const properties = {
|
||||
cd: false,
|
||||
coll: "abc-collection",
|
||||
db: "a1-db",
|
||||
dba: "main",
|
||||
offerThroughput: 50000,
|
||||
pk: "state",
|
||||
sid: "a1",
|
||||
rg: "b1",
|
||||
st: true,
|
||||
indexingPolicy: SharedConstants.IndexingPolicies.AllPropertiesIndexed,
|
||||
partitionKeyVersion: 2
|
||||
};
|
||||
const additionalOptions = {};
|
||||
const createGremlinGraphWithARMSpy = jest.spyOn(CreateCollectionUtilities, "createGremlinGraphWithARM");
|
||||
CreateCollectionUtilities.createGremlinGraph(
|
||||
armEndpoint,
|
||||
properties.db,
|
||||
properties.coll,
|
||||
properties.indexingPolicy,
|
||||
properties.offerThroughput,
|
||||
properties.pk,
|
||||
properties.partitionKeyVersion,
|
||||
properties.cd,
|
||||
properties.st,
|
||||
properties.sid,
|
||||
properties.rg,
|
||||
properties.dba,
|
||||
additionalOptions
|
||||
);
|
||||
expect(createGremlinGraphWithARMSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should invoke createGremlinDatabase + createGremlinGraphWithARM if create database is true", () => {
|
||||
const properties = {
|
||||
cd: true,
|
||||
coll: "abc-collection",
|
||||
db: "a1-db",
|
||||
dba: "main",
|
||||
offerThroughput: 50000,
|
||||
pk: "state",
|
||||
sid: "a1",
|
||||
rg: "b1",
|
||||
st: true,
|
||||
indexingPolicy: SharedConstants.IndexingPolicies.AllPropertiesIndexed,
|
||||
partitionKeyVersion: 2
|
||||
};
|
||||
const additionalOptions = {};
|
||||
const createGremlinGraphWithARMSpy = jest.spyOn(CreateCollectionUtilities, "createGremlinGraphWithARM");
|
||||
const createGremlinDatabaseSpy = jest.spyOn(AddDbUtilities, "createGremlinDatabase");
|
||||
CreateCollectionUtilities.createGremlinGraph(
|
||||
armEndpoint,
|
||||
properties.db,
|
||||
properties.coll,
|
||||
properties.indexingPolicy,
|
||||
properties.offerThroughput,
|
||||
properties.pk,
|
||||
properties.partitionKeyVersion,
|
||||
properties.cd,
|
||||
properties.st,
|
||||
properties.sid,
|
||||
properties.rg,
|
||||
properties.dba,
|
||||
additionalOptions
|
||||
);
|
||||
expect(createGremlinDatabaseSpy).toHaveBeenCalled();
|
||||
expect(createGremlinGraphWithARMSpy).toHaveBeenCalled();
|
||||
it("exceeds collection threshold", () => {
|
||||
mockDatabase.collections = ko.observableArray([
|
||||
mockCollection1,
|
||||
mockCollection2,
|
||||
mockCollection3,
|
||||
mockCollection4
|
||||
]);
|
||||
expect(getMaxThroughput(defaults, mockContainer)).toEqual(defaults.throughput.unlimited.greatThanThreshold);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,303 +1,23 @@
|
||||
import * as _ from "underscore";
|
||||
import * as DataExplorerConstants from "../Common/Constants";
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
import * as SharedConstants from "./Constants";
|
||||
import * as ViewModels from "../Contracts/ViewModels";
|
||||
import { AddDbUtilities } from "../Shared/AddDatabaseUtility";
|
||||
import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { HttpStatusCodes } from "../Common/Constants";
|
||||
import { sendMessage } from "../Common/MessageHandler";
|
||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
|
||||
import { any } from "underscore";
|
||||
import { CollectionCreationDefaults } from "../Contracts/ViewModels";
|
||||
import Explorer from "../Explorer/Explorer";
|
||||
import { userContext } from "../UserContext";
|
||||
|
||||
export class CreateSqlCollectionUtilities {
|
||||
public static createSqlCollection(
|
||||
armEndpoint: string,
|
||||
databaseId: string,
|
||||
analyticalStorageTtl: number,
|
||||
collectionId: string,
|
||||
indexingPolicy: DataModels.IndexingPolicy,
|
||||
offerThroughput: number,
|
||||
partitionKey: string,
|
||||
partitionKeyVersion: number,
|
||||
createDatabase: boolean,
|
||||
useDatabaseSharedOffer: boolean,
|
||||
sid: string,
|
||||
rg: string,
|
||||
dba: string,
|
||||
uniqueKeyPolicy: DataModels.UniqueKeyPolicy,
|
||||
additionalOptions: DataModels.RpOptions
|
||||
): Promise<DataModels.CreateCollectionWithRpResponse> {
|
||||
const params: DataModels.SqlCollectionParameters = {
|
||||
uniqueKeyPolicy,
|
||||
db: databaseId,
|
||||
coll: collectionId,
|
||||
pk: partitionKey,
|
||||
offerThroughput,
|
||||
cd: createDatabase,
|
||||
st: useDatabaseSharedOffer,
|
||||
sid,
|
||||
rg,
|
||||
dba,
|
||||
analyticalStorageTtl,
|
||||
indexingPolicy,
|
||||
partitionKeyVersion
|
||||
};
|
||||
|
||||
if (params.cd) {
|
||||
return AddDbUtilities.createSqlDatabase(armEndpoint, params, additionalOptions).then(() => {
|
||||
return CreateSqlCollectionUtilities.createSqlCollectionWithARM(armEndpoint, params, additionalOptions);
|
||||
});
|
||||
}
|
||||
return CreateSqlCollectionUtilities.createSqlCollectionWithARM(armEndpoint, params, additionalOptions);
|
||||
export const getMaxThroughput = (defaults: CollectionCreationDefaults, container: Explorer): number => {
|
||||
const throughput = defaults.throughput.unlimited;
|
||||
if (typeof throughput === "number") {
|
||||
return throughput;
|
||||
} else {
|
||||
return _exceedsThreshold(throughput.collectionThreshold, container)
|
||||
? throughput.greatThanThreshold
|
||||
: throughput.lessThanOrEqualToThreshold;
|
||||
}
|
||||
};
|
||||
|
||||
public static async createSqlCollectionWithARM(
|
||||
armEndpoint: string,
|
||||
params: DataModels.SqlCollectionParameters,
|
||||
rpOptions: DataModels.RpOptions
|
||||
): Promise<DataModels.CreateCollectionWithRpResponse> {
|
||||
const rpPayloadToCreateCollection: DataModels.SqlCollectionCreationRequest = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.coll,
|
||||
partitionKey: {
|
||||
paths: [params.pk],
|
||||
kind: "Hash",
|
||||
version: params.partitionKeyVersion
|
||||
}
|
||||
},
|
||||
options: {}
|
||||
}
|
||||
};
|
||||
|
||||
if (params.analyticalStorageTtl) {
|
||||
rpPayloadToCreateCollection.properties.resource.analyticalStorageTtl = params.analyticalStorageTtl;
|
||||
}
|
||||
|
||||
if (params.indexingPolicy) {
|
||||
rpPayloadToCreateCollection.properties.resource.indexingPolicy = params.indexingPolicy;
|
||||
}
|
||||
|
||||
if (!params.st) {
|
||||
if (rpOptions) {
|
||||
rpPayloadToCreateCollection.properties.options = rpOptions;
|
||||
} else {
|
||||
rpPayloadToCreateCollection.properties.options["throughput"] =
|
||||
params.offerThroughput && params.offerThroughput.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (params.uniqueKeyPolicy) {
|
||||
rpPayloadToCreateCollection.properties.resource.uniqueKeyPolicy = params.uniqueKeyPolicy;
|
||||
}
|
||||
|
||||
try {
|
||||
let response = await new ResourceProviderClient<DataModels.CreateCollectionWithRpResponse>(armEndpoint).putAsync(
|
||||
CreateSqlCollectionUtilities.getSqlCollectionUri(params),
|
||||
DataExplorerConstants.ArmApiVersions.publicVersion,
|
||||
rpPayloadToCreateCollection
|
||||
);
|
||||
return response;
|
||||
} catch (response) {
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Error creating collection: ${JSON.stringify(response)}`
|
||||
);
|
||||
if (response.status === HttpStatusCodes.Forbidden) {
|
||||
sendMessage({ type: MessageTypes.ForbiddenError });
|
||||
}
|
||||
throw new Error(`Error creating collection`);
|
||||
}
|
||||
}
|
||||
|
||||
public static getSqlCollectionUri(params: DataModels.SqlCollectionParameters): string {
|
||||
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${params.dba}/sqlDatabases/${params.db}/containers/${params.coll}`;
|
||||
}
|
||||
}
|
||||
|
||||
export class CreateCollectionUtilities {
|
||||
public static createGremlinGraph(
|
||||
armEndpoint: string,
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
indexingPolicy: DataModels.IndexingPolicy,
|
||||
offerThroughput: number,
|
||||
partitionKey: string,
|
||||
partitionKeyVersion: number,
|
||||
createDatabase: boolean,
|
||||
useDatabaseSharedOffer: boolean,
|
||||
sid: string,
|
||||
rg: string,
|
||||
dba: string,
|
||||
additionalOptions: DataModels.RpOptions
|
||||
): Promise<DataModels.CreateCollectionWithRpResponse> {
|
||||
const params: DataModels.GraphParameters = {
|
||||
db: databaseId,
|
||||
coll: collectionId,
|
||||
pk: partitionKey,
|
||||
offerThroughput,
|
||||
cd: createDatabase,
|
||||
st: useDatabaseSharedOffer,
|
||||
sid,
|
||||
rg,
|
||||
dba,
|
||||
indexingPolicy,
|
||||
partitionKeyVersion
|
||||
};
|
||||
|
||||
if (params.cd) {
|
||||
return AddDbUtilities.createGremlinDatabase(armEndpoint, params, additionalOptions).then(() => {
|
||||
return CreateCollectionUtilities.createGremlinGraphWithARM(armEndpoint, params, additionalOptions);
|
||||
});
|
||||
}
|
||||
return CreateCollectionUtilities.createGremlinGraphWithARM(armEndpoint, params, additionalOptions);
|
||||
}
|
||||
|
||||
public static async createGremlinGraphWithARM(
|
||||
armEndpoint: string,
|
||||
params: DataModels.GraphParameters,
|
||||
rpOptions: DataModels.RpOptions
|
||||
): Promise<DataModels.CreateCollectionWithRpResponse> {
|
||||
const rpPayloadToCreateCollection: DataModels.GraphCreationRequest = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.coll,
|
||||
partitionKey: {
|
||||
paths: [params.pk],
|
||||
kind: "Hash",
|
||||
version: params.partitionKeyVersion
|
||||
}
|
||||
},
|
||||
options: {}
|
||||
}
|
||||
};
|
||||
|
||||
if (params.indexingPolicy) {
|
||||
rpPayloadToCreateCollection.properties.resource.indexingPolicy = params.indexingPolicy;
|
||||
}
|
||||
|
||||
if (!params.st) {
|
||||
if (rpOptions) {
|
||||
rpPayloadToCreateCollection.properties.options = rpOptions;
|
||||
} else {
|
||||
rpPayloadToCreateCollection.properties.options["throughput"] =
|
||||
params.offerThroughput && params.offerThroughput.toString();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
let response = await new ResourceProviderClient<DataModels.CreateCollectionWithRpResponse>(armEndpoint).putAsync(
|
||||
CreateCollectionUtilities.getGremlinGraphUri(params),
|
||||
DataExplorerConstants.ArmApiVersions.publicVersion,
|
||||
rpPayloadToCreateCollection
|
||||
);
|
||||
return response;
|
||||
} catch (response) {
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Error creating graph: ${JSON.stringify(response)}`
|
||||
);
|
||||
if (response.status === HttpStatusCodes.Forbidden) {
|
||||
sendMessage({ type: MessageTypes.ForbiddenError });
|
||||
}
|
||||
throw new Error(`Error creating graph`);
|
||||
}
|
||||
}
|
||||
|
||||
public static getGremlinGraphUri(params: DataModels.GraphParameters): string {
|
||||
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${params.dba}/gremlinDatabases/${params.db}/graphs/${params.coll}`;
|
||||
}
|
||||
}
|
||||
export class Utilities {
|
||||
public static async createAzureTableWithARM(
|
||||
armEndpoint: string,
|
||||
params: DataModels.CreateDatabaseAndCollectionRequest,
|
||||
rpOptions: DataModels.RpOptions
|
||||
): Promise<any> {
|
||||
const rpPayloadToCreateDatabase: DataModels.CreationRequest = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.collectionId
|
||||
},
|
||||
options: {}
|
||||
}
|
||||
};
|
||||
|
||||
if (!params.databaseLevelThroughput) {
|
||||
if (rpOptions) {
|
||||
rpPayloadToCreateDatabase.properties.options = rpOptions;
|
||||
} else {
|
||||
rpPayloadToCreateDatabase.properties.options["throughput"] =
|
||||
params.offerThroughput && params.offerThroughput.toString();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await new ResourceProviderClient(armEndpoint).putAsync(
|
||||
Utilities._getAzureTableUri(params),
|
||||
DataExplorerConstants.ArmApiVersions.publicVersion,
|
||||
rpPayloadToCreateDatabase
|
||||
);
|
||||
} catch (reason) {
|
||||
NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.Error,
|
||||
`Error creating table: ${JSON.stringify(reason)}, Payload: ${params}`
|
||||
);
|
||||
if (reason.status === HttpStatusCodes.Forbidden) {
|
||||
sendMessage({ type: MessageTypes.ForbiddenError });
|
||||
return;
|
||||
}
|
||||
throw new Error(`Error creating table`);
|
||||
}
|
||||
}
|
||||
|
||||
public static getMaxRUForStorageOption(
|
||||
defaults: ViewModels.CollectionCreationDefaults,
|
||||
storageOption: string
|
||||
): number {
|
||||
if (storageOption === SharedConstants.CollectionCreation.storage10Gb) {
|
||||
return SharedConstants.CollectionCreation.DefaultCollectionRUs10K;
|
||||
}
|
||||
|
||||
return defaults.throughput.unlimitedmax;
|
||||
}
|
||||
|
||||
public static getMinRUForStorageOption(
|
||||
defaults: ViewModels.CollectionCreationDefaults,
|
||||
storageOption: string
|
||||
): number {
|
||||
if (storageOption === SharedConstants.CollectionCreation.storage10Gb) {
|
||||
return SharedConstants.CollectionCreation.DefaultCollectionRUs400;
|
||||
}
|
||||
|
||||
return defaults.throughput.unlimitedmin;
|
||||
}
|
||||
|
||||
public static getMaxThroughput(defaults: ViewModels.CollectionCreationDefaults, container: Explorer): number {
|
||||
const throughput = defaults.throughput.unlimited;
|
||||
if (typeof throughput === "number") {
|
||||
return throughput;
|
||||
} else {
|
||||
return this._exceedsThreshold(throughput.collectionThreshold, container)
|
||||
? throughput.greatThanThreshold
|
||||
: throughput.lessThanOrEqualToThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
private static _exceedsThreshold(unlimitedThreshold: number, container: Explorer): boolean {
|
||||
const databases = (container && container.databases && container.databases()) || [];
|
||||
return _.any(
|
||||
databases,
|
||||
database =>
|
||||
database && database.collections && database.collections() && database.collections().length > unlimitedThreshold
|
||||
);
|
||||
}
|
||||
|
||||
private static _getAzureTableUri(params: DataModels.CreateDatabaseAndCollectionRequest): string {
|
||||
return `subscriptions/${userContext.subscriptionId}/resourceGroups/${userContext.resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/tables/${params.collectionId}`;
|
||||
}
|
||||
}
|
||||
const _exceedsThreshold = (unlimitedThreshold: number, container: Explorer): boolean => {
|
||||
const databases = (container && container.databases && container.databases()) || [];
|
||||
return any(
|
||||
databases,
|
||||
database =>
|
||||
database && database.collections && database.collections() && database.collections().length > unlimitedThreshold
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
import { AddDbUtilities } from "./AddDatabaseUtility";
|
||||
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
|
||||
jest.mock("../ResourceProvider/ResourceProviderClient.ts");
|
||||
|
||||
describe("Add Database Utitlity", () => {
|
||||
const armEndpoint = "https://management.azure.com";
|
||||
const properties = {
|
||||
pk: "state",
|
||||
coll: "abc-collection",
|
||||
cd: true,
|
||||
db: "a1-db",
|
||||
offerThroughput: 50000,
|
||||
st: true,
|
||||
sid: "a1",
|
||||
rg: "b1",
|
||||
dba: "main"
|
||||
};
|
||||
|
||||
describe("getRpClient", () => {
|
||||
it("should return an instance of ResourceProviderClient", () => {
|
||||
expect(AddDbUtilities.getRpClient()).not.toBeFalsy();
|
||||
expect(AddDbUtilities.getRpClient()).toBeInstanceOf(ResourceProviderClient);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getGremlinDatabaseUri", () => {
|
||||
it("should return a uri in the correct format", () => {
|
||||
expect(AddDbUtilities.getGremlinDatabaseUri(properties)).toEqual(
|
||||
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/gremlinDatabases/a1-db"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createGremlinDatabase", () => {
|
||||
it("should utilize resource provider client", () => {
|
||||
const resourceProviderClientSpy = spyOn<any>(AddDbUtilities, "getRpClient");
|
||||
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, undefined);
|
||||
expect(resourceProviderClientSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should invoke getGremlinDatabaseUri", () => {
|
||||
const getGremlinDatabaseUriSpy = spyOn<any>(AddDbUtilities, "getGremlinDatabaseUri");
|
||||
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, undefined);
|
||||
expect(getGremlinDatabaseUriSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should invoke a put call via resource provider client to create a database and set throughput if shared throughtput is true", () => {
|
||||
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
|
||||
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, undefined);
|
||||
expect(
|
||||
resourceProviderClientPutAsyncSpy
|
||||
).toHaveBeenCalledWith(
|
||||
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/gremlinDatabases/a1-db",
|
||||
"2020-04-01",
|
||||
{ properties: { options: { throughput: "50000" }, resource: { id: "a1-db" } } }
|
||||
);
|
||||
});
|
||||
|
||||
it("should invoke a put call via resource provider client to create a database and set autopilot if shared throughtput is true and autopilot settings are passed", () => {
|
||||
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
|
||||
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, { "x-ms-cosmos-offer-autopilot-tier": "1" });
|
||||
expect(
|
||||
resourceProviderClientPutAsyncSpy
|
||||
).toHaveBeenCalledWith(
|
||||
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/gremlinDatabases/a1-db",
|
||||
"2020-04-01",
|
||||
{ properties: { options: { "x-ms-cosmos-offer-autopilot-tier": "1" }, resource: { id: "a1-db" } } }
|
||||
);
|
||||
});
|
||||
|
||||
it("should invoke a put call via resource provider client to create a database and not set throughput if shared throughtput is false", () => {
|
||||
const properties = {
|
||||
pk: "state",
|
||||
coll: "abc-collection",
|
||||
cd: true,
|
||||
db: "a2-db",
|
||||
st: false,
|
||||
sid: "a2",
|
||||
rg: "c1",
|
||||
dba: "main"
|
||||
};
|
||||
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
|
||||
AddDbUtilities.createGremlinDatabase(armEndpoint, properties, undefined);
|
||||
expect(
|
||||
resourceProviderClientPutAsyncSpy
|
||||
).toHaveBeenCalledWith(
|
||||
"subscriptions/a2/resourceGroups/c1/providers/Microsoft.DocumentDB/databaseAccounts/main/gremlinDatabases/a2-db",
|
||||
"2020-04-01",
|
||||
{ properties: { options: {}, resource: { id: "a2-db" } } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createSqlDatabase", () => {
|
||||
it("should utilize resource provider client", () => {
|
||||
const resourceProviderClientSpy = spyOn<any>(AddDbUtilities, "getRpClient");
|
||||
AddDbUtilities.createSqlDatabase(armEndpoint, properties, undefined);
|
||||
expect(resourceProviderClientSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should invoke getSqlDatabaseUri", () => {
|
||||
const getSqlDatabaseUriSpy = spyOn<any>(AddDbUtilities, "getSqlDatabaseUri");
|
||||
AddDbUtilities.createSqlDatabase(armEndpoint, properties, undefined);
|
||||
expect(getSqlDatabaseUriSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should invoke a put call via resource provider client to create a database and set throughput if shared throughtput is true", () => {
|
||||
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
|
||||
AddDbUtilities.createSqlDatabase(armEndpoint, properties, undefined);
|
||||
expect(
|
||||
resourceProviderClientPutAsyncSpy
|
||||
).toHaveBeenCalledWith(
|
||||
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/sqlDatabases/a1-db",
|
||||
"2020-04-01",
|
||||
{ properties: { options: { throughput: "50000" }, resource: { id: "a1-db" } } }
|
||||
);
|
||||
});
|
||||
|
||||
it("should invoke a put call via resource provider client to create a database and set autopilot if shared throughtput is true and autopilot settings are passed", () => {
|
||||
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
|
||||
AddDbUtilities.createSqlDatabase(armEndpoint, properties, { "x-ms-cosmos-offer-autopilot-tier": "1" });
|
||||
expect(
|
||||
resourceProviderClientPutAsyncSpy
|
||||
).toHaveBeenCalledWith(
|
||||
"subscriptions/a1/resourceGroups/b1/providers/Microsoft.DocumentDB/databaseAccounts/main/sqlDatabases/a1-db",
|
||||
"2020-04-01",
|
||||
{ properties: { options: { "x-ms-cosmos-offer-autopilot-tier": "1" }, resource: { id: "a1-db" } } }
|
||||
);
|
||||
});
|
||||
|
||||
it("should invoke a put call via resource provider client to create a database and not set throughput if shared throughtput is false", () => {
|
||||
const properties = {
|
||||
pk: "state",
|
||||
coll: "abc-collection",
|
||||
cd: true,
|
||||
db: "a2-db",
|
||||
st: false,
|
||||
sid: "a2",
|
||||
rg: "c1",
|
||||
dba: "main"
|
||||
};
|
||||
const resourceProviderClientPutAsyncSpy = jest.spyOn(ResourceProviderClient.prototype, "putAsync");
|
||||
AddDbUtilities.createSqlDatabase(armEndpoint, properties, undefined);
|
||||
expect(
|
||||
resourceProviderClientPutAsyncSpy
|
||||
).toHaveBeenCalledWith(
|
||||
"subscriptions/a2/resourceGroups/c1/providers/Microsoft.DocumentDB/databaseAccounts/main/sqlDatabases/a2-db",
|
||||
"2020-04-01",
|
||||
{ properties: { options: {}, resource: { id: "a2-db" } } }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,187 +0,0 @@
|
||||
import * as DataExplorerConstants from "../Common/Constants";
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
import { configContext } from "../ConfigContext";
|
||||
import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { HttpStatusCodes } from "../Common/Constants";
|
||||
import { sendMessage } from "../Common/MessageHandler";
|
||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
|
||||
import { userContext } from "../UserContext";
|
||||
import { createUpdateCassandraKeyspace } from "../Utils/arm/generatedClients/2020-04-01/cassandraResources";
|
||||
|
||||
export class AddDbUtilities {
|
||||
// todo - remove any
|
||||
public static async createMongoDatabaseWithARM(
|
||||
armEndpoint: string,
|
||||
params: DataModels.RpParameters,
|
||||
rpOptions: DataModels.RpOptions
|
||||
): Promise<any> {
|
||||
const rpPayloadToCreateDatabase: DataModels.MongoCreationRequest = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.db
|
||||
},
|
||||
options: {}
|
||||
}
|
||||
};
|
||||
|
||||
if (params.st) {
|
||||
if (rpOptions) {
|
||||
rpPayloadToCreateDatabase.properties.options = rpOptions;
|
||||
} else {
|
||||
rpPayloadToCreateDatabase.properties.options["throughput"] =
|
||||
params.offerThroughput && params.offerThroughput.toString();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await AddDbUtilities.getRpClient<DataModels.CreateDatabaseWithRpResponse>(armEndpoint).putAsync(
|
||||
AddDbUtilities._getMongoDatabaseUri(params),
|
||||
DataExplorerConstants.ArmApiVersions.publicVersion,
|
||||
rpPayloadToCreateDatabase
|
||||
);
|
||||
} catch (reason) {
|
||||
AddDbUtilities._handleCreationError(reason, params);
|
||||
}
|
||||
}
|
||||
|
||||
// todo - remove any
|
||||
public static async createCassandraKeyspace(
|
||||
params: DataModels.RpParameters,
|
||||
rpOptions: DataModels.RpOptions
|
||||
): Promise<any> {
|
||||
const rpPayloadToCreateKeyspace: DataModels.CreationRequest = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.db
|
||||
},
|
||||
options: {}
|
||||
}
|
||||
};
|
||||
|
||||
if (params.st) {
|
||||
if (rpOptions) {
|
||||
rpPayloadToCreateKeyspace.properties.options = rpOptions;
|
||||
} else {
|
||||
rpPayloadToCreateKeyspace.properties.options["throughput"] =
|
||||
params.offerThroughput && params.offerThroughput.toString();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await createUpdateCassandraKeyspace(
|
||||
userContext.subscriptionId,
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount?.name,
|
||||
params.db,
|
||||
rpPayloadToCreateKeyspace
|
||||
);
|
||||
} catch (reason) {
|
||||
AddDbUtilities._handleCreationError(reason, params, "keyspace");
|
||||
}
|
||||
}
|
||||
|
||||
public static async createSqlDatabase(
|
||||
armEndpoint: string,
|
||||
params: DataModels.RpParameters,
|
||||
rpOptions: DataModels.RpOptions
|
||||
): Promise<any> {
|
||||
const rpPayloadToCreateSqlDatabase: DataModels.CreationRequest = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.db
|
||||
},
|
||||
options: {}
|
||||
}
|
||||
};
|
||||
|
||||
if (params.st) {
|
||||
if (rpOptions) {
|
||||
rpPayloadToCreateSqlDatabase.properties.options = rpOptions;
|
||||
} else {
|
||||
rpPayloadToCreateSqlDatabase.properties.options["throughput"] =
|
||||
params.offerThroughput && params.offerThroughput.toString();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await AddDbUtilities.getRpClient<DataModels.CreateDatabaseWithRpResponse>(armEndpoint).putAsync(
|
||||
AddDbUtilities.getSqlDatabaseUri(params),
|
||||
DataExplorerConstants.ArmApiVersions.publicVersion,
|
||||
rpPayloadToCreateSqlDatabase
|
||||
);
|
||||
} catch (reason) {
|
||||
AddDbUtilities._handleCreationError(reason, params, "database");
|
||||
}
|
||||
}
|
||||
|
||||
public static getRpClient<T>(armEndpoint?: string): ResourceProviderClient<T> {
|
||||
return new ResourceProviderClient<T>(armEndpoint || configContext.ARM_ENDPOINT);
|
||||
}
|
||||
|
||||
public static async createGremlinDatabase(
|
||||
armEndpoint: string,
|
||||
params: DataModels.RpParameters,
|
||||
autoPilotSettings: DataModels.RpOptions
|
||||
): Promise<DataModels.CreateDatabaseWithRpResponse> {
|
||||
const rpPayloadToCreateDatabase: DataModels.CreationRequest = {
|
||||
properties: {
|
||||
resource: {
|
||||
id: params.db
|
||||
},
|
||||
options: {}
|
||||
}
|
||||
};
|
||||
|
||||
const uri = AddDbUtilities.getGremlinDatabaseUri(params);
|
||||
|
||||
if (params.st) {
|
||||
if (autoPilotSettings) {
|
||||
rpPayloadToCreateDatabase.properties.options = autoPilotSettings;
|
||||
} else {
|
||||
rpPayloadToCreateDatabase.properties.options["throughput"] =
|
||||
params.offerThroughput && params.offerThroughput.toString();
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise<DataModels.CreateDatabaseWithRpResponse>((resolve, reject) => {
|
||||
AddDbUtilities.getRpClient<DataModels.CreateDatabaseWithRpResponse>(armEndpoint)
|
||||
.putAsync(uri, DataExplorerConstants.ArmApiVersions.publicVersion, rpPayloadToCreateDatabase)
|
||||
.then(
|
||||
() => {
|
||||
resolve();
|
||||
},
|
||||
reason => {
|
||||
AddDbUtilities._handleCreationError(reason, params);
|
||||
reject();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private static _handleCreationError(reason: any, params: DataModels.RpParameters, dbType: string = "database") {
|
||||
NotificationConsoleUtils.logConsoleError(`Error creating ${dbType}: ${JSON.stringify(reason)}, Payload: ${params}`);
|
||||
if (reason.status === HttpStatusCodes.Forbidden) {
|
||||
sendMessage({ type: MessageTypes.ForbiddenError });
|
||||
return;
|
||||
}
|
||||
throw new Error(`Error creating ${dbType}`);
|
||||
}
|
||||
|
||||
private static _getMongoDatabaseUri(params: DataModels.RpParameters): string {
|
||||
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/mongodbDatabases/${params.db}`;
|
||||
}
|
||||
|
||||
private static _getCassandraKeyspaceUri(params: DataModels.RpParameters): string {
|
||||
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/cassandraKeyspaces/${params.db}`;
|
||||
}
|
||||
|
||||
public static getGremlinDatabaseUri(params: DataModels.RpParameters): string {
|
||||
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${params.dba}/gremlinDatabases/${params.db}`;
|
||||
}
|
||||
|
||||
public static getSqlDatabaseUri(params: DataModels.RpParameters): string {
|
||||
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${params.dba}/sqlDatabases/${params.db}`;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,3 @@
|
||||
/**
|
||||
* Defines constants related to logging telemetry. Everything except Action should be kept in sync with the one in the Portal code as much as possible.
|
||||
*
|
||||
* TODO: Move this to ExplorerContracts (265329)
|
||||
*/
|
||||
export class General {
|
||||
public static ExtensionName: string = "Microsoft_Azure_DocumentDB";
|
||||
public static BladeNamePrefix: string = "Extension/Microsoft_Azure_DocumentDB/Blade/";
|
||||
}
|
||||
|
||||
// Data Explorer specific actions. No need to keep this in sync with the one in Portal.
|
||||
export enum Action {
|
||||
CollapseTreeNode,
|
||||
@@ -83,24 +73,19 @@ export enum Action {
|
||||
NotebooksGitHubDisconnect
|
||||
}
|
||||
|
||||
export class ActionModifiers {
|
||||
public static Start: string = "start";
|
||||
public static Success: string = "success";
|
||||
public static Failed: string = "failed";
|
||||
public static Mark: string = "mark";
|
||||
public static Open: string = "open";
|
||||
public static IFrameReady: string = "iframeready";
|
||||
public static Close: string = "close";
|
||||
public static Submit: string = "submit";
|
||||
public static IndexAll: string = "index all properties";
|
||||
public static NoIndex: string = "no indexing";
|
||||
public static Cancel: string = "cancel";
|
||||
}
|
||||
|
||||
export class CosmosDBEndpointNames {
|
||||
public static Gateway: string = "CosmosDBGateway";
|
||||
public static ResourceProvider: string = "DocumentDBResourceProvider";
|
||||
}
|
||||
export const ActionModifiers = {
|
||||
Start: "start",
|
||||
Success: "success",
|
||||
Failed: "failed",
|
||||
Mark: "mark",
|
||||
Open: "open",
|
||||
IFrameReady: "iframeready",
|
||||
Close: "close",
|
||||
Submit: "submit",
|
||||
IndexAll: "index all properties",
|
||||
NoIndex: "no indexing",
|
||||
Cancel: "cancel"
|
||||
} as const;
|
||||
|
||||
export enum SourceBlade {
|
||||
AddCollection,
|
||||
@@ -126,17 +111,3 @@ export enum SourceBlade {
|
||||
ScriptExplorer,
|
||||
Keys
|
||||
}
|
||||
|
||||
export class BladeLoadRequirements {
|
||||
public static collections: string = "Collections";
|
||||
public static collectionsWithOffers: string = "CollectionsWithOffers";
|
||||
public static databaseAccount: string = "DatabaseAccount";
|
||||
public static keys: string = "Keys";
|
||||
public static metrics: string = "Metrics";
|
||||
public static notifications: string = "Notifications";
|
||||
public static singleCollection: string = "SingleCollection";
|
||||
|
||||
public static keysBlade: string[] = [BladeLoadRequirements.databaseAccount, BladeLoadRequirements.keys];
|
||||
public static metricsBlade: string[] = [BladeLoadRequirements.databaseAccount];
|
||||
public static overview: string[] = [BladeLoadRequirements.databaseAccount, BladeLoadRequirements.notifications];
|
||||
}
|
||||
|
||||
@@ -8,123 +8,124 @@ import { userContext } from "../../UserContext";
|
||||
/**
|
||||
* Class that persists telemetry data to the portal tables.
|
||||
*/
|
||||
// TODO: Move to a separate Diagnostics folder
|
||||
// TODO: Log telemetry for StorageExplorer case/other clients as well
|
||||
export default class TelemetryProcessor {
|
||||
public static trace(action: Action, actionModifier: string = ActionModifiers.Mark, data?: any): void {
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: actionModifier,
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.trackEvent({ name: Action[action] }, TelemetryProcessor.getData(data));
|
||||
}
|
||||
|
||||
public static traceStart(action: Action, data?: any): number {
|
||||
const timestamp: number = Date.now();
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Start,
|
||||
timestamp: timestamp,
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.startTrackEvent(Action[action]);
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public static traceSuccess(action: Action, data?: any, timestamp?: number): void {
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Success,
|
||||
timestamp: timestamp || Date.now(),
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.stopTrackEvent(Action[action], TelemetryProcessor.getData(data));
|
||||
}
|
||||
|
||||
public static traceFailure(action: Action, data?: any, timestamp?: number): void {
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Failed,
|
||||
timestamp: timestamp || Date.now(),
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.stopTrackEvent(Action[action], TelemetryProcessor.getData(data));
|
||||
}
|
||||
|
||||
public static traceCancel(action: Action, data?: any, timestamp?: number): void {
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Cancel,
|
||||
timestamp: timestamp || Date.now(),
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.stopTrackEvent(Action[action], TelemetryProcessor.getData(data));
|
||||
}
|
||||
|
||||
public static traceOpen(action: Action, data?: any, timestamp?: number): number {
|
||||
const validTimestamp = timestamp || Date.now();
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Open,
|
||||
timestamp: validTimestamp,
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.startTrackEvent(Action[action]);
|
||||
return validTimestamp;
|
||||
}
|
||||
|
||||
public static traceMark(action: Action, data?: any, timestamp?: number): number {
|
||||
const validTimestamp = timestamp || Date.now();
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Mark,
|
||||
timestamp: validTimestamp,
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.startTrackEvent(Action[action]);
|
||||
return validTimestamp;
|
||||
}
|
||||
|
||||
private static getData(data: any = {}): any {
|
||||
if (typeof data === "string") {
|
||||
data = { message: data };
|
||||
export function trace(action: Action, actionModifier: string = ActionModifiers.Mark, data?: unknown): void {
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: actionModifier,
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.trackEvent({ name: Action[action] }, getData(data));
|
||||
}
|
||||
|
||||
export function traceStart(action: Action, data?: unknown): number {
|
||||
const timestamp: number = Date.now();
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Start,
|
||||
timestamp: timestamp,
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.startTrackEvent(Action[action]);
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
export function traceSuccess(action: Action, data?: unknown, timestamp?: number): void {
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Success,
|
||||
timestamp: timestamp || Date.now(),
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.stopTrackEvent(Action[action], getData(data));
|
||||
}
|
||||
|
||||
export function traceFailure(action: Action, data?: unknown, timestamp?: number): void {
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Failed,
|
||||
timestamp: timestamp || Date.now(),
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.stopTrackEvent(Action[action], getData(data));
|
||||
}
|
||||
|
||||
export function traceCancel(action: Action, data?: unknown, timestamp?: number): void {
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Cancel,
|
||||
timestamp: timestamp || Date.now(),
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.stopTrackEvent(Action[action], getData(data));
|
||||
}
|
||||
|
||||
export function traceOpen(action: Action, data?: unknown, timestamp?: number): number {
|
||||
const validTimestamp = timestamp || Date.now();
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Open,
|
||||
timestamp: validTimestamp,
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.startTrackEvent(Action[action]);
|
||||
return validTimestamp;
|
||||
}
|
||||
|
||||
export function traceMark(action: Action, data?: unknown, timestamp?: number): number {
|
||||
const validTimestamp = timestamp || Date.now();
|
||||
sendMessage({
|
||||
type: MessageTypes.TelemetryInfo,
|
||||
data: {
|
||||
action: Action[action],
|
||||
actionModifier: ActionModifiers.Mark,
|
||||
timestamp: validTimestamp,
|
||||
data: JSON.stringify(data)
|
||||
}
|
||||
});
|
||||
|
||||
appInsights.startTrackEvent(Action[action]);
|
||||
return validTimestamp;
|
||||
}
|
||||
|
||||
function getData(data: unknown = {}): { [key: string]: string } | undefined {
|
||||
if (typeof data === "string") {
|
||||
data = { message: data };
|
||||
}
|
||||
if (typeof data === "object") {
|
||||
return {
|
||||
// TODO: Need to `any` here since the window imports Explorer which can't be in strict mode yet
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
authType: (window as any).authType,
|
||||
subscriptionId: userContext.subscriptionId,
|
||||
subscriptionId: userContext.subscriptionId as string,
|
||||
platform: configContext.platform,
|
||||
env: process.env.NODE_ENV,
|
||||
env: process.env.NODE_ENV as string,
|
||||
...data
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ApplicationInsights } from "@microsoft/applicationinsights-web";
|
||||
|
||||
const appInsights = new ApplicationInsights({
|
||||
config: {
|
||||
instrumentationKey: "fa645d97-6237-4656-9559-0ee0cb55ee49"
|
||||
instrumentationKey: "fa645d97-6237-4656-9559-0ee0cb55ee49",
|
||||
disableFetchTracking: false
|
||||
}
|
||||
});
|
||||
appInsights.loadAppInsights();
|
||||
|
||||
@@ -3,7 +3,10 @@ import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/Notificat
|
||||
|
||||
const _global = typeof self === "undefined" ? window : self;
|
||||
|
||||
// DEPRECATED: Use logConsoleInfo, logConsoleError, logConsoleProgress instead
|
||||
/**
|
||||
* @deprecated
|
||||
* Use logConsoleInfo, logConsoleError, logConsoleProgress instead
|
||||
* */
|
||||
export function logConsoleMessage(type: ConsoleDataType, message: string, id?: string): string {
|
||||
const dataExplorer = _global.dataExplorer;
|
||||
if (dataExplorer) {
|
||||
|
||||
@@ -193,7 +193,7 @@ export function getAutoPilotV3SpendHtml(maxAutoPilotThroughputSet: number, isDat
|
||||
maxAutoPilotThroughputSet
|
||||
)} GB of data stored, the max RU/s will be automatically upgraded based on the new storage value. <a href='${
|
||||
Constants.AutopilotDocumentation.Url
|
||||
}' target='_blank'>Learn more</a>.`;
|
||||
}' target='_blank' aria-label='Learn more about autoscale throughput'>Learn more</a>.`;
|
||||
}
|
||||
|
||||
export function computeAutoscaleUsagePriceHourly(
|
||||
|
||||
@@ -852,6 +852,10 @@ export interface SqlContainerResource {
|
||||
|
||||
/* The conflict resolution policy for the container. */
|
||||
conflictResolutionPolicy?: ConflictResolutionPolicy;
|
||||
|
||||
//TODO: this property is manually added. It should be auto-generated instead. Need to be fixed in the API spec.
|
||||
/* Analytical storage time to live */
|
||||
analyticalStorageTtl?: number;
|
||||
}
|
||||
|
||||
/* Cosmos DB indexing policy */
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
click: onRefreshResourcesClick, clickBubble: false, event: { keypress: onRefreshDatabasesKeyPress }"
|
||||
tabindex="0"
|
||||
aria-label="Refresh tree"
|
||||
title="Refresh tree"
|
||||
>
|
||||
<img
|
||||
class="refreshcol"
|
||||
@@ -121,6 +122,7 @@
|
||||
click: toggleLeftPaneExpanded, event: { keypress: toggleLeftPaneExpandedKeyPress }"
|
||||
tabindex="0"
|
||||
aria-label="Collapse Tree"
|
||||
title="Collapse Tree"
|
||||
>
|
||||
<img class="refreshcol1" src="/imgarrowlefticon.svg" alt="Hide" />
|
||||
</span>
|
||||
@@ -259,7 +261,7 @@
|
||||
<div class="splashLoaderContentContainer">
|
||||
<p class="connectExplorerContent"><img src="/HdeConnectCosmosDB.svg" alt="Azure Cosmos DB" /></p>
|
||||
<p class="splashLoaderTitle" id="explorerLoadingStatusTitle">Welcome to Azure Cosmos DB</p>
|
||||
<p class="splashLoaderText" id="explorerLoadingStatusText">Connecting...</p>
|
||||
<p class="splashLoaderText" id="explorerLoadingStatusText" role="alert">Connecting...</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Global loader - End -->
|
||||
|
||||
@@ -62,8 +62,6 @@
|
||||
"./src/Shared/ExplorerSettings.ts",
|
||||
"./src/Shared/StorageUtility.ts",
|
||||
"./src/Shared/StringUtility.ts",
|
||||
"./src/Shared/Telemetry/TelemetryConstants.ts",
|
||||
"./src/Shared/Telemetry/TelemetryProcessor.ts",
|
||||
"./src/Shared/appInsights.ts",
|
||||
"./src/UserContext.ts",
|
||||
"./src/Utils/GitHubUtils.ts",
|
||||
|
||||
Reference in New Issue
Block a user