mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-29 22:02:01 +00:00
Compare commits
18 Commits
users/just
...
unit-tests
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f4a4e5c4c | ||
|
|
1b64827c24 | ||
|
|
a6ae784a45 | ||
|
|
7458107efd | ||
|
|
64533b445f | ||
|
|
d7bdd0032e | ||
|
|
372ac6921f | ||
|
|
c6eda097fc | ||
|
|
05d02f08fa | ||
|
|
ab4f02f74a | ||
|
|
0fc6647627 | ||
|
|
c5ed537109 | ||
|
|
db322ccb59 | ||
|
|
2d7631c358 | ||
|
|
e401c88df6 | ||
|
|
f14b574527 | ||
|
|
45513e5e1b | ||
|
|
15154dfd6a |
4
.npmrc
4
.npmrc
@@ -1,6 +1,4 @@
|
|||||||
save-exact=true
|
save-exact=true
|
||||||
registry=https://msdata.pkgs.visualstudio.com/_packaging/cosmosdbportal/npm/registry/
|
|
||||||
always-auth=true
|
|
||||||
allow-same-version=true
|
|
||||||
# Ignore peer dependency conflicts
|
# Ignore peer dependency conflicts
|
||||||
force=true # TODO: Remove this when we update to React 17 or higher!
|
force=true # TODO: Remove this when we update to React 17 or higher!
|
||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -24,6 +24,5 @@
|
|||||||
"source.organizeImports": "explicit"
|
"source.organizeImports": "explicit"
|
||||||
},
|
},
|
||||||
"typescript.preferences.importModuleSpecifier": "non-relative",
|
"typescript.preferences.importModuleSpecifier": "non-relative",
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
"sarif-viewer.connectToGithubCodeScanning": "off"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2869,6 +2869,7 @@ a:link {
|
|||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: clip;
|
overflow-x: clip;
|
||||||
|
min-height: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uniqueIndexesContainer {
|
.uniqueIndexesContainer {
|
||||||
|
|||||||
199
package-lock.json
generated
199
package-lock.json
generated
@@ -10,7 +10,7 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/arm-cosmosdb": "9.1.0",
|
"@azure/arm-cosmosdb": "9.1.0",
|
||||||
"@azure/cosmos": "4.2.0-beta.1",
|
"@azure/cosmos": "4.3.0",
|
||||||
"@azure/cosmos-language-service": "0.0.5",
|
"@azure/cosmos-language-service": "0.0.5",
|
||||||
"@azure/identity": "4.5.0",
|
"@azure/identity": "4.5.0",
|
||||||
"@azure/msal-browser": "2.14.2",
|
"@azure/msal-browser": "2.14.2",
|
||||||
@@ -290,57 +290,69 @@
|
|||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
"node_modules/@azure/core-rest-pipeline": {
|
"node_modules/@azure/core-http-compat": {
|
||||||
"version": "1.18.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.3.0.tgz",
|
||||||
"integrity": "sha512-QSoGUp4Eq/gohEFNJaUOwTN7BCc2nHTjjbm75JT0aD7W65PWM1H/tItz0GsABn22uaKyGxiMhWQLt2r+FGU89Q==",
|
"integrity": "sha512-qLQujmUypBBG0gxHd0j6/Jdmul6ttl24c8WGiLXIk7IHXdBlfoBqW27hyz3Xn6xbfdyVSarl1Ttbk0AwnZBYCw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/abort-controller": "^2.0.0",
|
"@azure/abort-controller": "^2.0.0",
|
||||||
"@azure/core-auth": "^1.8.0",
|
"@azure/core-client": "^1.3.0",
|
||||||
"@azure/core-tracing": "^1.0.1",
|
"@azure/core-rest-pipeline": "^1.20.0"
|
||||||
"@azure/core-util": "^1.11.0",
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@azure/core-lro": {
|
||||||
|
"version": "2.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz",
|
||||||
|
"integrity": "sha512-0YIpccoX8m/k00O7mDDMdJpbr6mf1yWo2dfmxt5A8XVZVVMz2SSKaEbMCeJRvgQ0IaSlqhjT47p4hVIRRy90xw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@azure/abort-controller": "^2.0.0",
|
||||||
|
"@azure/core-util": "^1.2.0",
|
||||||
"@azure/logger": "^1.0.0",
|
"@azure/logger": "^1.0.0",
|
||||||
"http-proxy-agent": "^7.0.0",
|
|
||||||
"https-proxy-agent": "^7.0.0",
|
|
||||||
"tslib": "^2.6.2"
|
"tslib": "^2.6.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/core-rest-pipeline/node_modules/agent-base": {
|
"node_modules/@azure/core-lro/node_modules/tslib": {
|
||||||
"version": "7.1.1",
|
"version": "2.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
"integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
||||||
|
},
|
||||||
|
"node_modules/@azure/core-paging": {
|
||||||
|
"version": "1.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz",
|
||||||
|
"integrity": "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.3.4"
|
"tslib": "^2.6.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 14"
|
"node": ">=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": {
|
"node_modules/@azure/core-paging/node_modules/tslib": {
|
||||||
"version": "7.0.2",
|
"version": "2.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
||||||
|
},
|
||||||
|
"node_modules/@azure/core-rest-pipeline": {
|
||||||
|
"version": "1.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.20.0.tgz",
|
||||||
|
"integrity": "sha512-ASoP8uqZBS3H/8N8at/XwFr6vYrRP3syTK0EUjDXQy0Y1/AUS+QeIRThKmTNJO2RggvBBxaXDPM7YoIwDGeA0g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"agent-base": "^7.1.0",
|
"@azure/abort-controller": "^2.0.0",
|
||||||
"debug": "^4.3.4"
|
"@azure/core-auth": "^1.8.0",
|
||||||
|
"@azure/core-tracing": "^1.0.1",
|
||||||
|
"@azure/core-util": "^1.11.0",
|
||||||
|
"@azure/logger": "^1.0.0",
|
||||||
|
"@typespec/ts-http-runtime": "^0.2.2",
|
||||||
|
"tslib": "^2.6.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 14"
|
"node": ">=18.0.0"
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": {
|
|
||||||
"version": "7.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
|
|
||||||
"integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
|
|
||||||
"dependencies": {
|
|
||||||
"agent-base": "^7.0.2",
|
|
||||||
"debug": "4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 14"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/core-rest-pipeline/node_modules/tslib": {
|
"node_modules/@azure/core-rest-pipeline/node_modules/tslib": {
|
||||||
@@ -379,15 +391,16 @@
|
|||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
"node_modules/@azure/cosmos": {
|
"node_modules/@azure/cosmos": {
|
||||||
"version": "4.2.0-beta.1",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.2.0-beta.1.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.3.0.tgz",
|
||||||
"integrity": "sha512-mREONehm1DxjEKXGaNU6Wmpf9Ckb9IrhKFXhDFVs45pxmoEb3y2s/Ub0owuFmqlphpcS1zgtYQn5exn+lwnJuQ==",
|
"integrity": "sha512-0Ls3l1uWBBSphx6YRhnM+w7rSvq8qVugBCdO6kSiNuRYXEf6+YWLjbzz4e7L2kkz/6ScFdZIOJYP+XtkiRYOhA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/abort-controller": "^2.0.0",
|
"@azure/abort-controller": "^2.0.0",
|
||||||
"@azure/core-auth": "^1.7.1",
|
"@azure/core-auth": "^1.7.1",
|
||||||
"@azure/core-rest-pipeline": "^1.15.1",
|
"@azure/core-rest-pipeline": "^1.15.1",
|
||||||
"@azure/core-tracing": "^1.1.1",
|
"@azure/core-tracing": "^1.1.1",
|
||||||
"@azure/core-util": "^1.8.1",
|
"@azure/core-util": "^1.8.1",
|
||||||
|
"@azure/keyvault-keys": "^4.8.0",
|
||||||
"fast-json-stable-stringify": "^2.1.0",
|
"fast-json-stable-stringify": "^2.1.0",
|
||||||
"jsbi": "^4.3.0",
|
"jsbi": "^4.3.0",
|
||||||
"priorityqueuejs": "^2.0.0",
|
"priorityqueuejs": "^2.0.0",
|
||||||
@@ -492,14 +505,66 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
||||||
},
|
},
|
||||||
"node_modules/@azure/logger": {
|
"node_modules/@azure/keyvault-common": {
|
||||||
"version": "1.0.4",
|
"version": "2.0.0",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/@azure/keyvault-common/-/keyvault-common-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-wRLVaroQtOqfg60cxkzUkGKrKMsCP6uYXAOomOIysSMyt1/YM0eUn9LqieAWM8DLcU4+07Fio2YGpPeqUbpP9w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@azure/abort-controller": "^2.0.0",
|
||||||
|
"@azure/core-auth": "^1.3.0",
|
||||||
|
"@azure/core-client": "^1.5.0",
|
||||||
|
"@azure/core-rest-pipeline": "^1.8.0",
|
||||||
|
"@azure/core-tracing": "^1.0.0",
|
||||||
|
"@azure/core-util": "^1.10.0",
|
||||||
|
"@azure/logger": "^1.1.4",
|
||||||
"tslib": "^2.2.0"
|
"tslib": "^2.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@azure/keyvault-common/node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
||||||
|
},
|
||||||
|
"node_modules/@azure/keyvault-keys": {
|
||||||
|
"version": "4.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@azure/keyvault-keys/-/keyvault-keys-4.9.0.tgz",
|
||||||
|
"integrity": "sha512-ZBP07+K4Pj3kS4TF4XdkqFcspWwBHry3vJSOFM5k5ZABvf7JfiMonvaFk2nBF6xjlEbMpz5PE1g45iTMme0raQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@azure/abort-controller": "^2.0.0",
|
||||||
|
"@azure/core-auth": "^1.3.0",
|
||||||
|
"@azure/core-client": "^1.5.0",
|
||||||
|
"@azure/core-http-compat": "^2.0.1",
|
||||||
|
"@azure/core-lro": "^2.2.0",
|
||||||
|
"@azure/core-paging": "^1.1.1",
|
||||||
|
"@azure/core-rest-pipeline": "^1.8.1",
|
||||||
|
"@azure/core-tracing": "^1.0.0",
|
||||||
|
"@azure/core-util": "^1.0.0",
|
||||||
|
"@azure/keyvault-common": "^2.0.0",
|
||||||
|
"@azure/logger": "^1.0.0",
|
||||||
|
"tslib": "^2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@azure/keyvault-keys/node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
||||||
|
},
|
||||||
|
"node_modules/@azure/logger": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-0hKEzLhpw+ZTAfNJyRrn6s+V0nDWzXk9OjBr2TiGIu0OfMr5s2V4FpKLTAK3Ca5r5OKLbf4hkOGDPyiRjie/jA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@typespec/ts-http-runtime": "^0.2.2",
|
||||||
|
"tslib": "^2.6.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/logger/node_modules/tslib": {
|
"node_modules/@azure/logger/node_modules/tslib": {
|
||||||
@@ -13074,6 +13139,56 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@typespec/ts-http-runtime": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-Gz/Sm64+Sq/vklJu1tt9t+4R2lvnud8NbTD/ZfpZtMiUX7YeVpCA8j6NSW8ptwcoLL+NmYANwqP8DV0q/bwl2w==",
|
||||||
|
"dependencies": {
|
||||||
|
"http-proxy-agent": "^7.0.0",
|
||||||
|
"https-proxy-agent": "^7.0.0",
|
||||||
|
"tslib": "^2.6.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@typespec/ts-http-runtime/node_modules/agent-base": {
|
||||||
|
"version": "7.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
|
||||||
|
"integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@typespec/ts-http-runtime/node_modules/http-proxy-agent": {
|
||||||
|
"version": "7.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
||||||
|
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.1.0",
|
||||||
|
"debug": "^4.3.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@typespec/ts-http-runtime/node_modules/https-proxy-agent": {
|
||||||
|
"version": "7.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
||||||
|
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.1.2",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@typespec/ts-http-runtime/node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
||||||
|
},
|
||||||
"node_modules/@ungap/url-search-params": {
|
"node_modules/@ungap/url-search-params": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/arm-cosmosdb": "9.1.0",
|
"@azure/arm-cosmosdb": "9.1.0",
|
||||||
"@azure/cosmos": "4.2.0-beta.1",
|
"@azure/cosmos": "4.3.0",
|
||||||
"@azure/cosmos-language-service": "0.0.5",
|
"@azure/cosmos-language-service": "0.0.5",
|
||||||
"@azure/identity": "4.5.0",
|
"@azure/identity": "4.5.0",
|
||||||
"@azure/msal-browser": "2.14.2",
|
"@azure/msal-browser": "2.14.2",
|
||||||
|
|||||||
6
preview/package-lock.json
generated
6
preview/package-lock.json
generated
@@ -10,7 +10,7 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/arm-cosmosdb": "9.1.0",
|
"@azure/arm-cosmosdb": "9.1.0",
|
||||||
"@azure/cosmos": "4.2.0-beta.1",
|
"@azure/cosmos": "4.3.0",
|
||||||
"@azure/cosmos-language-service": "0.0.5",
|
"@azure/cosmos-language-service": "0.0.5",
|
||||||
"@azure/identity": "4.5.0",
|
"@azure/identity": "4.5.0",
|
||||||
"@azure/msal-browser": "2.14.2",
|
"@azure/msal-browser": "2.14.2",
|
||||||
@@ -377,8 +377,8 @@
|
|||||||
"license": "0BSD"
|
"license": "0BSD"
|
||||||
},
|
},
|
||||||
"node_modules/@azure/cosmos": {
|
"node_modules/@azure/cosmos": {
|
||||||
"version": "4.2.0-beta.1",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.2.0-beta.1.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.3.0.tgz",
|
||||||
"integrity": "sha512-mREONehm1DxjEKXGaNU6Wmpf9Ckb9IrhKFXhDFVs45pxmoEb3y2s/Ub0owuFmqlphpcS1zgtYQn5exn+lwnJuQ==",
|
"integrity": "sha512-mREONehm1DxjEKXGaNU6Wmpf9Ckb9IrhKFXhDFVs45pxmoEb3y2s/Ub0owuFmqlphpcS1zgtYQn5exn+lwnJuQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/abort-controller": "^2.0.0",
|
"@azure/abort-controller": "^2.0.0",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { QueryOperationOptions } from "@azure/cosmos";
|
|
||||||
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||||
import * as Constants from "../Common/Constants";
|
import * as Constants from "../Common/Constants";
|
||||||
import { QueryResults } from "../Contracts/ViewModels";
|
import { QueryResults } from "../Contracts/ViewModels";
|
||||||
@@ -14,18 +13,14 @@ interface QueryResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MinimalQueryIterator {
|
export interface MinimalQueryIterator {
|
||||||
fetchNext: (queryOperationOptions?: QueryOperationOptions) => Promise<QueryResponse>;
|
fetchNext: () => Promise<QueryResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick<QueryIterator<any>, "fetchNext">;
|
// Pick<QueryIterator<any>, "fetchNext">;
|
||||||
|
|
||||||
export function nextPage(
|
export function nextPage(documentsIterator: MinimalQueryIterator, firstItemIndex: number): Promise<QueryResults> {
|
||||||
documentsIterator: MinimalQueryIterator,
|
|
||||||
firstItemIndex: number,
|
|
||||||
queryOperationOptions?: QueryOperationOptions,
|
|
||||||
): Promise<QueryResults> {
|
|
||||||
TelemetryProcessor.traceStart(Action.ExecuteQuery);
|
TelemetryProcessor.traceStart(Action.ExecuteQuery);
|
||||||
return documentsIterator.fetchNext(queryOperationOptions).then((response) => {
|
return documentsIterator.fetchNext().then((response) => {
|
||||||
TelemetryProcessor.traceSuccess(Action.ExecuteQuery, { dataExplorerArea: Constants.Areas.Tab });
|
TelemetryProcessor.traceSuccess(Action.ExecuteQuery, { dataExplorerArea: Constants.Areas.Tab });
|
||||||
const documents = response.resources;
|
const documents = response.resources;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { monaco } from "Explorer/LazyMonaco";
|
import { monaco } from "Explorer/LazyMonaco";
|
||||||
import { getRUThreshold, ruThresholdEnabled } from "Shared/StorageUtility";
|
|
||||||
|
|
||||||
export enum QueryErrorSeverity {
|
export enum QueryErrorSeverity {
|
||||||
Error = "Error",
|
Error = "Error",
|
||||||
@@ -103,20 +102,9 @@ export interface ErrorEnrichment {
|
|||||||
learnMoreUrl?: string;
|
learnMoreUrl?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const REPLACEMENT_MESSAGES: Record<string, (original: string) => string> = {
|
const REPLACEMENT_MESSAGES: Record<string, (original: string) => string> = {};
|
||||||
OPERATION_RU_LIMIT_EXCEEDED: (original) => {
|
|
||||||
if (ruThresholdEnabled()) {
|
|
||||||
const threshold = getRUThreshold();
|
|
||||||
return `Query exceeded the Request Unit (RU) limit of ${threshold} RUs. You can change this limit in Data Explorer settings.`;
|
|
||||||
}
|
|
||||||
return original;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const HELP_LINKS: Record<string, string> = {
|
const HELP_LINKS: Record<string, string> = {};
|
||||||
OPERATION_RU_LIMIT_EXCEEDED:
|
|
||||||
"https://learn.microsoft.com/en-us/azure/cosmos-db/data-explorer#configure-request-unit-threshold",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class QueryError {
|
export default class QueryError {
|
||||||
message: string;
|
message: string;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
exports[`getCommonQueryOptions builds the correct default options objects 1`] = `
|
exports[`getCommonQueryOptions builds the correct default options objects 1`] = `
|
||||||
{
|
{
|
||||||
"disableNonStreamingOrderByQuery": true,
|
"disableNonStreamingOrderByQuery": true,
|
||||||
|
"enableQueryControl": false,
|
||||||
"enableScanInQuery": true,
|
"enableScanInQuery": true,
|
||||||
"forceQueryPlan": true,
|
"forceQueryPlan": true,
|
||||||
"maxDegreeOfParallelism": 0,
|
"maxDegreeOfParallelism": 0,
|
||||||
@@ -14,6 +15,7 @@ exports[`getCommonQueryOptions builds the correct default options objects 1`] =
|
|||||||
exports[`getCommonQueryOptions reads from localStorage 1`] = `
|
exports[`getCommonQueryOptions reads from localStorage 1`] = `
|
||||||
{
|
{
|
||||||
"disableNonStreamingOrderByQuery": true,
|
"disableNonStreamingOrderByQuery": true,
|
||||||
|
"enableQueryControl": false,
|
||||||
"enableScanInQuery": true,
|
"enableScanInQuery": true,
|
||||||
"forceQueryPlan": true,
|
"forceQueryPlan": true,
|
||||||
"maxDegreeOfParallelism": 17,
|
"maxDegreeOfParallelism": 17,
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ export interface IBulkDeleteResult {
|
|||||||
export const deleteDocuments = async (
|
export const deleteDocuments = async (
|
||||||
collection: CollectionBase,
|
collection: CollectionBase,
|
||||||
documentIds: DocumentId[],
|
documentIds: DocumentId[],
|
||||||
|
abortSignal: AbortSignal,
|
||||||
): Promise<IBulkDeleteResult[]> => {
|
): Promise<IBulkDeleteResult[]> => {
|
||||||
const clearMessage = logConsoleProgress(`Deleting ${documentIds.length} ${getEntityName(true)}`);
|
const clearMessage = logConsoleProgress(`Deleting ${documentIds.length} ${getEntityName(true)}`);
|
||||||
try {
|
try {
|
||||||
@@ -65,7 +66,11 @@ export const deleteDocuments = async (
|
|||||||
operationType: BulkOperationType.Delete,
|
operationType: BulkOperationType.Delete,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const promise = v2Container.items.bulk(operations).then((bulkResults) => {
|
const promise = v2Container.items
|
||||||
|
.bulk(operations, undefined, {
|
||||||
|
abortSignal,
|
||||||
|
})
|
||||||
|
.then((bulkResults) => {
|
||||||
return bulkResults.map((bulkResult, index) => {
|
return bulkResults.map((bulkResult, index) => {
|
||||||
const documentId = documentIdsChunk[index];
|
const documentId = documentIdsChunk[index];
|
||||||
return { ...bulkResult, documentId };
|
return { ...bulkResult, documentId };
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export const getCommonQueryOptions = (options: FeedOptions): FeedOptions => {
|
|||||||
options.maxItemCount ||
|
options.maxItemCount ||
|
||||||
(storedItemPerPageSetting !== undefined && storedItemPerPageSetting) ||
|
(storedItemPerPageSetting !== undefined && storedItemPerPageSetting) ||
|
||||||
Queries.itemsPerPage;
|
Queries.itemsPerPage;
|
||||||
|
options.enableQueryControl = LocalStorageUtility.getEntryBoolean(StorageKey.QueryControlEnabled);
|
||||||
options.maxDegreeOfParallelism = LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism);
|
options.maxDegreeOfParallelism = LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism);
|
||||||
options.disableNonStreamingOrderByQuery = !isVectorSearchEnabled();
|
options.disableNonStreamingOrderByQuery = !isVectorSearchEnabled();
|
||||||
return options;
|
return options;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { QueryOperationOptions } from "@azure/cosmos";
|
|
||||||
import { QueryResults } from "../../Contracts/ViewModels";
|
import { QueryResults } from "../../Contracts/ViewModels";
|
||||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { getEntityName } from "../DocumentUtility";
|
import { getEntityName } from "../DocumentUtility";
|
||||||
@@ -9,13 +8,12 @@ export const queryDocumentsPage = async (
|
|||||||
resourceName: string,
|
resourceName: string,
|
||||||
documentsIterator: MinimalQueryIterator,
|
documentsIterator: MinimalQueryIterator,
|
||||||
firstItemIndex: number,
|
firstItemIndex: number,
|
||||||
queryOperationOptions?: QueryOperationOptions,
|
|
||||||
): Promise<QueryResults> => {
|
): Promise<QueryResults> => {
|
||||||
const entityName = getEntityName();
|
const entityName = getEntityName();
|
||||||
const clearMessage = logConsoleProgress(`Querying ${entityName} for container ${resourceName}`);
|
const clearMessage = logConsoleProgress(`Querying ${entityName} for container ${resourceName}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result: QueryResults = await nextPage(documentsIterator, firstItemIndex, queryOperationOptions);
|
const result: QueryResults = await nextPage(documentsIterator, firstItemIndex);
|
||||||
const itemCount = (result.documents && result.documents.length) || 0;
|
const itemCount = (result.documents && result.documents.length) || 0;
|
||||||
logConsoleInfo(`Successfully fetched ${itemCount} ${entityName} for container ${resourceName}`);
|
logConsoleInfo(`Successfully fetched ${itemCount} ${entityName} for container ${resourceName}`);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -126,12 +126,5 @@ async function readCollectionsWithARM(databaseId: string): Promise<DataModels.Co
|
|||||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
throw new Error(`Unsupported default experience type: ${apiType}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TO DO: Remove when we get RP API Spec with materializedViews
|
return rpResponse?.value?.map((collection) => collection.properties?.resource as DataModels.Collection);
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
return rpResponse?.value?.map((collection: any) => {
|
|
||||||
const collectionDataModel: DataModels.Collection = collection.properties?.resource as DataModels.Collection;
|
|
||||||
collectionDataModel.materializedViews = collection.properties?.resource?.materializedViews;
|
|
||||||
collectionDataModel.materializedViewDefinition = collection.properties?.resource?.materializedViewDefinition;
|
|
||||||
return collectionDataModel;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export enum PaneKind {
|
|||||||
GlobalSettings,
|
GlobalSettings,
|
||||||
AdHocAccess,
|
AdHocAccess,
|
||||||
SwitchDirectory,
|
SwitchDirectory,
|
||||||
|
QuickStart,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export interface ArmEntity {
|
|||||||
type: string;
|
type: string;
|
||||||
kind: string;
|
kind: string;
|
||||||
tags?: Tags;
|
tags?: Tags;
|
||||||
|
resourceGroup?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DatabaseAccount extends ArmEntity {
|
export interface DatabaseAccount extends ArmEntity {
|
||||||
@@ -388,7 +389,7 @@ export interface VectorEmbeddingPolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface VectorEmbedding {
|
export interface VectorEmbedding {
|
||||||
dataType: "float16" | "float32" | "uint8" | "int8";
|
dataType: "float32" | "uint8" | "int8";
|
||||||
dimensions: number;
|
dimensions: number;
|
||||||
distanceFunction: "euclidean" | "cosine" | "dotproduct";
|
distanceFunction: "euclidean" | "cosine" | "dotproduct";
|
||||||
path: string;
|
path: string;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
ItemDefinition,
|
||||||
JSONObject,
|
JSONObject,
|
||||||
QueryMetrics,
|
QueryMetrics,
|
||||||
Resource,
|
Resource,
|
||||||
@@ -30,8 +31,11 @@ export interface UploadDetailsRecord {
|
|||||||
numFailed: number;
|
numFailed: number;
|
||||||
numThrottled: number;
|
numThrottled: number;
|
||||||
errors: string[];
|
errors: string[];
|
||||||
|
resources?: ItemDefinition[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BulkInsertResult = Omit<UploadDetailsRecord, "fileName">;
|
||||||
|
|
||||||
export interface QueryResultsMetadata {
|
export interface QueryResultsMetadata {
|
||||||
hasMoreResults: boolean;
|
hasMoreResults: boolean;
|
||||||
firstItemIndex: number;
|
firstItemIndex: number;
|
||||||
@@ -46,6 +50,7 @@ export interface QueryResults extends QueryResultsMetadata {
|
|||||||
roundTrips?: number;
|
roundTrips?: number;
|
||||||
headers?: any;
|
headers?: any;
|
||||||
queryMetrics?: QueryMetrics;
|
queryMetrics?: QueryMetrics;
|
||||||
|
ruThresholdExceeded?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Button {
|
export interface Button {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
} from "Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputBucketsComponent";
|
} from "Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputBucketsComponent";
|
||||||
import { useDatabases } from "Explorer/useDatabases";
|
import { useDatabases } from "Explorer/useDatabases";
|
||||||
import { isFabricNative } from "Platform/Fabric/FabricUtil";
|
import { isFabricNative } from "Platform/Fabric/FabricUtil";
|
||||||
import { isFullTextSearchEnabled, isVectorSearchEnabled } from "Utils/CapabilityUtils";
|
import { isVectorSearchEnabled } from "Utils/CapabilityUtils";
|
||||||
import { isRunningOnPublicCloud } from "Utils/CloudUtils";
|
import { isRunningOnPublicCloud } from "Utils/CloudUtils";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import DiscardIcon from "../../../../images/discard.svg";
|
import DiscardIcon from "../../../../images/discard.svg";
|
||||||
@@ -188,7 +188,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
|||||||
this.isGlobalSecondaryIndex =
|
this.isGlobalSecondaryIndex =
|
||||||
!!this.collection?.materializedViewDefinition() || !!this.collection?.materializedViews();
|
!!this.collection?.materializedViewDefinition() || !!this.collection?.materializedViews();
|
||||||
this.isVectorSearchEnabled = isVectorSearchEnabled() && !hasDatabaseSharedThroughput(this.collection);
|
this.isVectorSearchEnabled = isVectorSearchEnabled() && !hasDatabaseSharedThroughput(this.collection);
|
||||||
this.isFullTextSearchEnabled = isFullTextSearchEnabled() && !hasDatabaseSharedThroughput(this.collection);
|
this.isFullTextSearchEnabled = userContext.apiType === "SQL";
|
||||||
|
|
||||||
this.changeFeedPolicyVisible = userContext.features.enableChangeFeedPolicy;
|
this.changeFeedPolicyVisible = userContext.features.enableChangeFeedPolicy;
|
||||||
this.throughputBucketsEnabled = userContext.throughputBucketsEnabled;
|
this.throughputBucketsEnabled = userContext.throughputBucketsEnabled;
|
||||||
@@ -1091,6 +1091,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
|||||||
currentOffer: this.collection.offer(),
|
currentOffer: this.collection.offer(),
|
||||||
autopilotThroughput: this.state.isAutoPilotSelected ? this.state.autoPilotThroughput : undefined,
|
autopilotThroughput: this.state.isAutoPilotSelected ? this.state.autoPilotThroughput : undefined,
|
||||||
manualThroughput: this.state.isAutoPilotSelected ? undefined : this.state.throughput,
|
manualThroughput: this.state.isAutoPilotSelected ? undefined : this.state.throughput,
|
||||||
|
throughputBuckets: this.throughputBucketsEnabled ? this.state.throughputBuckets : undefined,
|
||||||
};
|
};
|
||||||
if (this.hasProvisioningTypeChanged()) {
|
if (this.hasProvisioningTypeChanged()) {
|
||||||
if (this.state.isAutoPilotSelected) {
|
if (this.state.isAutoPilotSelected) {
|
||||||
|
|||||||
@@ -198,6 +198,32 @@ exports[`SettingsComponent renders 1`] = `
|
|||||||
timeToLiveSecondsBaseline={5}
|
timeToLiveSecondsBaseline={5}
|
||||||
/>
|
/>
|
||||||
</PivotItem>
|
</PivotItem>
|
||||||
|
<PivotItem
|
||||||
|
headerText="Container Policies"
|
||||||
|
itemKey="ContainerVectorPolicyTab"
|
||||||
|
key="ContainerVectorPolicyTab"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginTop": 20,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ContainerPolicyComponent
|
||||||
|
fullTextPolicy={{}}
|
||||||
|
fullTextPolicyBaseline={{}}
|
||||||
|
isFullTextSearchEnabled={true}
|
||||||
|
isGlobalSecondaryIndex={true}
|
||||||
|
isVectorSearchEnabled={false}
|
||||||
|
onFullTextPolicyChange={[Function]}
|
||||||
|
onFullTextPolicyDirtyChange={[Function]}
|
||||||
|
onVectorEmbeddingPolicyChange={[Function]}
|
||||||
|
onVectorEmbeddingPolicyDirtyChange={[Function]}
|
||||||
|
resetShouldDiscardContainerPolicyChange={[Function]}
|
||||||
|
shouldDiscardContainerPolicies={false}
|
||||||
|
vectorEmbeddingPolicy={{}}
|
||||||
|
vectorEmbeddingPolicyBaseline={{}}
|
||||||
|
/>
|
||||||
|
</PivotItem>
|
||||||
<PivotItem
|
<PivotItem
|
||||||
headerText="Indexing Policy"
|
headerText="Indexing Policy"
|
||||||
itemKey="IndexingPolicyTab"
|
itemKey="IndexingPolicyTab"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Text } from "@fluentui/react";
|
import { Stack, Text } from "@fluentui/react";
|
||||||
import React, { FunctionComponent } from "react";
|
import React, { FunctionComponent } from "react";
|
||||||
import { InfoTooltip } from "../../../../Common/Tooltip/InfoTooltip";
|
import { InfoTooltip } from "../../../../Common/Tooltip/InfoTooltip";
|
||||||
import * as SharedConstants from "../../../../Shared/Constants";
|
import * as SharedConstants from "../../../../Shared/Constants";
|
||||||
@@ -54,6 +54,7 @@ export const CostEstimateText: FunctionComponent<CostEstimateTextProps> = ({
|
|||||||
|
|
||||||
if (isAutoscale) {
|
if (isAutoscale) {
|
||||||
return (
|
return (
|
||||||
|
<Stack style={{ marginBottom: 6 }}>
|
||||||
<Text variant="small">
|
<Text variant="small">
|
||||||
{estimatedMonthlyCost} ({currency}){iconWithEstimatedCostDisclaimer}:{" "}
|
{estimatedMonthlyCost} ({currency}){iconWithEstimatedCostDisclaimer}:{" "}
|
||||||
<b>
|
<b>
|
||||||
@@ -63,10 +64,12 @@ export const CostEstimateText: FunctionComponent<CostEstimateTextProps> = ({
|
|||||||
({numberOfRegions + (numberOfRegions === 1 ? " region" : " regions")}, {requestUnits / 10} - {requestUnits}{" "}
|
({numberOfRegions + (numberOfRegions === 1 ? " region" : " regions")}, {requestUnits / 10} - {requestUnits}{" "}
|
||||||
RU/s, {currencySign + pricePerRu}/RU)
|
RU/s, {currencySign + pricePerRu}/RU)
|
||||||
</Text>
|
</Text>
|
||||||
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<Stack style={{ marginBottom: 8 }}>
|
||||||
<Text variant="small">
|
<Text variant="small">
|
||||||
Estimated cost ({currency}){iconWithEstimatedCostDisclaimer}:{" "}
|
Estimated cost ({currency}){iconWithEstimatedCostDisclaimer}:{" "}
|
||||||
<b>
|
<b>
|
||||||
@@ -77,5 +80,6 @@ export const CostEstimateText: FunctionComponent<CostEstimateTextProps> = ({
|
|||||||
({numberOfRegions + (numberOfRegions === 1 ? " region" : " regions")}, {requestUnits}RU/s,{" "}
|
({numberOfRegions + (numberOfRegions === 1 ? " region" : " regions")}, {requestUnits}RU/s,{" "}
|
||||||
{currencySign + pricePerRu}/RU)
|
{currencySign + pricePerRu}/RU)
|
||||||
</Text>
|
</Text>
|
||||||
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Checkbox, DirectionalHint, Link, Stack, Text, TextField, TooltipHost } from "@fluentui/react";
|
import { Checkbox, DirectionalHint, Link, Separator, Stack, Text, TextField, TooltipHost } from "@fluentui/react";
|
||||||
import { getWorkloadType } from "Common/DatabaseAccountUtility";
|
import { getWorkloadType } from "Common/DatabaseAccountUtility";
|
||||||
|
import { CostEstimateText } from "Explorer/Controls/ThroughputInput/CostEstimateText/CostEstimateText";
|
||||||
import { useDatabases } from "Explorer/useDatabases";
|
import { useDatabases } from "Explorer/useDatabases";
|
||||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||||
import * as Constants from "../../../Common/Constants";
|
import * as Constants from "../../../Common/Constants";
|
||||||
@@ -9,8 +10,8 @@ import { userContext } from "../../../UserContext";
|
|||||||
import { getCollectionName } from "../../../Utils/APITypeUtils";
|
import { getCollectionName } from "../../../Utils/APITypeUtils";
|
||||||
import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils";
|
import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils";
|
||||||
import * as PricingUtils from "../../../Utils/PricingUtils";
|
import * as PricingUtils from "../../../Utils/PricingUtils";
|
||||||
import { CostEstimateText } from "./CostEstimateText/CostEstimateText";
|
|
||||||
import "./ThroughputInput.less";
|
import "./ThroughputInput.less";
|
||||||
|
import { isFabricNative } from "../../../Platform/Fabric/FabricUtil";
|
||||||
|
|
||||||
export interface ThroughputInputProps {
|
export interface ThroughputInputProps {
|
||||||
isDatabase: boolean;
|
isDatabase: boolean;
|
||||||
@@ -43,7 +44,8 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
|
|||||||
if (
|
if (
|
||||||
isFreeTier ||
|
isFreeTier ||
|
||||||
isQuickstart ||
|
isQuickstart ||
|
||||||
[Constants.WorkloadType.Learning, Constants.WorkloadType.DevelopmentTesting].includes(workloadType)
|
[Constants.WorkloadType.Learning, Constants.WorkloadType.DevelopmentTesting].includes(workloadType) ||
|
||||||
|
isFabricNative()
|
||||||
) {
|
) {
|
||||||
defaultThroughput = AutoPilotUtils.autoPilotThroughput1K;
|
defaultThroughput = AutoPilotUtils.autoPilotThroughput1K;
|
||||||
} else if (workloadType === Constants.WorkloadType.Production) {
|
} else if (workloadType === Constants.WorkloadType.Production) {
|
||||||
@@ -230,36 +232,65 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isAutoscaleSelected && (
|
{isAutoscaleSelected && (
|
||||||
<Stack className="throughputInputSpacing">
|
<Stack className="throughputInputSpacing">
|
||||||
<Text variant="small" aria-label="capacity calculator of azure cosmos db">
|
<Text style={{ marginTop: -2, fontSize: 12 }}>
|
||||||
Estimate your required RU/s with{" "}
|
Your container throughput will automatically scale up to the maximum value you select, from a minimum of 10%
|
||||||
<Link
|
of that value.
|
||||||
className="underlinedLink outlineNone"
|
</Text>
|
||||||
target="_blank"
|
<Stack horizontal verticalAlign="end" tokens={{ childrenGap: 8 }}>
|
||||||
href="https://cosmos.azure.com/capacitycalculator/"
|
<Stack tokens={{ childrenGap: 4 }}>
|
||||||
aria-label="capacity calculator of azure cosmos db"
|
<Stack horizontal verticalAlign="center" tokens={{ childrenGap: 4 }}>
|
||||||
|
<Text variant="small" style={{ lineHeight: "20px", fontWeight: 600 }}>
|
||||||
|
Minimum RU/s
|
||||||
|
</Text>
|
||||||
|
<InfoTooltip>The minimum RU/s your container will scale to</InfoTooltip>
|
||||||
|
</Stack>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontFamily: "Segoe UI",
|
||||||
|
width: 70,
|
||||||
|
height: 27,
|
||||||
|
border: "none",
|
||||||
|
fontSize: 14,
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
fontWeight: 400,
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
capacity calculator
|
{Math.round(throughput / 10).toString()}
|
||||||
</Link>
|
</Text>
|
||||||
.
|
</Stack>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontFamily: "Segoe UI",
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 400,
|
||||||
|
paddingBottom: 6,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
x 10 =
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Stack horizontal>
|
<Stack tokens={{ childrenGap: 4 }}>
|
||||||
<Text variant="small" style={{ lineHeight: "20px", fontWeight: 600 }} aria-label="maxRUDescription">
|
<Stack horizontal verticalAlign="center" tokens={{ childrenGap: 4 }}>
|
||||||
{isDatabase ? "Database" : getCollectionName()} Max RU/s
|
<Text variant="small" style={{ lineHeight: "20px", fontWeight: 600 }}>
|
||||||
|
Maximum RU/s
|
||||||
</Text>
|
</Text>
|
||||||
<InfoTooltip>{getAutoScaleTooltip()}</InfoTooltip>
|
<InfoTooltip>{getAutoScaleTooltip()}</InfoTooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
id="autoscaleRUValueField"
|
id="autoscaleRUValueField"
|
||||||
type="number"
|
type="number"
|
||||||
styles={{
|
styles={{
|
||||||
fieldGroup: { width: 300, height: 27 },
|
fieldGroup: { width: 100, height: 27, flexShrink: 0 },
|
||||||
field: { fontSize: 12 },
|
field: { fontSize: 14, fontWeight: 400 },
|
||||||
}}
|
}}
|
||||||
onChange={(event, newInput?: string) => onThroughputValueChange(newInput)}
|
onChange={(_event, newInput?: string) => onThroughputValueChange(newInput)}
|
||||||
step={AutoPilotUtils.autoPilotIncrementStep}
|
step={AutoPilotUtils.autoPilotIncrementStep}
|
||||||
min={AutoPilotUtils.autoPilotThroughput1K}
|
min={AutoPilotUtils.autoPilotThroughput1K}
|
||||||
max={isSharded ? Number.MAX_SAFE_INTEGER.toString() : "10000"}
|
max={isSharded ? Number.MAX_SAFE_INTEGER.toString() : "10000"}
|
||||||
@@ -268,16 +299,26 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
|
|||||||
required={true}
|
required={true}
|
||||||
errorMessage={throughputError}
|
errorMessage={throughputError}
|
||||||
/>
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<Text variant="small">
|
<CostEstimateText requestUnits={throughput} isAutoscale={isAutoscaleSelected} />
|
||||||
Your {isDatabase ? "database" : getCollectionName().toLocaleLowerCase()} throughput will automatically scale
|
<Stack className="throughputInputSpacing">
|
||||||
from{" "}
|
<Text variant="small" aria-label="ruDescription">
|
||||||
<b>
|
Estimate your required RU/s with
|
||||||
{AutoPilotUtils.getMinRUsBasedOnUserInput(throughput)} RU/s (10% of max RU/s) - {throughput} RU/s
|
<Link
|
||||||
</b>{" "}
|
className="underlinedLink"
|
||||||
based on usage.
|
target="_blank"
|
||||||
|
href="https://cosmos.azure.com/capacitycalculator/"
|
||||||
|
aria-label="Capacity calculator"
|
||||||
|
>
|
||||||
|
capacity calculator
|
||||||
|
</Link>
|
||||||
|
.
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<Separator className="panelSeparator" style={{ paddingTop: -8, paddingBottom: -8 }} />
|
||||||
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isAutoscaleSelected && (
|
{!isAutoscaleSelected && (
|
||||||
@@ -300,7 +341,6 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
|
|||||||
</Text>
|
</Text>
|
||||||
<InfoTooltip>{getAutoScaleTooltip()}</InfoTooltip>
|
<InfoTooltip>{getAutoScaleTooltip()}</InfoTooltip>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<TooltipHost
|
<TooltipHost
|
||||||
directionalHint={DirectionalHint.topLeftEdge}
|
directionalHint={DirectionalHint.topLeftEdge}
|
||||||
content={
|
content={
|
||||||
@@ -325,11 +365,10 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
|
|||||||
errorMessage={throughputError}
|
errorMessage={throughputError}
|
||||||
/>
|
/>
|
||||||
</TooltipHost>
|
</TooltipHost>
|
||||||
|
<CostEstimateText requestUnits={throughput} isAutoscale={isAutoscaleSelected} />
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<CostEstimateText requestUnits={throughput} isAutoscale={isAutoscaleSelected} />
|
|
||||||
|
|
||||||
{throughput > SharedConstants.CollectionCreation.DefaultCollectionRUs100K && (
|
{throughput > SharedConstants.CollectionCreation.DefaultCollectionRUs100K && (
|
||||||
<Stack horizontal verticalAlign="start">
|
<Stack horizontal verticalAlign="start">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@ import { readDatabases } from "../Common/dataAccess/readDatabases";
|
|||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
import { ContainerConnectionInfo, IPhoenixServiceInfo, IProvisionData, IResponse } from "../Contracts/DataModels";
|
import { ContainerConnectionInfo, IPhoenixServiceInfo, IProvisionData, IResponse } from "../Contracts/DataModels";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
|
import { UploadDetailsRecord } from "../Contracts/ViewModels";
|
||||||
import { GitHubOAuthService } from "../GitHub/GitHubOAuthService";
|
import { GitHubOAuthService } from "../GitHub/GitHubOAuthService";
|
||||||
import { PhoenixClient } from "../Phoenix/PhoenixClient";
|
import { PhoenixClient } from "../Phoenix/PhoenixClient";
|
||||||
import * as ExplorerSettings from "../Shared/ExplorerSettings";
|
import * as ExplorerSettings from "../Shared/ExplorerSettings";
|
||||||
@@ -1115,8 +1116,8 @@ export default class Explorer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public openUploadItemsPane(): void {
|
public openUploadItemsPane(onUpload?: (data: UploadDetailsRecord[]) => void): void {
|
||||||
useSidePanel.getState().openSidePanel("Upload " + getUploadName(), <UploadItemsPane />);
|
useSidePanel.getState().openSidePanel("Upload " + getUploadName(), <UploadItemsPane onUpload={onUpload} />);
|
||||||
}
|
}
|
||||||
public openExecuteSprocParamsPanel(storedProcedure: StoredProcedure): void {
|
public openExecuteSprocParamsPanel(storedProcedure: StoredProcedure): void {
|
||||||
useSidePanel
|
useSidePanel
|
||||||
@@ -1124,7 +1125,7 @@ export default class Explorer {
|
|||||||
.openSidePanel("Input parameters", <ExecuteSprocParamsPane storedProcedure={storedProcedure} />);
|
.openSidePanel("Input parameters", <ExecuteSprocParamsPane storedProcedure={storedProcedure} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getDownloadModalConent(fileName: string): JSX.Element {
|
public getDownloadModalContent(fileName: string): JSX.Element {
|
||||||
if (useNotebook.getState().isPhoenixNotebooks) {
|
if (useNotebook.getState().isPhoenixNotebooks) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ import * as StorageUtility from "../../../Shared/StorageUtility";
|
|||||||
import { LocalStorageUtility, StorageKey } from "../../../Shared/StorageUtility";
|
import { LocalStorageUtility, StorageKey } from "../../../Shared/StorageUtility";
|
||||||
import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
|
import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils";
|
import {
|
||||||
|
logConsoleError,
|
||||||
|
logConsoleInfo,
|
||||||
|
logConsoleProgress,
|
||||||
|
logConsoleWarning,
|
||||||
|
} from "../../../Utils/NotificationConsoleUtils";
|
||||||
import { EditorReact } from "../../Controls/Editor/EditorReact";
|
import { EditorReact } from "../../Controls/Editor/EditorReact";
|
||||||
import * as InputTypeaheadComponent from "../../Controls/InputTypeahead/InputTypeaheadComponent";
|
import * as InputTypeaheadComponent from "../../Controls/InputTypeahead/InputTypeaheadComponent";
|
||||||
import * as TabComponent from "../../Controls/Tabs/TabComponent";
|
import * as TabComponent from "../../Controls/Tabs/TabComponent";
|
||||||
@@ -1083,6 +1088,7 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
public static reportToConsole(type: ConsoleDataType.InProgress, msg: string, ...errorData: any[]): () => void;
|
public static reportToConsole(type: ConsoleDataType.InProgress, msg: string, ...errorData: any[]): () => void;
|
||||||
public static reportToConsole(type: ConsoleDataType.Info, msg: string, ...errorData: any[]): void;
|
public static reportToConsole(type: ConsoleDataType.Info, msg: string, ...errorData: any[]): void;
|
||||||
public static reportToConsole(type: ConsoleDataType.Error, msg: string, ...errorData: any[]): void;
|
public static reportToConsole(type: ConsoleDataType.Error, msg: string, ...errorData: any[]): void;
|
||||||
|
public static reportToConsole(type: ConsoleDataType.Warning, msg: string, ...errorData: any[]): void;
|
||||||
public static reportToConsole(type: ConsoleDataType, msg: string, ...errorData: any[]): void | (() => void) {
|
public static reportToConsole(type: ConsoleDataType, msg: string, ...errorData: any[]): void | (() => void) {
|
||||||
let errorDataStr = "";
|
let errorDataStr = "";
|
||||||
if (errorData && errorData.length > 0) {
|
if (errorData && errorData.length > 0) {
|
||||||
@@ -1099,6 +1105,8 @@ export class GraphExplorer extends React.Component<GraphExplorerProps, GraphExpl
|
|||||||
return logConsoleInfo(consoleMessage);
|
return logConsoleInfo(consoleMessage);
|
||||||
case ConsoleDataType.InProgress:
|
case ConsoleDataType.InProgress:
|
||||||
return logConsoleProgress(consoleMessage);
|
return logConsoleProgress(consoleMessage);
|
||||||
|
case ConsoleDataType.Warning:
|
||||||
|
return logConsoleWarning(consoleMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,3 +95,10 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.newVertexComponent {
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,4 +13,5 @@ export enum ConsoleDataType {
|
|||||||
Info = 0,
|
Info = 0,
|
||||||
Error = 1,
|
Error = 1,
|
||||||
InProgress = 2,
|
InProgress = 2,
|
||||||
|
Warning = 3,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,8 +173,20 @@
|
|||||||
.message {
|
.message {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
white-space:pre-wrap;
|
white-space:pre-wrap;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.notificationConsoleContents {
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.notificationConsoleData {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@ import ErrorRedIcon from "../../../../images/error_red.svg";
|
|||||||
import infoBubbleIcon from "../../../../images/info-bubble-9x9.svg";
|
import infoBubbleIcon from "../../../../images/info-bubble-9x9.svg";
|
||||||
import InfoIcon from "../../../../images/info_color.svg";
|
import InfoIcon from "../../../../images/info_color.svg";
|
||||||
import LoadingIcon from "../../../../images/loading.svg";
|
import LoadingIcon from "../../../../images/loading.svg";
|
||||||
|
import WarningIcon from "../../../../images/warning.svg";
|
||||||
import { ClientDefaults, KeyCodes } from "../../../Common/Constants";
|
import { ClientDefaults, KeyCodes } from "../../../Common/Constants";
|
||||||
import { userContext } from "../../../UserContext";
|
import { userContext } from "../../../UserContext";
|
||||||
import { useNotificationConsole } from "../../../hooks/useNotificationConsole";
|
import { useNotificationConsole } from "../../../hooks/useNotificationConsole";
|
||||||
@@ -91,6 +92,9 @@ export class NotificationConsoleComponent extends React.Component<
|
|||||||
const numInfoItems = this.state.allConsoleData.filter(
|
const numInfoItems = this.state.allConsoleData.filter(
|
||||||
(data: ConsoleData) => data.type === ConsoleDataType.Info,
|
(data: ConsoleData) => data.type === ConsoleDataType.Info,
|
||||||
).length;
|
).length;
|
||||||
|
const numWarningItems = this.state.allConsoleData.filter(
|
||||||
|
(data: ConsoleData) => data.type === ConsoleDataType.Warning,
|
||||||
|
).length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="notificationConsoleContainer">
|
<div className="notificationConsoleContainer">
|
||||||
@@ -118,6 +122,10 @@ export class NotificationConsoleComponent extends React.Component<
|
|||||||
<img src={infoBubbleIcon} alt="Info items" />
|
<img src={infoBubbleIcon} alt="Info items" />
|
||||||
<span className="numInfoItems">{numInfoItems}</span>
|
<span className="numInfoItems">{numInfoItems}</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span className="notificationConsoleHeaderIconWithData">
|
||||||
|
<img src={WarningIcon} alt="Warning items" />
|
||||||
|
<span className="numWarningItems">{numWarningItems}</span>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
{userContext.features.pr && <PrPreview pr={userContext.features.pr} />}
|
{userContext.features.pr && <PrPreview pr={userContext.features.pr} />}
|
||||||
<span className="consoleSplitter" />
|
<span className="consoleSplitter" />
|
||||||
@@ -198,6 +206,7 @@ export class NotificationConsoleComponent extends React.Component<
|
|||||||
{item.type === ConsoleDataType.Info && <img className="infoIcon" src={InfoIcon} alt="info" />}
|
{item.type === ConsoleDataType.Info && <img className="infoIcon" src={InfoIcon} alt="info" />}
|
||||||
{item.type === ConsoleDataType.Error && <img className="errorIcon" src={ErrorRedIcon} alt="error" />}
|
{item.type === ConsoleDataType.Error && <img className="errorIcon" src={ErrorRedIcon} alt="error" />}
|
||||||
{item.type === ConsoleDataType.InProgress && <img className="loaderIcon" src={LoaderIcon} alt="in progress" />}
|
{item.type === ConsoleDataType.InProgress && <img className="loaderIcon" src={LoaderIcon} alt="in progress" />}
|
||||||
|
{item.type === ConsoleDataType.Warning && <img className="warningIcon" src={WarningIcon} alt="warning" />}
|
||||||
<span className="date">{item.date}</span>
|
<span className="date">{item.date}</span>
|
||||||
<span className="message" role="alert" aria-live="assertive">
|
<span className="message" role="alert" aria-live="assertive">
|
||||||
{item.message}
|
{item.message}
|
||||||
|
|||||||
@@ -59,6 +59,19 @@ exports[`NotificationConsoleComponent renders the console 1`] = `
|
|||||||
0
|
0
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span
|
||||||
|
className="notificationConsoleHeaderIconWithData"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="Warning items"
|
||||||
|
src={{}}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className="numWarningItems"
|
||||||
|
>
|
||||||
|
0
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="consoleSplitter"
|
className="consoleSplitter"
|
||||||
@@ -229,6 +242,19 @@ exports[`NotificationConsoleComponent renders the console 2`] = `
|
|||||||
1
|
1
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span
|
||||||
|
className="notificationConsoleHeaderIconWithData"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="Warning items"
|
||||||
|
src={{}}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className="numWarningItems"
|
||||||
|
>
|
||||||
|
0
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="consoleSplitter"
|
className="consoleSplitter"
|
||||||
|
|||||||
@@ -188,6 +188,11 @@ function openPane(action: ActionContracts.OpenPane, explorer: Explorer) {
|
|||||||
action.paneKind === ActionContracts.PaneKind[ActionContracts.PaneKind.AddCollection]
|
action.paneKind === ActionContracts.PaneKind[ActionContracts.PaneKind.AddCollection]
|
||||||
) {
|
) {
|
||||||
explorer.onNewCollectionClicked();
|
explorer.onNewCollectionClicked();
|
||||||
|
} else if (
|
||||||
|
action.paneKind === ActionContracts.PaneKind.QuickStart ||
|
||||||
|
action.paneKind === ActionContracts.PaneKind[ActionContracts.PaneKind.QuickStart]
|
||||||
|
) {
|
||||||
|
explorer.onNewCollectionClicked({ isQuickstart: true });
|
||||||
} else if (
|
} else if (
|
||||||
action.paneKind === ActionContracts.PaneKind.CassandraAddCollection ||
|
action.paneKind === ActionContracts.PaneKind.CassandraAddCollection ||
|
||||||
action.paneKind === ActionContracts.PaneKind[ActionContracts.PaneKind.CassandraAddCollection]
|
action.paneKind === ActionContracts.PaneKind[ActionContracts.PaneKind.CassandraAddCollection]
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { FullTextPoliciesComponent } from "Explorer/Controls/FullTextSeach/FullT
|
|||||||
import { VectorEmbeddingPoliciesComponent } from "Explorer/Controls/VectorSearch/VectorEmbeddingPoliciesComponent";
|
import { VectorEmbeddingPoliciesComponent } from "Explorer/Controls/VectorSearch/VectorEmbeddingPoliciesComponent";
|
||||||
import {
|
import {
|
||||||
AllPropertiesIndexed,
|
AllPropertiesIndexed,
|
||||||
AnalyticalStorageContent,
|
AnalyticalStoreHeader,
|
||||||
ContainerVectorPolicyTooltipContent,
|
ContainerVectorPolicyTooltipContent,
|
||||||
FullTextPolicyDefault,
|
FullTextPolicyDefault,
|
||||||
getPartitionKey,
|
getPartitionKey,
|
||||||
@@ -49,12 +49,7 @@ import { Action } from "Shared/Telemetry/TelemetryConstants";
|
|||||||
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
|
||||||
import { userContext } from "UserContext";
|
import { userContext } from "UserContext";
|
||||||
import { getCollectionName } from "Utils/APITypeUtils";
|
import { getCollectionName } from "Utils/APITypeUtils";
|
||||||
import {
|
import { isCapabilityEnabled, isServerlessAccount, isVectorSearchEnabled } from "Utils/CapabilityUtils";
|
||||||
isCapabilityEnabled,
|
|
||||||
isFullTextSearchEnabled,
|
|
||||||
isServerlessAccount,
|
|
||||||
isVectorSearchEnabled,
|
|
||||||
} from "Utils/CapabilityUtils";
|
|
||||||
import { getUpsellMessage } from "Utils/PricingUtils";
|
import { getUpsellMessage } from "Utils/PricingUtils";
|
||||||
import { ValidCosmosDbIdDescription, ValidCosmosDbIdInputPattern } from "Utils/ValidationUtils";
|
import { ValidCosmosDbIdDescription, ValidCosmosDbIdInputPattern } from "Utils/ValidationUtils";
|
||||||
import { CollapsibleSectionComponent } from "../../Controls/CollapsiblePanel/CollapsibleSectionComponent";
|
import { CollapsibleSectionComponent } from "../../Controls/CollapsiblePanel/CollapsibleSectionComponent";
|
||||||
@@ -65,6 +60,7 @@ import { useDatabases } from "../../useDatabases";
|
|||||||
import { PanelFooterComponent } from "../PanelFooterComponent";
|
import { PanelFooterComponent } from "../PanelFooterComponent";
|
||||||
import { PanelInfoErrorComponent } from "../PanelInfoErrorComponent";
|
import { PanelInfoErrorComponent } from "../PanelInfoErrorComponent";
|
||||||
import { PanelLoadingScreen } from "../PanelLoadingScreen";
|
import { PanelLoadingScreen } from "../PanelLoadingScreen";
|
||||||
|
import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils";
|
||||||
|
|
||||||
export interface AddCollectionPanelProps {
|
export interface AddCollectionPanelProps {
|
||||||
explorer: Explorer;
|
explorer: Explorer;
|
||||||
@@ -110,6 +106,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
private collectionThroughput: number;
|
private collectionThroughput: number;
|
||||||
private isCollectionAutoscale: boolean;
|
private isCollectionAutoscale: boolean;
|
||||||
private isCostAcknowledged: boolean;
|
private isCostAcknowledged: boolean;
|
||||||
|
private showFullTextSearch: boolean;
|
||||||
|
|
||||||
constructor(props: AddCollectionPanelProps) {
|
constructor(props: AddCollectionPanelProps) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -144,6 +141,8 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
fullTextIndexes: [],
|
fullTextIndexes: [],
|
||||||
fullTextPolicyValidated: true,
|
fullTextPolicyValidated: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.showFullTextSearch = userContext.apiType === "SQL";
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
@@ -266,7 +265,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
|
|
||||||
<div className="panelMainContent">
|
<div className="panelMainContent">
|
||||||
{!(isFabricNative() && this.props.databaseId !== undefined) && (
|
{!(isFabricNative() && this.props.databaseId !== undefined) && (
|
||||||
<Stack hidden={userContext.apiType === "Tables"}>
|
<Stack hidden={userContext.apiType === "Tables"} style={{ marginBottom: -2 }}>
|
||||||
<Stack horizontal>
|
<Stack horizontal>
|
||||||
<span className="mandatoryStar">* </span>
|
<span className="mandatoryStar">* </span>
|
||||||
<Text className="panelTextBold" variant="small">
|
<Text className="panelTextBold" variant="small">
|
||||||
@@ -337,7 +336,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
size={40}
|
size={40}
|
||||||
className="panelTextField"
|
className="panelTextField"
|
||||||
aria-label="New database id, Type a new database id"
|
aria-label="New database id, Type a new database id"
|
||||||
autoFocus
|
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
value={this.state.newDatabaseId}
|
value={this.state.newDatabaseId}
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
@@ -408,12 +406,12 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
responsiveMode={999}
|
responsiveMode={999}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Separator className="panelSeparator" />
|
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
<Separator className="panelSeparator" style={{ marginTop: -4, marginBottom: -4 }} />
|
||||||
|
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack horizontal>
|
<Stack horizontal style={{ marginTop: -5, marginBottom: 1 }}>
|
||||||
<span className="mandatoryStar">* </span>
|
<span className="mandatoryStar">* </span>
|
||||||
<Text className="panelTextBold" variant="small">
|
<Text className="panelTextBold" variant="small">
|
||||||
{`${getCollectionName()} id`}
|
{`${getCollectionName()} id`}
|
||||||
@@ -451,10 +449,10 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<Separator className="panelSeparator" style={{ marginTop: -5, marginBottom: -5 }} />
|
||||||
{this.shouldShowIndexingOptionsForFreeTierAccount() && (
|
{this.shouldShowIndexingOptionsForFreeTierAccount() && (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack horizontal>
|
<Stack horizontal style={{ marginTop: -4, marginBottom: -5 }}>
|
||||||
<span className="mandatoryStar">* </span>
|
<span className="mandatoryStar">* </span>
|
||||||
<Text className="panelTextBold" variant="small">
|
<Text className="panelTextBold" variant="small">
|
||||||
Indexing
|
Indexing
|
||||||
@@ -500,7 +498,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
(!this.state.isSharedThroughputChecked ||
|
(!this.state.isSharedThroughputChecked ||
|
||||||
this.props.explorer.isFixedCollectionWithSharedThroughputSupported()) && (
|
this.props.explorer.isFixedCollectionWithSharedThroughputSupported()) && (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack horizontal>
|
<Stack horizontal style={{ marginTop: -5, marginBottom: -4 }}>
|
||||||
<span className="mandatoryStar">* </span>
|
<span className="mandatoryStar">* </span>
|
||||||
<Text className="panelTextBold" variant="small">
|
<Text className="panelTextBold" variant="small">
|
||||||
Sharding
|
Sharding
|
||||||
@@ -556,7 +554,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
|
|
||||||
{this.state.isSharded && (
|
{this.state.isSharded && (
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack horizontal>
|
<Stack horizontal style={{ marginTop: -5, marginBottom: -4 }}>
|
||||||
<span className="mandatoryStar">* </span>
|
<span className="mandatoryStar">* </span>
|
||||||
<Text className="panelTextBold" variant="small">
|
<Text className="panelTextBold" variant="small">
|
||||||
{getPartitionKeyName()}
|
{getPartitionKeyName()}
|
||||||
@@ -600,7 +598,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
{userContext.apiType === "SQL" &&
|
{userContext.apiType === "SQL" &&
|
||||||
this.state.subPartitionKeys.map((subPartitionKey: string, index: number) => {
|
this.state.subPartitionKeys.map((subPartitionKey: string, index: number) => {
|
||||||
return (
|
return (
|
||||||
<Stack style={{ marginBottom: 8 }} key={`uniqueKey${index}`} horizontal>
|
<Stack style={{ marginBottom: 2, marginTop: -5 }} key={`uniqueKey${index}`} horizontal>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: "20px",
|
width: "20px",
|
||||||
@@ -668,6 +666,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
<Separator className="panelSeparator" style={{ marginTop: 2, marginBottom: -4 }} />
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -728,7 +727,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{!isFabricNative() && userContext.apiType === "SQL" && (
|
{!isFabricNative() && userContext.apiType === "SQL" && (
|
||||||
<Stack>
|
<Stack style={{ marginTop: -2, marginBottom: -4 }}>
|
||||||
{UniqueKeysHeader()}
|
{UniqueKeysHeader()}
|
||||||
{this.state.uniqueKeys.map((uniqueKey: string, i: number): JSX.Element => {
|
{this.state.uniqueKeys.map((uniqueKey: string, i: number): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
@@ -742,7 +741,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
: "Comma separated paths e.g. /firstName,/address/zipCode"
|
: "Comma separated paths e.g. /firstName,/address/zipCode"
|
||||||
}
|
}
|
||||||
className="panelTextField"
|
className="panelTextField"
|
||||||
autoFocus
|
|
||||||
value={uniqueKey}
|
value={uniqueKey}
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const uniqueKeys = this.state.uniqueKeys.map((uniqueKey: string, j: number) => {
|
const uniqueKeys = this.state.uniqueKeys.map((uniqueKey: string, j: number) => {
|
||||||
@@ -777,10 +775,12 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<Separator className="panelSeparator" style={{ marginTop: -15, marginBottom: -4 }} />
|
||||||
|
|
||||||
{shouldShowAnalyticalStoreOptions() && (
|
{shouldShowAnalyticalStoreOptions() && (
|
||||||
<Stack className="panelGroupSpacing">
|
<Stack className="panelGroupSpacing" style={{ marginTop: -4 }}>
|
||||||
<Text className="panelTextBold" variant="small">
|
<Text className="panelTextBold" variant="small">
|
||||||
{AnalyticalStorageContent()}
|
{AnalyticalStoreHeader()}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Stack horizontal verticalAlign="center">
|
<Stack horizontal verticalAlign="center">
|
||||||
@@ -821,7 +821,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
<Stack className="panelGroupSpacing">
|
<Stack className="panelGroupSpacing">
|
||||||
<Text variant="small">
|
<Text variant="small">
|
||||||
Azure Synapse Link is required for creating an analytical store{" "}
|
Azure Synapse Link is required for creating an analytical store{" "}
|
||||||
{getCollectionName().toLocaleLowerCase()}. Enable Synapse Link for this Cosmos DB account.{" "}
|
{getCollectionName().toLocaleLowerCase()}. Enable Synapse Link for this Cosmos DB account. <br />
|
||||||
<Link
|
<Link
|
||||||
href="https://aka.ms/cosmosdb-synapselink"
|
href="https://aka.ms/cosmosdb-synapselink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -1161,7 +1161,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private shouldShowFullTextSearchParameters() {
|
private shouldShowFullTextSearchParameters() {
|
||||||
return isFullTextSearchEnabled() && (isServerlessAccount() || this.shouldShowCollectionThroughputInput());
|
return !isFabricNative() && this.showFullTextSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseUniqueKeys(): DataModels.UniqueKeyPolicy {
|
private parseUniqueKeys(): DataModels.UniqueKeyPolicy {
|
||||||
@@ -1316,7 +1316,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.shouldShowFullTextSearchParameters()) {
|
if (this.showFullTextSearch) {
|
||||||
indexingPolicy.fullTextIndexes = this.state.fullTextIndexes;
|
indexingPolicy.fullTextIndexes = this.state.fullTextIndexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1350,7 +1350,12 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
let offerThroughput: number;
|
let offerThroughput: number;
|
||||||
let autoPilotMaxThroughput: number;
|
let autoPilotMaxThroughput: number;
|
||||||
|
|
||||||
if (databaseLevelThroughput) {
|
// Throughput
|
||||||
|
if (isFabricNative()) {
|
||||||
|
// Fabric Native accounts are always autoscale and have a fixed throughput of 1K
|
||||||
|
autoPilotMaxThroughput = AutoPilotUtils.autoPilotThroughput1K;
|
||||||
|
offerThroughput = undefined;
|
||||||
|
} else if (databaseLevelThroughput) {
|
||||||
if (this.state.createNewDatabase) {
|
if (this.state.createNewDatabase) {
|
||||||
if (this.isNewDatabaseAutoscale) {
|
if (this.isNewDatabaseAutoscale) {
|
||||||
autoPilotMaxThroughput = this.newDatabaseThroughput;
|
autoPilotMaxThroughput = this.newDatabaseThroughput;
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export function UniqueKeysHeader(): JSX.Element {
|
|||||||
"Unique keys provide developers with the ability to add a layer of data integrity to their database. By creating a unique key policy when a container is created, you ensure the uniqueness of one or more values per partition key.";
|
"Unique keys provide developers with the ability to add a layer of data integrity to their database. By creating a unique key policy when a container is created, you ensure the uniqueness of one or more values per partition key.";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack horizontal>
|
<Stack horizontal style={{ marginBottom: -2 }}>
|
||||||
<Text className="panelTextBold" variant="small">
|
<Text className="panelTextBold" variant="small">
|
||||||
Unique keys
|
Unique keys
|
||||||
</Text>
|
</Text>
|
||||||
@@ -98,6 +98,21 @@ export function shouldShowAnalyticalStoreOptions(): boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function AnalyticalStoreHeader(): JSX.Element {
|
||||||
|
const tooltipContent =
|
||||||
|
"Enable analytical store capability to perform near real-time analytics on your operational data, without impacting the performance of transactional workloads.";
|
||||||
|
return (
|
||||||
|
<Stack horizontal style={{ marginBottom: -2 }}>
|
||||||
|
<Text className="panelTextBold" variant="small">
|
||||||
|
Analytical Store
|
||||||
|
</Text>
|
||||||
|
<TooltipHost directionalHint={DirectionalHint.bottomLeftEdge} content={tooltipContent}>
|
||||||
|
<Icon iconName="Info" className="panelInfoIcon" tabIndex={0} ariaLabel={tooltipContent} />
|
||||||
|
</TooltipHost>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function AnalyticalStorageContent(): JSX.Element {
|
export function AnalyticalStorageContent(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Text variant="small">
|
<Text variant="small">
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
|||||||
>
|
>
|
||||||
<Stack
|
<Stack
|
||||||
hidden={false}
|
hidden={false}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": -2,
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Stack
|
<Stack
|
||||||
horizontal={true}
|
horizontal={true}
|
||||||
@@ -88,7 +93,6 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
|||||||
aria-label="New database id, Type a new database id"
|
aria-label="New database id, Type a new database id"
|
||||||
aria-required={true}
|
aria-required={true}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoFocus={true}
|
|
||||||
className="panelTextField"
|
className="panelTextField"
|
||||||
id="newDatabaseId"
|
id="newDatabaseId"
|
||||||
name="newDatabaseId"
|
name="newDatabaseId"
|
||||||
@@ -138,13 +142,25 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
|||||||
</StyledTooltipHostBase>
|
</StyledTooltipHostBase>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
</Stack>
|
||||||
<Separator
|
<Separator
|
||||||
className="panelSeparator"
|
className="panelSeparator"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": -4,
|
||||||
|
"marginTop": -4,
|
||||||
|
}
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack
|
<Stack
|
||||||
horizontal={true}
|
horizontal={true}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": 1,
|
||||||
|
"marginTop": -5,
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="mandatoryStar"
|
className="mandatoryStar"
|
||||||
@@ -187,9 +203,24 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
|||||||
value=""
|
value=""
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<Separator
|
||||||
|
className="panelSeparator"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": -5,
|
||||||
|
"marginTop": -5,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Stack
|
<Stack
|
||||||
horizontal={true}
|
horizontal={true}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": -4,
|
||||||
|
"marginTop": -5,
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="mandatoryStar"
|
className="mandatoryStar"
|
||||||
@@ -254,6 +285,15 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
|||||||
Add hierarchical partition key
|
Add hierarchical partition key
|
||||||
</CustomizedDefaultButton>
|
</CustomizedDefaultButton>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<Separator
|
||||||
|
className="panelSeparator"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": -4,
|
||||||
|
"marginTop": 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<ThroughputInput
|
<ThroughputInput
|
||||||
isDatabase={false}
|
isDatabase={false}
|
||||||
@@ -263,9 +303,21 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
|||||||
setIsThroughputCapExceeded={[Function]}
|
setIsThroughputCapExceeded={[Function]}
|
||||||
setThroughputValue={[Function]}
|
setThroughputValue={[Function]}
|
||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": -4,
|
||||||
|
"marginTop": -2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
<Stack
|
<Stack
|
||||||
horizontal={true}
|
horizontal={true}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": -2,
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
className="panelTextBold"
|
className="panelTextBold"
|
||||||
@@ -306,26 +358,53 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
|||||||
Add unique key
|
Add unique key
|
||||||
</CustomizedActionButton>
|
</CustomizedActionButton>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<Separator
|
||||||
|
className="panelSeparator"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": -4,
|
||||||
|
"marginTop": -15,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Stack
|
<Stack
|
||||||
className="panelGroupSpacing"
|
className="panelGroupSpacing"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginTop": -4,
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
className="panelTextBold"
|
className="panelTextBold"
|
||||||
variant="small"
|
variant="small"
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
horizontal={true}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"marginBottom": -2,
|
||||||
|
}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
|
className="panelTextBold"
|
||||||
variant="small"
|
variant="small"
|
||||||
>
|
>
|
||||||
Enable analytical store capability to perform near real-time analytics on your operational data, without impacting the performance of transactional workloads.
|
Analytical Store
|
||||||
|
|
||||||
<StyledLinkBase
|
|
||||||
aria-label="Learn more about analytical store."
|
|
||||||
href="https://aka.ms/analytical-store-overview"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
Learn more
|
|
||||||
</StyledLinkBase>
|
|
||||||
</Text>
|
</Text>
|
||||||
|
<StyledTooltipHostBase
|
||||||
|
content="Enable analytical store capability to perform near real-time analytics on your operational data, without impacting the performance of transactional workloads."
|
||||||
|
directionalHint={4}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
ariaLabel="Enable analytical store capability to perform near real-time analytics on your operational data, without impacting the performance of transactional workloads."
|
||||||
|
className="panelInfoIcon"
|
||||||
|
iconName="Info"
|
||||||
|
tabIndex={0}
|
||||||
|
/>
|
||||||
|
</StyledTooltipHostBase>
|
||||||
|
</Stack>
|
||||||
</Text>
|
</Text>
|
||||||
<Stack
|
<Stack
|
||||||
horizontal={true}
|
horizontal={true}
|
||||||
@@ -382,7 +461,7 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
|||||||
|
|
||||||
container
|
container
|
||||||
. Enable Synapse Link for this Cosmos DB account.
|
. Enable Synapse Link for this Cosmos DB account.
|
||||||
|
<br />
|
||||||
<StyledLinkBase
|
<StyledLinkBase
|
||||||
aria-label="Learn more about Azure Synapse Link."
|
aria-label="Learn more about Azure Synapse Link."
|
||||||
className="capacitycalculator-link"
|
className="capacitycalculator-link"
|
||||||
@@ -411,6 +490,44 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
|
|||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<Stack>
|
||||||
|
<CollapsibleSectionComponent
|
||||||
|
isExpandedByDefault={false}
|
||||||
|
onExpand={[Function]}
|
||||||
|
title="Container Full Text Search Policy"
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
id="collapsibleFullTextPolicySectionContent"
|
||||||
|
styles={
|
||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"position": "relative",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
styles={
|
||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"paddingLeft": 40,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FullTextPoliciesComponent
|
||||||
|
fullTextPolicy={
|
||||||
|
{
|
||||||
|
"defaultLanguage": "en-US",
|
||||||
|
"fullTextPaths": [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onFullTextPathChange={[Function]}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</CollapsibleSectionComponent>
|
||||||
|
</Stack>
|
||||||
<CollapsibleSectionComponent
|
<CollapsibleSectionComponent
|
||||||
isExpandedByDefault={false}
|
isExpandedByDefault={false}
|
||||||
onExpand={[Function]}
|
onExpand={[Function]}
|
||||||
|
|||||||
@@ -40,12 +40,12 @@ import { PanelInfoErrorComponent } from "Explorer/Panes/PanelInfoErrorComponent"
|
|||||||
import { PanelLoadingScreen } from "Explorer/Panes/PanelLoadingScreen";
|
import { PanelLoadingScreen } from "Explorer/Panes/PanelLoadingScreen";
|
||||||
import { useDatabases } from "Explorer/useDatabases";
|
import { useDatabases } from "Explorer/useDatabases";
|
||||||
import { useSidePanel } from "hooks/useSidePanel";
|
import { useSidePanel } from "hooks/useSidePanel";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { MutableRefObject, useEffect, useRef, useState } from "react";
|
||||||
import { CollectionCreation } from "Shared/Constants";
|
import { CollectionCreation } from "Shared/Constants";
|
||||||
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
|
||||||
import { userContext } from "UserContext";
|
import { userContext } from "UserContext";
|
||||||
import { isFullTextSearchEnabled, isServerlessAccount, isVectorSearchEnabled } from "Utils/CapabilityUtils";
|
import { isServerlessAccount, isVectorSearchEnabled } from "Utils/CapabilityUtils";
|
||||||
import { ValidCosmosDbIdDescription, ValidCosmosDbIdInputPattern } from "Utils/ValidationUtils";
|
import { ValidCosmosDbIdDescription, ValidCosmosDbIdInputPattern } from "Utils/ValidationUtils";
|
||||||
|
|
||||||
export interface AddGlobalSecondaryIndexPanelProps {
|
export interface AddGlobalSecondaryIndexPanelProps {
|
||||||
@@ -75,6 +75,8 @@ export const AddGlobalSecondaryIndexPanel = (props: AddGlobalSecondaryIndexPanel
|
|||||||
const [showErrorDetails, setShowErrorDetails] = useState<boolean>();
|
const [showErrorDetails, setShowErrorDetails] = useState<boolean>();
|
||||||
const [isExecuting, setIsExecuting] = useState<boolean>();
|
const [isExecuting, setIsExecuting] = useState<boolean>();
|
||||||
|
|
||||||
|
const showFullTextSearch: MutableRefObject<boolean> = useRef<boolean>(userContext.apiType === "SQL");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sourceContainerOptions: IDropdownOption[] = [];
|
const sourceContainerOptions: IDropdownOption[] = [];
|
||||||
useDatabases.getState().databases.forEach((database: Database) => {
|
useDatabases.getState().databases.forEach((database: Database) => {
|
||||||
@@ -140,10 +142,6 @@ export const AddGlobalSecondaryIndexPanel = (props: AddGlobalSecondaryIndexPanel
|
|||||||
return isVectorSearchEnabled() && (isServerlessAccount() || showCollectionThroughputInput());
|
return isVectorSearchEnabled() && (isServerlessAccount() || showCollectionThroughputInput());
|
||||||
};
|
};
|
||||||
|
|
||||||
const showFullTextSearchParameters = (): boolean => {
|
|
||||||
return isFullTextSearchEnabled() && (isServerlessAccount() || showCollectionThroughputInput());
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAnalyticalStorageTtl = (): number => {
|
const getAnalyticalStorageTtl = (): number => {
|
||||||
if (!isSynapseLinkEnabled()) {
|
if (!isSynapseLinkEnabled()) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -228,7 +226,7 @@ export const AddGlobalSecondaryIndexPanel = (props: AddGlobalSecondaryIndexPanel
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showFullTextSearchParameters()) {
|
if (showFullTextSearch) {
|
||||||
indexingPolicy.fullTextIndexes = fullTextIndexes;
|
indexingPolicy.fullTextIndexes = fullTextIndexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +385,7 @@ export const AddGlobalSecondaryIndexPanel = (props: AddGlobalSecondaryIndexPanel
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{showFullTextSearchParameters() && (
|
{showFullTextSearch && (
|
||||||
<FullTextSearchComponent
|
<FullTextSearchComponent
|
||||||
{...{ fullTextPolicy, setFullTextPolicy, setFullTextIndexes, setFullTextPolicyValidated }}
|
{...{ fullTextPolicy, setFullTextPolicy, setFullTextIndexes, setFullTextPolicyValidated }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -172,6 +172,17 @@ exports[`AddGlobalSecondaryIndexPanel render default panel 1`] = `
|
|||||||
}
|
}
|
||||||
setEnableAnalyticalStore={[Function]}
|
setEnableAnalyticalStore={[Function]}
|
||||||
/>
|
/>
|
||||||
|
<FullTextSearchComponent
|
||||||
|
fullTextPolicy={
|
||||||
|
{
|
||||||
|
"defaultLanguage": "en-US",
|
||||||
|
"fullTextPaths": [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setFullTextIndexes={[Function]}
|
||||||
|
setFullTextPolicy={[Function]}
|
||||||
|
setFullTextPolicyValidated={[Function]}
|
||||||
|
/>
|
||||||
<AdvancedComponent
|
<AdvancedComponent
|
||||||
setSubPartitionKeys={[Function]}
|
setSubPartitionKeys={[Function]}
|
||||||
setUseHashV1={[Function]}
|
setUseHashV1={[Function]}
|
||||||
|
|||||||
@@ -56,6 +56,14 @@
|
|||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.panelMainContent {
|
||||||
|
padding: 0 24px;
|
||||||
|
margin: 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panelHeader {
|
.panelHeader {
|
||||||
@@ -113,17 +121,21 @@
|
|||||||
.deleteCollectionFeedback {
|
.deleteCollectionFeedback {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addRemoveIcon {
|
.addRemoveIcon {
|
||||||
margin-left: 4px !important;
|
margin-left: 4px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addRemoveIconLabel {
|
.addRemoveIconLabel {
|
||||||
margin-top: 28px;
|
margin-top: 28px;
|
||||||
margin-left: 4px !important;
|
margin-left: 4px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addRemoveIcon [alt="editEntity"]:focus,
|
.addRemoveIcon [alt="editEntity"]:focus,
|
||||||
.addRemoveIconLabel [alt="editEntity"]:focus {
|
.addRemoveIconLabel [alt="editEntity"]:focus {
|
||||||
border: 1px dashed #605e5c;
|
border: 1px dashed #605e5c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addNewParamStyle {
|
.addNewParamStyle {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
margin-left: 5px !important;
|
margin-left: 5px !important;
|
||||||
@@ -133,50 +145,63 @@
|
|||||||
.panelGroupSpacing> :not(:last-child) {
|
.panelGroupSpacing> :not(:last-child) {
|
||||||
margin-bottom: @DefaultSpace;
|
margin-bottom: @DefaultSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fileUpload {
|
.fileUpload {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.customFileUpload {
|
.customFileUpload {
|
||||||
padding: 25px 0px 0px 10px;
|
padding: 25px 0px 0px 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fileIcon {
|
.fileIcon {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panelAddIconLabel {
|
.panelAddIconLabel {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
margin: 30px 0 0 10px;
|
margin: 30px 0 0 10px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panelAddIcon {
|
.panelAddIcon {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
margin: 30px 0 0 10px;
|
margin: 30px 0 0 10px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.removeIcon {
|
.removeIcon {
|
||||||
color: @InfoIconColor;
|
color: @InfoIconColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
.backImageIcon {
|
.backImageIcon {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[alt="back"]:focus {
|
[alt="back"]:focus {
|
||||||
border: 1px solid #605e5c;
|
border: 1px solid #605e5c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addEntityDatePicker {
|
.addEntityDatePicker {
|
||||||
max-width: 145px;
|
max-width: 145px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addEntityTextField {
|
.addEntityTextField {
|
||||||
width: 237px;
|
width: 237px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addButtonEntiy {
|
.addButtonEntiy {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-select-view {
|
.column-select-view {
|
||||||
margin: 20px 0px 0px 0px;
|
margin: 20px 0px 0px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panelSeparator::before {
|
.panelSeparator::before {
|
||||||
background-color: #edebe9;
|
background-color: #edebe9;
|
||||||
}
|
}
|
||||||
@@ -180,6 +180,11 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
|||||||
? LocalStorageUtility.getEntryNumber(StorageKey.MaxWaitTimeInSeconds)
|
? LocalStorageUtility.getEntryNumber(StorageKey.MaxWaitTimeInSeconds)
|
||||||
: Constants.Queries.DefaultMaxWaitTimeInSeconds,
|
: Constants.Queries.DefaultMaxWaitTimeInSeconds,
|
||||||
);
|
);
|
||||||
|
const [queryControlEnabled, setQueryControlEnabled] = useState<boolean>(
|
||||||
|
LocalStorageUtility.hasItem(StorageKey.QueryControlEnabled)
|
||||||
|
? LocalStorageUtility.getEntryString(StorageKey.QueryControlEnabled) === "true"
|
||||||
|
: false,
|
||||||
|
);
|
||||||
const [maxDegreeOfParallelism, setMaxDegreeOfParallelism] = useState<number>(
|
const [maxDegreeOfParallelism, setMaxDegreeOfParallelism] = useState<number>(
|
||||||
LocalStorageUtility.hasItem(StorageKey.MaxDegreeOfParellism)
|
LocalStorageUtility.hasItem(StorageKey.MaxDegreeOfParellism)
|
||||||
? LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism)
|
? LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism)
|
||||||
@@ -204,6 +209,7 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
|||||||
!isEmulator;
|
!isEmulator;
|
||||||
const shouldShowGraphAutoVizOption = userContext.apiType === "Gremlin" && !isEmulator;
|
const shouldShowGraphAutoVizOption = userContext.apiType === "Gremlin" && !isEmulator;
|
||||||
const shouldShowCrossPartitionOption = userContext.apiType !== "Gremlin" && !isEmulator;
|
const shouldShowCrossPartitionOption = userContext.apiType !== "Gremlin" && !isEmulator;
|
||||||
|
const shouldShowEnhancedQueryControl = userContext.apiType === "SQL";
|
||||||
const shouldShowParallelismOption = userContext.apiType !== "Gremlin" && !isEmulator;
|
const shouldShowParallelismOption = userContext.apiType !== "Gremlin" && !isEmulator;
|
||||||
const showEnableEntraIdRbac =
|
const showEnableEntraIdRbac =
|
||||||
isDataplaneRbacSupported(userContext.apiType) &&
|
isDataplaneRbacSupported(userContext.apiType) &&
|
||||||
@@ -381,6 +387,7 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
|||||||
LocalStorageUtility.setEntryNumber(StorageKey.MaxWaitTimeInSeconds, MaxWaitTimeInSeconds);
|
LocalStorageUtility.setEntryNumber(StorageKey.MaxWaitTimeInSeconds, MaxWaitTimeInSeconds);
|
||||||
LocalStorageUtility.setEntryString(StorageKey.ContainerPaginationEnabled, containerPaginationEnabled.toString());
|
LocalStorageUtility.setEntryString(StorageKey.ContainerPaginationEnabled, containerPaginationEnabled.toString());
|
||||||
LocalStorageUtility.setEntryString(StorageKey.IsCrossPartitionQueryEnabled, crossPartitionQueryEnabled.toString());
|
LocalStorageUtility.setEntryString(StorageKey.IsCrossPartitionQueryEnabled, crossPartitionQueryEnabled.toString());
|
||||||
|
LocalStorageUtility.setEntryString(StorageKey.QueryControlEnabled, queryControlEnabled.toString());
|
||||||
LocalStorageUtility.setEntryNumber(StorageKey.MaxDegreeOfParellism, maxDegreeOfParallelism);
|
LocalStorageUtility.setEntryNumber(StorageKey.MaxDegreeOfParellism, maxDegreeOfParallelism);
|
||||||
LocalStorageUtility.setEntryString(StorageKey.PriorityLevel, priorityLevel.toString());
|
LocalStorageUtility.setEntryString(StorageKey.PriorityLevel, priorityLevel.toString());
|
||||||
LocalStorageUtility.setEntryString(StorageKey.CopilotSampleDBEnabled, copilotSampleDBEnabled.toString());
|
LocalStorageUtility.setEntryString(StorageKey.CopilotSampleDBEnabled, copilotSampleDBEnabled.toString());
|
||||||
@@ -410,6 +417,7 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
|||||||
`Updated items per page setting to ${LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage)}`,
|
`Updated items per page setting to ${LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage)}`,
|
||||||
);
|
);
|
||||||
logConsoleInfo(`${crossPartitionQueryEnabled ? "Enabled" : "Disabled"} cross-partition query feed option`);
|
logConsoleInfo(`${crossPartitionQueryEnabled ? "Enabled" : "Disabled"} cross-partition query feed option`);
|
||||||
|
logConsoleInfo(`${queryControlEnabled ? "Enabled" : "Disabled"} query control option`);
|
||||||
logConsoleInfo(
|
logConsoleInfo(
|
||||||
`Updated the max degree of parallelism query feed option to ${LocalStorageUtility.getEntryNumber(
|
`Updated the max degree of parallelism query feed option to ${LocalStorageUtility.getEntryNumber(
|
||||||
StorageKey.MaxDegreeOfParellism,
|
StorageKey.MaxDegreeOfParellism,
|
||||||
@@ -760,7 +768,6 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
|||||||
)}
|
)}
|
||||||
</AccordionPanel>
|
</AccordionPanel>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|
||||||
<AccordionItem value="5">
|
<AccordionItem value="5">
|
||||||
<AccordionHeader>
|
<AccordionHeader>
|
||||||
<div className={styles.header}>RU Limit</div>
|
<div className={styles.header}>RU Limit</div>
|
||||||
@@ -943,6 +950,38 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
|
|||||||
</AccordionPanel>
|
</AccordionPanel>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
)}
|
)}
|
||||||
|
{shouldShowEnhancedQueryControl && (
|
||||||
|
<AccordionItem value="10">
|
||||||
|
<AccordionHeader>
|
||||||
|
<div className={styles.header}>Enhanced query control</div>
|
||||||
|
</AccordionHeader>
|
||||||
|
<AccordionPanel>
|
||||||
|
<div className={styles.settingsSectionContainer}>
|
||||||
|
<div className={styles.settingsSectionDescription}>
|
||||||
|
Query up to the max degree of parallelism.
|
||||||
|
<a
|
||||||
|
href="https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/performance-tips-query-sdk?tabs=v3&pivots=programming-language-nodejs#enhanced-query-control"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
Learn more{" "}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<Checkbox
|
||||||
|
styles={{
|
||||||
|
label: { padding: 0 },
|
||||||
|
}}
|
||||||
|
className="padding"
|
||||||
|
ariaLabel="EnableQueryControl"
|
||||||
|
checked={queryControlEnabled}
|
||||||
|
onChange={() => setQueryControlEnabled(!queryControlEnabled)}
|
||||||
|
label="Enable query control"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</AccordionPanel>
|
||||||
|
</AccordionItem>
|
||||||
|
)}
|
||||||
{shouldShowParallelismOption && (
|
{shouldShowParallelismOption && (
|
||||||
<AccordionItem value="10">
|
<AccordionItem value="10">
|
||||||
<AccordionHeader>
|
<AccordionHeader>
|
||||||
|
|||||||
@@ -495,6 +495,51 @@ exports[`Settings Pane should render Default properly 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
</AccordionPanel>
|
</AccordionPanel>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
<AccordionItem
|
||||||
|
value="10"
|
||||||
|
>
|
||||||
|
<AccordionHeader>
|
||||||
|
<div
|
||||||
|
className="___15c001r_0000000 fq02s40"
|
||||||
|
>
|
||||||
|
Enhanced query control
|
||||||
|
</div>
|
||||||
|
</AccordionHeader>
|
||||||
|
<AccordionPanel>
|
||||||
|
<div
|
||||||
|
className="___1dfa554_0000000 fo7qwa0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="___10gar1i_0000000 f1fow5ox f1ugzwwg"
|
||||||
|
>
|
||||||
|
Query up to the max degree of parallelism.
|
||||||
|
<a
|
||||||
|
href="https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/performance-tips-query-sdk?tabs=v3&pivots=programming-language-nodejs#enhanced-query-control"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
|
||||||
|
Learn more
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<StyledCheckboxBase
|
||||||
|
ariaLabel="EnableQueryControl"
|
||||||
|
checked={false}
|
||||||
|
className="padding"
|
||||||
|
label="Enable query control"
|
||||||
|
onChange={[Function]}
|
||||||
|
styles={
|
||||||
|
{
|
||||||
|
"label": {
|
||||||
|
"padding": 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</AccordionPanel>
|
||||||
|
</AccordionItem>
|
||||||
<AccordionItem
|
<AccordionItem
|
||||||
value="10"
|
value="10"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -48,7 +48,11 @@ const classNames = mergeStyleSets({
|
|||||||
warning: [{ color: theme.semanticColors.warningIcon }, iconClass],
|
warning: [{ color: theme.semanticColors.warningIcon }, iconClass],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const UploadItemsPane: FunctionComponent = () => {
|
export type UploadItemsPaneProps = {
|
||||||
|
onUpload?: (data: UploadDetailsRecord[]) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ onUpload }) => {
|
||||||
const [files, setFiles] = useState<FileList>();
|
const [files, setFiles] = useState<FileList>();
|
||||||
const [uploadFileData, setUploadFileData] = useState<UploadDetailsRecord[]>([]);
|
const [uploadFileData, setUploadFileData] = useState<UploadDetailsRecord[]>([]);
|
||||||
const [formError, setFormError] = useState<string>("");
|
const [formError, setFormError] = useState<string>("");
|
||||||
@@ -71,6 +75,8 @@ export const UploadItemsPane: FunctionComponent = () => {
|
|||||||
(uploadDetails) => {
|
(uploadDetails) => {
|
||||||
setUploadFileData(uploadDetails.data);
|
setUploadFileData(uploadDetails.data);
|
||||||
setFiles(undefined);
|
setFiles(undefined);
|
||||||
|
// Emit the upload details to the parent component
|
||||||
|
onUpload && onUpload(uploadDetails.data);
|
||||||
},
|
},
|
||||||
(error: Error) => {
|
(error: Error) => {
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
|
|||||||
@@ -30,6 +30,21 @@
|
|||||||
margin: 0px auto;
|
margin: 0px auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
.splashStackContainer {
|
||||||
|
.splashStackRow {
|
||||||
|
display: flex;
|
||||||
|
gap: 0 16px;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
width: 85% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mainButtonsContainer {
|
.mainButtonsContainer {
|
||||||
.flex-display();
|
.flex-display();
|
||||||
|
|||||||
@@ -126,8 +126,12 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
|||||||
useDatabases.getState().sampleDataResourceTokenCollection
|
useDatabases.getState().sampleDataResourceTokenCollection
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<Stack style={{ width: "66%", cursor: "pointer", margin: "40px auto" }} tokens={{ childrenGap: 16 }}>
|
<Stack
|
||||||
<Stack horizontal tokens={{ childrenGap: 16 }}>
|
className="splashStackContainer"
|
||||||
|
style={{ width: "66%", cursor: "pointer", margin: "40px auto" }}
|
||||||
|
tokens={{ childrenGap: 16 }}
|
||||||
|
>
|
||||||
|
<Stack className="splashStackRow" horizontal>
|
||||||
<SplashScreenButton
|
<SplashScreenButton
|
||||||
imgSrc={QuickStartIcon}
|
imgSrc={QuickStartIcon}
|
||||||
title={"Launch quick start"}
|
title={"Launch quick start"}
|
||||||
@@ -147,7 +151,7 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack horizontal tokens={{ childrenGap: 16 }}>
|
<Stack className="splashStackRow" horizontal>
|
||||||
{useQueryCopilot.getState().copilotEnabled && (
|
{useQueryCopilot.getState().copilotEnabled && (
|
||||||
<SplashScreenButton
|
<SplashScreenButton
|
||||||
imgSrc={CopilotIcon}
|
imgSrc={CopilotIcon}
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import { useDialog } from "Explorer/Controls/Dialog";
|
|||||||
import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
|
import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
|
||||||
import { InputDataList, InputDatalistDropdownOptionSection } from "Explorer/Controls/InputDataList/InputDataList";
|
import { InputDataList, InputDatalistDropdownOptionSection } from "Explorer/Controls/InputDataList/InputDataList";
|
||||||
import { ProgressModalDialog } from "Explorer/Controls/ProgressModalDialog";
|
import { ProgressModalDialog } from "Explorer/Controls/ProgressModalDialog";
|
||||||
import Explorer from "Explorer/Explorer";
|
|
||||||
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
||||||
import { querySampleDocuments, readSampleDocument } from "Explorer/QueryCopilot/QueryCopilotUtilities";
|
import { querySampleDocuments, readSampleDocument } from "Explorer/QueryCopilot/QueryCopilotUtilities";
|
||||||
import {
|
import {
|
||||||
@@ -64,7 +63,7 @@ import * as Logger from "../../../Common/Logger";
|
|||||||
import * as MongoProxyClient from "../../../Common/MongoProxyClient";
|
import * as MongoProxyClient from "../../../Common/MongoProxyClient";
|
||||||
import * as DataModels from "../../../Contracts/DataModels";
|
import * as DataModels from "../../../Contracts/DataModels";
|
||||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
import { CollectionBase } from "../../../Contracts/ViewModels";
|
import { CollectionBase, UploadDetailsRecord } from "../../../Contracts/ViewModels";
|
||||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import * as QueryUtils from "../../../Utils/QueryUtils";
|
import * as QueryUtils from "../../../Utils/QueryUtils";
|
||||||
import { defaultQueryFields, extractPartitionKeyValues } from "../../../Utils/QueryUtils";
|
import { defaultQueryFields, extractPartitionKeyValues } from "../../../Utils/QueryUtils";
|
||||||
@@ -309,7 +308,6 @@ type UiKeyboardEvent = (e: KeyboardEvent | React.SyntheticEvent<Element, Event>)
|
|||||||
|
|
||||||
// Export to expose to unit tests
|
// Export to expose to unit tests
|
||||||
export type ButtonsDependencies = {
|
export type ButtonsDependencies = {
|
||||||
_collection: ViewModels.CollectionBase;
|
|
||||||
selectedRows: Set<TableRowId>;
|
selectedRows: Set<TableRowId>;
|
||||||
editorState: ViewModels.DocumentExplorerState;
|
editorState: ViewModels.DocumentExplorerState;
|
||||||
isPreferredApiMongoDB: boolean;
|
isPreferredApiMongoDB: boolean;
|
||||||
@@ -320,26 +318,7 @@ export type ButtonsDependencies = {
|
|||||||
onSaveExistingDocumentClick: UiKeyboardEvent;
|
onSaveExistingDocumentClick: UiKeyboardEvent;
|
||||||
onRevertExistingDocumentClick: UiKeyboardEvent;
|
onRevertExistingDocumentClick: UiKeyboardEvent;
|
||||||
onDeleteExistingDocumentsClick: UiKeyboardEvent;
|
onDeleteExistingDocumentsClick: UiKeyboardEvent;
|
||||||
};
|
onUploadDocumentsClick: UiKeyboardEvent;
|
||||||
|
|
||||||
const createUploadButton = (container: Explorer): CommandButtonComponentProps => {
|
|
||||||
const label = "Upload Item";
|
|
||||||
return {
|
|
||||||
id: UPLOAD_BUTTON_ID,
|
|
||||||
iconSrc: UploadIcon,
|
|
||||||
iconAlt: label,
|
|
||||||
onCommandClick: () => {
|
|
||||||
const selectedCollection: ViewModels.Collection = useSelectedNode.getState().findSelectedCollection();
|
|
||||||
selectedCollection && container.openUploadItemsPane();
|
|
||||||
},
|
|
||||||
commandButtonLabel: label,
|
|
||||||
ariaLabel: label,
|
|
||||||
hasPopup: true,
|
|
||||||
disabled:
|
|
||||||
useSelectedNode.getState().isDatabaseNodeOrNoneSelected() ||
|
|
||||||
!useClientWriteEnabled.getState().clientWriteEnabled ||
|
|
||||||
useSelectedNode.getState().isQueryCopilotCollectionSelected(),
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Export to expose to unit tests
|
// Export to expose to unit tests
|
||||||
@@ -352,7 +331,6 @@ export const UPLOAD_BUTTON_ID = "uploadItemBtn";
|
|||||||
|
|
||||||
// Export to expose in unit tests
|
// Export to expose in unit tests
|
||||||
export const getTabsButtons = ({
|
export const getTabsButtons = ({
|
||||||
_collection,
|
|
||||||
selectedRows,
|
selectedRows,
|
||||||
editorState,
|
editorState,
|
||||||
isPreferredApiMongoDB,
|
isPreferredApiMongoDB,
|
||||||
@@ -363,6 +341,7 @@ export const getTabsButtons = ({
|
|||||||
onSaveExistingDocumentClick,
|
onSaveExistingDocumentClick,
|
||||||
onRevertExistingDocumentClick,
|
onRevertExistingDocumentClick,
|
||||||
onDeleteExistingDocumentsClick,
|
onDeleteExistingDocumentsClick,
|
||||||
|
onUploadDocumentsClick,
|
||||||
}: ButtonsDependencies): CommandButtonComponentProps[] => {
|
}: ButtonsDependencies): CommandButtonComponentProps[] => {
|
||||||
if (isFabric() && userContext.fabricContext?.isReadOnly) {
|
if (isFabric() && userContext.fabricContext?.isReadOnly) {
|
||||||
// All the following buttons require write access
|
// All the following buttons require write access
|
||||||
@@ -474,7 +453,20 @@ export const getTabsButtons = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isPreferredApiMongoDB) {
|
if (!isPreferredApiMongoDB) {
|
||||||
buttons.push(createUploadButton(_collection.container));
|
const label = "Upload Item";
|
||||||
|
buttons.push({
|
||||||
|
id: UPLOAD_BUTTON_ID,
|
||||||
|
iconSrc: UploadIcon,
|
||||||
|
iconAlt: label,
|
||||||
|
onCommandClick: onUploadDocumentsClick,
|
||||||
|
commandButtonLabel: label,
|
||||||
|
ariaLabel: label,
|
||||||
|
hasPopup: true,
|
||||||
|
disabled:
|
||||||
|
useSelectedNode.getState().isDatabaseNodeOrNoneSelected() ||
|
||||||
|
!useClientWriteEnabled.getState().clientWriteEnabled ||
|
||||||
|
useSelectedNode.getState().isQueryCopilotCollectionSelected(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return buttons;
|
return buttons;
|
||||||
@@ -679,6 +671,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
collection: CollectionBase;
|
collection: CollectionBase;
|
||||||
}>(undefined);
|
}>(undefined);
|
||||||
const [bulkDeleteMode, setBulkDeleteMode] = useState<"inProgress" | "completed" | "aborting" | "aborted">(undefined);
|
const [bulkDeleteMode, setBulkDeleteMode] = useState<"inProgress" | "completed" | "aborting" | "aborted">(undefined);
|
||||||
|
const [abortController, setAbortController] = useState<AbortController | undefined>(undefined);
|
||||||
|
|
||||||
const setKeyboardActions = useKeyboardActionGroup(KeyboardActionGroup.ACTIVE_TAB);
|
const setKeyboardActions = useKeyboardActionGroup(KeyboardActionGroup.ACTIVE_TAB);
|
||||||
|
|
||||||
@@ -706,13 +699,19 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (bulkDeleteProcess.pendingIds.length === 0 && bulkDeleteProcess.throttledIds.length === 0) {
|
||||||
(bulkDeleteProcess.pendingIds.length === 0 && bulkDeleteProcess.throttledIds.length === 0) ||
|
// Successfully deleted all documents
|
||||||
bulkDeleteMode === "aborting"
|
|
||||||
) {
|
|
||||||
// Successfully deleted all documents or operation was aborted
|
|
||||||
bulkDeleteOperation.onCompleted(bulkDeleteProcess.successfulIds);
|
bulkDeleteOperation.onCompleted(bulkDeleteProcess.successfulIds);
|
||||||
setBulkDeleteMode(bulkDeleteMode === "aborting" ? "aborted" : "completed");
|
setBulkDeleteMode("completed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bulkDeleteMode === "aborting") {
|
||||||
|
// Operation was aborted
|
||||||
|
abortController?.abort();
|
||||||
|
bulkDeleteOperation.onCompleted(bulkDeleteProcess.successfulIds);
|
||||||
|
setBulkDeleteMode("aborted");
|
||||||
|
setAbortController(undefined);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -720,8 +719,10 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
const newPendingIds = bulkDeleteProcess.pendingIds.concat(bulkDeleteProcess.throttledIds);
|
const newPendingIds = bulkDeleteProcess.pendingIds.concat(bulkDeleteProcess.throttledIds);
|
||||||
const timeout = bulkDeleteProcess.beforeExecuteMs || 0;
|
const timeout = bulkDeleteProcess.beforeExecuteMs || 0;
|
||||||
|
|
||||||
|
const ac = new AbortController();
|
||||||
|
setAbortController(ac);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
deleteNoSqlDocuments(bulkDeleteOperation.collection, [...newPendingIds])
|
deleteNoSqlDocuments(bulkDeleteOperation.collection, [...newPendingIds], ac.signal)
|
||||||
.then((deleteResult) => {
|
.then((deleteResult) => {
|
||||||
let retryAfterMilliseconds = 0;
|
let retryAfterMilliseconds = 0;
|
||||||
const newSuccessful: DocumentId[] = [];
|
const newSuccessful: DocumentId[] = [];
|
||||||
@@ -877,7 +878,6 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateNavbarWithTabsButtons(isTabActive, {
|
updateNavbarWithTabsButtons(isTabActive, {
|
||||||
_collection,
|
|
||||||
selectedRows,
|
selectedRows,
|
||||||
editorState,
|
editorState,
|
||||||
isPreferredApiMongoDB,
|
isPreferredApiMongoDB,
|
||||||
@@ -888,6 +888,7 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
onSaveExistingDocumentClick,
|
onSaveExistingDocumentClick,
|
||||||
onRevertExistingDocumentClick,
|
onRevertExistingDocumentClick,
|
||||||
onDeleteExistingDocumentsClick,
|
onDeleteExistingDocumentsClick,
|
||||||
|
onUploadDocumentsClick,
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -1293,24 +1294,47 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
);
|
);
|
||||||
}, [deleteDocuments, documentIds, isPreferredApiMongoDB, selectedRows]);
|
}, [deleteDocuments, documentIds, isPreferredApiMongoDB, selectedRows]);
|
||||||
|
|
||||||
|
const onUploadDocumentsClick = useCallback((): void => {
|
||||||
|
if (!isPreferredApiMongoDB) {
|
||||||
|
const onSuccessUpload = (data: UploadDetailsRecord[]) => {
|
||||||
|
const addedIdsSet = new Set(
|
||||||
|
data
|
||||||
|
.reduce(
|
||||||
|
(result: ItemDefinition[], record) =>
|
||||||
|
result.concat(record.resources && record.resources.length ? record.resources : []),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
.map((document) => {
|
||||||
|
const partitionKeyValueArray: PartitionKey[] = extractPartitionKeyValues(
|
||||||
|
document,
|
||||||
|
partitionKey as PartitionKeyDefinition,
|
||||||
|
);
|
||||||
|
return newDocumentId(
|
||||||
|
document as ItemDefinition & Resource,
|
||||||
|
partitionKeyProperties,
|
||||||
|
partitionKeyValueArray as string[],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const documents = new Set(documentIds);
|
||||||
|
addedIdsSet.forEach((item) => documents.add(item));
|
||||||
|
setDocumentIds(Array.from(documents));
|
||||||
|
|
||||||
|
setSelectedDocumentContent(undefined);
|
||||||
|
setClickedRowIndex(undefined);
|
||||||
|
setSelectedRows(new Set());
|
||||||
|
setEditorState(ViewModels.DocumentExplorerState.noDocumentSelected);
|
||||||
|
};
|
||||||
|
|
||||||
|
_collection.container.openUploadItemsPane(onSuccessUpload);
|
||||||
|
}
|
||||||
|
}, [_collection.container, documentIds, isPreferredApiMongoDB, newDocumentId, partitionKey, partitionKeyProperties]);
|
||||||
|
|
||||||
// If editor state changes, update the nav
|
// If editor state changes, update the nav
|
||||||
useEffect(
|
useEffect(
|
||||||
() =>
|
() =>
|
||||||
updateNavbarWithTabsButtons(isTabActive, {
|
updateNavbarWithTabsButtons(isTabActive, {
|
||||||
_collection,
|
|
||||||
selectedRows,
|
|
||||||
editorState,
|
|
||||||
isPreferredApiMongoDB,
|
|
||||||
clientWriteEnabled,
|
|
||||||
onNewDocumentClick,
|
|
||||||
onSaveNewDocumentClick,
|
|
||||||
onRevertNewDocumentClick,
|
|
||||||
onSaveExistingDocumentClick,
|
|
||||||
onRevertExistingDocumentClick: onRevertExistingDocumentClick,
|
|
||||||
onDeleteExistingDocumentsClick: onDeleteExistingDocumentsClick,
|
|
||||||
}),
|
|
||||||
[
|
|
||||||
_collection,
|
|
||||||
selectedRows,
|
selectedRows,
|
||||||
editorState,
|
editorState,
|
||||||
isPreferredApiMongoDB,
|
isPreferredApiMongoDB,
|
||||||
@@ -1321,6 +1345,20 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
|||||||
onSaveExistingDocumentClick,
|
onSaveExistingDocumentClick,
|
||||||
onRevertExistingDocumentClick,
|
onRevertExistingDocumentClick,
|
||||||
onDeleteExistingDocumentsClick,
|
onDeleteExistingDocumentsClick,
|
||||||
|
onUploadDocumentsClick,
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
selectedRows,
|
||||||
|
editorState,
|
||||||
|
isPreferredApiMongoDB,
|
||||||
|
clientWriteEnabled,
|
||||||
|
onNewDocumentClick,
|
||||||
|
onSaveNewDocumentClick,
|
||||||
|
onRevertNewDocumentClick,
|
||||||
|
onSaveExistingDocumentClick,
|
||||||
|
onRevertExistingDocumentClick,
|
||||||
|
onDeleteExistingDocumentsClick,
|
||||||
|
onUploadDocumentsClick,
|
||||||
isTabActive,
|
isTabActive,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import { FeedOptions, QueryOperationOptions } from "@azure/cosmos";
|
import { FeedOptions } from "@azure/cosmos";
|
||||||
import { AuthType } from "AuthType";
|
import { AuthType } from "AuthType";
|
||||||
import QueryError, { createMonacoErrorLocationResolver, createMonacoMarkersForQueryErrors } from "Common/QueryError";
|
import QueryError, { createMonacoErrorLocationResolver, createMonacoMarkersForQueryErrors } from "Common/QueryError";
|
||||||
import { SplitterDirection } from "Common/Splitter";
|
import { SplitterDirection } from "Common/Splitter";
|
||||||
@@ -19,7 +19,7 @@ import { CosmosFluentProvider } from "Explorer/Theme/ThemeUtil";
|
|||||||
import { useSelectedNode } from "Explorer/useSelectedNode";
|
import { useSelectedNode } from "Explorer/useSelectedNode";
|
||||||
import { KeyboardAction } from "KeyboardShortcuts";
|
import { KeyboardAction } from "KeyboardShortcuts";
|
||||||
import { QueryConstants } from "Shared/Constants";
|
import { QueryConstants } from "Shared/Constants";
|
||||||
import { LocalStorageUtility, StorageKey, getRUThreshold, ruThresholdEnabled } from "Shared/StorageUtility";
|
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||||
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||||
import { Allotment } from "allotment";
|
import { Allotment } from "allotment";
|
||||||
import { useClientWriteEnabled } from "hooks/useClientWriteEnabled";
|
import { useClientWriteEnabled } from "hooks/useClientWriteEnabled";
|
||||||
@@ -369,22 +369,9 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
this.setState({
|
this.setState({
|
||||||
isExecutionError: false,
|
isExecutionError: false,
|
||||||
});
|
});
|
||||||
|
this.props.tabsBaseInstance.isExecutionWarning(false);
|
||||||
let queryOperationOptions: QueryOperationOptions;
|
|
||||||
if (userContext.apiType === "SQL" && ruThresholdEnabled()) {
|
|
||||||
const ruThreshold: number = getRUThreshold();
|
|
||||||
queryOperationOptions = {
|
|
||||||
ruCapPerOperation: ruThreshold,
|
|
||||||
} as QueryOperationOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryDocuments = async (firstItemIndex: number) =>
|
const queryDocuments = async (firstItemIndex: number) =>
|
||||||
await queryDocumentsPage(
|
await queryDocumentsPage(this.props.collection && this.props.collection.id(), this._iterator, firstItemIndex);
|
||||||
this.props.collection && this.props.collection.id(),
|
|
||||||
this._iterator,
|
|
||||||
firstItemIndex,
|
|
||||||
queryOperationOptions,
|
|
||||||
);
|
|
||||||
this.props.tabsBaseInstance.isExecuting(true);
|
this.props.tabsBaseInstance.isExecuting(true);
|
||||||
this.setState({
|
this.setState({
|
||||||
isExecuting: true,
|
isExecuting: true,
|
||||||
@@ -424,6 +411,9 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
|
|||||||
firstItemIndex,
|
firstItemIndex,
|
||||||
queryDocuments,
|
queryDocuments,
|
||||||
);
|
);
|
||||||
|
if (queryResults.ruThresholdExceeded) {
|
||||||
|
this.props.tabsBaseInstance.isExecutionWarning(true);
|
||||||
|
}
|
||||||
this.setState({ queryResults, errors: [] });
|
this.setState({ queryResults, errors: [] });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.props.tabsBaseInstance.isExecutionError(true);
|
this.props.tabsBaseInstance.isExecutionError(true);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ enum ResultsTabs {
|
|||||||
|
|
||||||
const ResultsTab: React.FC<ResultsViewProps> = ({ queryResults, isMongoDB, executeQueryDocumentsPage }) => {
|
const ResultsTab: React.FC<ResultsViewProps> = ({ queryResults, isMongoDB, executeQueryDocumentsPage }) => {
|
||||||
const styles = useQueryTabStyles();
|
const styles = useQueryTabStyles();
|
||||||
|
/* eslint-disable react/prop-types */
|
||||||
const queryResultsString = queryResults
|
const queryResultsString = queryResults
|
||||||
? isMongoDB
|
? isMongoDB
|
||||||
? MongoUtility.tojson(queryResults.documents, undefined, false)
|
? MongoUtility.tojson(queryResults.documents, undefined, false)
|
||||||
@@ -47,6 +48,172 @@ const ResultsTab: React.FC<ResultsViewProps> = ({ queryResults, isMongoDB, execu
|
|||||||
await executeQueryDocumentsPage(firstItemIndex + itemCount - 1);
|
await executeQueryDocumentsPage(firstItemIndex + itemCount - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ExportResults: React.FC = () => {
|
||||||
|
const [showDropdown, setShowDropdown] = useState(false);
|
||||||
|
const dropdownRef = React.useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
||||||
|
setShowDropdown(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (showDropdown) {
|
||||||
|
document.addEventListener("mousedown", handleClickOutside);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("mousedown", handleClickOutside);
|
||||||
|
};
|
||||||
|
}, [showDropdown]);
|
||||||
|
|
||||||
|
const escapeCsvValue = (value: string): string => {
|
||||||
|
return `"${value.replace(/"/g, '""')}"`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatValueForCsv = (value: string | object): string => {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (typeof value === "object") {
|
||||||
|
return escapeCsvValue(JSON.stringify(value));
|
||||||
|
}
|
||||||
|
return escapeCsvValue(String(value));
|
||||||
|
};
|
||||||
|
|
||||||
|
const exportToCsv = () => {
|
||||||
|
try {
|
||||||
|
const allHeadersSet = new Set<string>();
|
||||||
|
queryResults.documents.forEach((doc) => {
|
||||||
|
Object.keys(doc).forEach((key) => allHeadersSet.add(key));
|
||||||
|
});
|
||||||
|
|
||||||
|
const allHeaders = Array.from(allHeadersSet);
|
||||||
|
const csvHeader = allHeaders.map(escapeCsvValue).join(",");
|
||||||
|
const csvData = queryResults.documents
|
||||||
|
.map((doc) =>
|
||||||
|
allHeaders.map((header) => (doc[header] !== undefined ? formatValueForCsv(doc[header]) : "")).join(","),
|
||||||
|
)
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
const csvContent = `sep=,\n${csvHeader}\n${csvData}`;
|
||||||
|
downloadFile(csvContent, "query-results.csv", "text/csv");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to export CSV:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const exportToJson = () => {
|
||||||
|
try {
|
||||||
|
downloadFile(queryResultsString, "query-results.json", "application/json");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to export JSON:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const downloadFile = (content: string, fileName: string, contentType: string) => {
|
||||||
|
const blob = new Blob([content], { type: contentType });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const downloadLink = document.createElement("a");
|
||||||
|
downloadLink.href = url;
|
||||||
|
downloadLink.download = fileName;
|
||||||
|
document.body.appendChild(downloadLink);
|
||||||
|
downloadLink.click();
|
||||||
|
document.body.removeChild(downloadLink);
|
||||||
|
setTimeout(() => URL.revokeObjectURL(url), 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExport = (format: "CSV" | "JSON") => {
|
||||||
|
setShowDropdown(false);
|
||||||
|
if (format === "CSV") {
|
||||||
|
exportToCsv();
|
||||||
|
} else {
|
||||||
|
exportToJson();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = (e: React.KeyboardEvent, format: "CSV" | "JSON") => {
|
||||||
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
|
e.preventDefault();
|
||||||
|
handleExport(format);
|
||||||
|
} else if (e.key === "Escape") {
|
||||||
|
setShowDropdown(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ position: "relative", display: "inline-block" }} ref={dropdownRef}>
|
||||||
|
<Button
|
||||||
|
onClick={() => setShowDropdown((v) => !v)}
|
||||||
|
size="small"
|
||||||
|
appearance="transparent"
|
||||||
|
icon={<ArrowDownloadRegular />}
|
||||||
|
title="Download Query Results"
|
||||||
|
aria-haspopup="listbox"
|
||||||
|
aria-expanded={showDropdown}
|
||||||
|
/>
|
||||||
|
{showDropdown && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
right: 0,
|
||||||
|
zIndex: 10,
|
||||||
|
background: "white",
|
||||||
|
border: "1px solid #ccc",
|
||||||
|
borderRadius: 2,
|
||||||
|
minWidth: 60,
|
||||||
|
boxShadow: "0 2px 8px rgba(0,0,0,0.15)",
|
||||||
|
marginTop: 4,
|
||||||
|
}}
|
||||||
|
role="listbox"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
width: "100%",
|
||||||
|
padding: "8px 16px",
|
||||||
|
background: "none",
|
||||||
|
border: "none",
|
||||||
|
textAlign: "left",
|
||||||
|
cursor: "pointer",
|
||||||
|
transition: "background 0.2s",
|
||||||
|
}}
|
||||||
|
onMouseOver={(e) => (e.currentTarget.style.background = "#f3f3f3")}
|
||||||
|
onMouseOut={(e) => (e.currentTarget.style.background = "none")}
|
||||||
|
onClick={() => handleExport("JSON")}
|
||||||
|
onKeyDown={(e) => handleKeyDown(e, "JSON")}
|
||||||
|
role="option"
|
||||||
|
tabIndex={0}
|
||||||
|
>
|
||||||
|
JSON
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
display: "block",
|
||||||
|
width: "100%",
|
||||||
|
padding: "8px 16px",
|
||||||
|
background: "none",
|
||||||
|
border: "none",
|
||||||
|
textAlign: "left",
|
||||||
|
cursor: "pointer",
|
||||||
|
transition: "background 0.2s",
|
||||||
|
}}
|
||||||
|
onMouseOver={(e) => (e.currentTarget.style.background = "#f3f3f3")}
|
||||||
|
onMouseOut={(e) => (e.currentTarget.style.background = "none")}
|
||||||
|
onClick={() => handleExport("CSV")}
|
||||||
|
onKeyDown={(e) => handleKeyDown(e, "CSV")}
|
||||||
|
role="option"
|
||||||
|
tabIndex={0}
|
||||||
|
>
|
||||||
|
CSV
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.queryResultsBar}>
|
<div className={styles.queryResultsBar}>
|
||||||
@@ -67,6 +234,7 @@ const ResultsTab: React.FC<ResultsViewProps> = ({ queryResults, isMongoDB, execu
|
|||||||
aria-label="Copy"
|
aria-label="Copy"
|
||||||
onClick={onClickCopyResults}
|
onClick={onClickCopyResults}
|
||||||
/>
|
/>
|
||||||
|
<ExportResults />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.queryResultsViewer}>
|
<div className={styles.queryResultsViewer}>
|
||||||
<EditorReact language={"json"} content={queryResultsString} isReadOnly={true} ariaLabel={"Query results"} />
|
<EditorReact language={"json"} content={queryResultsString} isReadOnly={true} ariaLabel={"Query results"} />
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import React, { MutableRefObject, useEffect, useRef, useState } from "react";
|
|||||||
import loadingIcon from "../../../images/circular_loader_black_16x16.gif";
|
import loadingIcon from "../../../images/circular_loader_black_16x16.gif";
|
||||||
import errorIcon from "../../../images/close-black.svg";
|
import errorIcon from "../../../images/close-black.svg";
|
||||||
import errorQuery from "../../../images/error_no_outline.svg";
|
import errorQuery from "../../../images/error_no_outline.svg";
|
||||||
|
import warningIconSvg from "../../../images/warning.svg";
|
||||||
import { useObservable } from "../../hooks/useObservable";
|
import { useObservable } from "../../hooks/useObservable";
|
||||||
import { ReactTabKind, useTabs } from "../../hooks/useTabs";
|
import { ReactTabKind, useTabs } from "../../hooks/useTabs";
|
||||||
import TabsBase from "./TabsBase";
|
import TabsBase from "./TabsBase";
|
||||||
@@ -117,6 +118,9 @@ function TabNav({ tab, active, tabKind }: { tab?: Tab; active: boolean; tabKind?
|
|||||||
>
|
>
|
||||||
<span className="statusIconContainer" style={{ width: tabKind === ReactTabKind.Home ? 0 : 18 }}>
|
<span className="statusIconContainer" style={{ width: tabKind === ReactTabKind.Home ? 0 : 18 }}>
|
||||||
{useObservable(tab?.isExecutionError || ko.observable(false)) && <ErrorIcon tab={tab} active={active} />}
|
{useObservable(tab?.isExecutionError || ko.observable(false)) && <ErrorIcon tab={tab} active={active} />}
|
||||||
|
{useObservable(tab?.isExecutionWarning || ko.observable(false)) && (
|
||||||
|
<WarningIcon tab={tab} active={active} />
|
||||||
|
)}
|
||||||
{isTabExecuting(tab, tabKind) && (
|
{isTabExecuting(tab, tabKind) && (
|
||||||
<img className="loadingIcon" title="Loading" src={loadingIcon} alt="Loading" />
|
<img className="loadingIcon" title="Loading" src={loadingIcon} alt="Loading" />
|
||||||
)}
|
)}
|
||||||
@@ -194,6 +198,20 @@ const ErrorIcon = ({ tab, active }: { tab: Tab; active: boolean }) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const WarningIcon = ({ tab, active }: { tab: Tab; active: boolean }) => (
|
||||||
|
<div
|
||||||
|
id="warningStatusIcon"
|
||||||
|
role="button"
|
||||||
|
title="Click to view more details"
|
||||||
|
tabIndex={active ? 0 : undefined}
|
||||||
|
className={active ? "actionsEnabled warningIconContainer" : "warningIconContainer"}
|
||||||
|
onClick={({ nativeEvent: e }) => tab.onErrorDetailsClick(undefined, e)}
|
||||||
|
onKeyPress={({ nativeEvent: e }) => tab.onErrorDetailsKeyPress(undefined, e)}
|
||||||
|
>
|
||||||
|
<img src={warningIconSvg} alt="Warning Icon" style={{ height: 15, marginBottom: 5 }} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
function TabPane({ tab, active }: { tab: Tab; active: boolean }) {
|
function TabPane({ tab, active }: { tab: Tab; active: boolean }) {
|
||||||
const ref = useRef<HTMLDivElement>();
|
const ref = useRef<HTMLDivElement>();
|
||||||
const attrs = {
|
const attrs = {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export default class TabsBase extends WaitsForTemplateViewModel {
|
|||||||
public tabTitle: ko.Observable<string>;
|
public tabTitle: ko.Observable<string>;
|
||||||
public tabPath: ko.Observable<string>;
|
public tabPath: ko.Observable<string>;
|
||||||
public isExecutionError = ko.observable(false);
|
public isExecutionError = ko.observable(false);
|
||||||
|
public isExecutionWarning = ko.observable(false);
|
||||||
public isExecuting = ko.observable(false);
|
public isExecuting = ko.observable(false);
|
||||||
protected _theme: string;
|
protected _theme: string;
|
||||||
public onLoadStartKey: number;
|
public onLoadStartKey: number;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { readTriggers } from "../../Common/dataAccess/readTriggers";
|
|||||||
import { readUserDefinedFunctions } from "../../Common/dataAccess/readUserDefinedFunctions";
|
import { readUserDefinedFunctions } from "../../Common/dataAccess/readUserDefinedFunctions";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { UploadDetailsRecord } from "../../Contracts/ViewModels";
|
import { BulkInsertResult, UploadDetailsRecord } from "../../Contracts/ViewModels";
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
@@ -1092,17 +1092,13 @@ export default class Collection implements ViewModels.Collection {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async bulkInsertDocuments(documents: JSONObject[]): Promise<{
|
public async bulkInsertDocuments(documents: JSONObject[]): Promise<BulkInsertResult> {
|
||||||
numSucceeded: number;
|
const stats: BulkInsertResult = {
|
||||||
numFailed: number;
|
|
||||||
numThrottled: number;
|
|
||||||
errors: string[];
|
|
||||||
}> {
|
|
||||||
const stats = {
|
|
||||||
numSucceeded: 0,
|
numSucceeded: 0,
|
||||||
numFailed: 0,
|
numFailed: 0,
|
||||||
numThrottled: 0,
|
numThrottled: 0,
|
||||||
errors: [] as string[],
|
errors: [] as string[],
|
||||||
|
resources: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const chunkSize = 100; // 100 is the max # of bulk operations the SDK currently accepts
|
const chunkSize = 100; // 100 is the max # of bulk operations the SDK currently accepts
|
||||||
@@ -1120,6 +1116,7 @@ export default class Collection implements ViewModels.Collection {
|
|||||||
responses.forEach((response, index) => {
|
responses.forEach((response, index) => {
|
||||||
if (response.statusCode === 201) {
|
if (response.statusCode === 201) {
|
||||||
stats.numSucceeded++;
|
stats.numSucceeded++;
|
||||||
|
stats.resources.push(response.resourceBody);
|
||||||
} else if (response.statusCode === 429) {
|
} else if (response.statusCode === 429) {
|
||||||
documentsToAttempt.push(attemptedDocuments[index]);
|
documentsToAttempt.push(attemptedDocuments[index]);
|
||||||
} else if (response.statusCode === 409) {
|
} else if (response.statusCode === 409) {
|
||||||
@@ -1152,18 +1149,22 @@ export default class Collection implements ViewModels.Collection {
|
|||||||
numFailed: 0,
|
numFailed: 0,
|
||||||
numThrottled: 0,
|
numThrottled: 0,
|
||||||
errors: [],
|
errors: [],
|
||||||
|
resources: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const parsedContent = JSON.parse(documentContent);
|
const parsedContent = JSON.parse(documentContent);
|
||||||
if (Array.isArray(parsedContent)) {
|
if (Array.isArray(parsedContent)) {
|
||||||
const { numSucceeded, numFailed, numThrottled, errors } = await this.bulkInsertDocuments(parsedContent);
|
const { numSucceeded, numFailed, numThrottled, errors, resources } =
|
||||||
|
await this.bulkInsertDocuments(parsedContent);
|
||||||
record.numSucceeded = numSucceeded;
|
record.numSucceeded = numSucceeded;
|
||||||
record.numFailed = numFailed;
|
record.numFailed = numFailed;
|
||||||
record.numThrottled = numThrottled;
|
record.numThrottled = numThrottled;
|
||||||
record.errors = errors;
|
record.errors = errors;
|
||||||
|
record.resources = record.resources.concat(resources);
|
||||||
} else {
|
} else {
|
||||||
await createDocument(this, parsedContent);
|
const resource = await createDocument(this, parsedContent);
|
||||||
|
record.resources.push(resource);
|
||||||
record.numSucceeded++;
|
record.numSucceeded++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export enum StorageKey {
|
|||||||
DatabaseAccountId,
|
DatabaseAccountId,
|
||||||
EncryptedKeyToken,
|
EncryptedKeyToken,
|
||||||
IsCrossPartitionQueryEnabled,
|
IsCrossPartitionQueryEnabled,
|
||||||
|
QueryControlEnabled,
|
||||||
MaxDegreeOfParellism,
|
MaxDegreeOfParellism,
|
||||||
IsGraphAutoVizDisabled,
|
IsGraphAutoVizDisabled,
|
||||||
TenantId,
|
TenantId,
|
||||||
|
|||||||
@@ -20,7 +20,3 @@ export const isServerlessAccount = (): boolean => {
|
|||||||
export const isVectorSearchEnabled = (): boolean => {
|
export const isVectorSearchEnabled = (): boolean => {
|
||||||
return userContext.apiType === "SQL" && isCapabilityEnabled(Constants.CapabilityNames.EnableNoSQLVectorSearch);
|
return userContext.apiType === "SQL" && isCapabilityEnabled(Constants.CapabilityNames.EnableNoSQLVectorSearch);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isFullTextSearchEnabled = (): boolean => {
|
|
||||||
return userContext.apiType === "SQL" && isCapabilityEnabled(Constants.CapabilityNames.EnableNoSQLFullTextSearch);
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ export function downloadItem(
|
|||||||
},
|
},
|
||||||
"Cancel",
|
"Cancel",
|
||||||
undefined,
|
undefined,
|
||||||
container.getDownloadModalConent(name),
|
container.getDownloadModalContent(name),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export async function downloadNotebookItem(
|
export async function downloadNotebookItem(
|
||||||
|
|||||||
@@ -23,3 +23,7 @@ export const logConsoleError = (msg: string): void => {
|
|||||||
export const logConsoleInfo = (msg: string): void => {
|
export const logConsoleInfo = (msg: string): void => {
|
||||||
log(ConsoleDataType.Info, msg);
|
log(ConsoleDataType.Info, msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const logConsoleWarning = (msg: string): void => {
|
||||||
|
log(ConsoleDataType.Warning, msg);
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { PartitionKey, PartitionKeyDefinition } from "@azure/cosmos";
|
import { PartitionKey, PartitionKeyDefinition } from "@azure/cosmos";
|
||||||
|
import { getRUThreshold, ruThresholdEnabled } from "Shared/StorageUtility";
|
||||||
|
import { userContext } from "UserContext";
|
||||||
|
import { logConsoleWarning } from "Utils/NotificationConsoleUtils";
|
||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
|
|
||||||
@@ -86,6 +89,18 @@ export const queryPagesUntilContentPresent = async (
|
|||||||
results.roundTrips = roundTrips;
|
results.roundTrips = roundTrips;
|
||||||
results.requestCharge = Number(results.requestCharge) + netRequestCharge;
|
results.requestCharge = Number(results.requestCharge) + netRequestCharge;
|
||||||
netRequestCharge = Number(results.requestCharge);
|
netRequestCharge = Number(results.requestCharge);
|
||||||
|
|
||||||
|
if (results.hasMoreResults && userContext.apiType === "SQL" && ruThresholdEnabled()) {
|
||||||
|
const ruThreshold: number = getRUThreshold();
|
||||||
|
if (netRequestCharge > ruThreshold) {
|
||||||
|
logConsoleWarning(
|
||||||
|
`Warning: Query has exceeded the Request Unit threshold of ${ruThreshold} RUs. Query results show only those documents returned before the threshold was exceeded`,
|
||||||
|
);
|
||||||
|
results.ruThresholdExceeded = true;
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const resultsMetadata = {
|
const resultsMetadata = {
|
||||||
hasMoreResults: results.hasMoreResults,
|
hasMoreResults: results.hasMoreResults,
|
||||||
itemCount: results.itemCount,
|
itemCount: results.itemCount,
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Lists the Cassandra keyspaces under an existing Azure Cosmos DB database account. */
|
/* Lists the Cassandra keyspaces under an existing Azure Cosmos DB database account. */
|
||||||
export async function listCassandraKeyspaces(
|
export async function listCassandraKeyspaces(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given database account and collection. */
|
/* Retrieves the metrics determined by the given filter for the given database account and collection. */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given collection, split by partition. */
|
/* Retrieves the metrics determined by the given filter for the given collection, split by partition. */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given collection and region, split by partition. */
|
/* Retrieves the metrics determined by the given filter for the given collection and region, split by partition. */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given database account, collection and region. */
|
/* Retrieves the metrics determined by the given filter for the given database account, collection and region. */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given database account and database. */
|
/* Retrieves the metrics determined by the given filter for the given database account and database. */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given database account and region. */
|
/* Retrieves the metrics determined by the given filter for the given database account and region. */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the properties of an existing Azure Cosmos DB database account. */
|
/* Retrieves the properties of an existing Azure Cosmos DB database account. */
|
||||||
export async function get(
|
export async function get(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Lists the graphs under an existing Azure Cosmos DB database account. */
|
/* Lists the graphs under an existing Azure Cosmos DB database account. */
|
||||||
export async function listGraphs(
|
export async function listGraphs(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Lists the Gremlin databases under an existing Azure Cosmos DB database account. */
|
/* Lists the Gremlin databases under an existing Azure Cosmos DB database account. */
|
||||||
export async function listGremlinDatabases(
|
export async function listGremlinDatabases(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* List Cosmos DB locations and their properties */
|
/* List Cosmos DB locations and their properties */
|
||||||
export async function list(subscriptionId: string): Promise<Types.LocationListResult | Types.CloudError> {
|
export async function list(subscriptionId: string): Promise<Types.LocationListResult | Types.CloudError> {
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Lists the MongoDB databases under an existing Azure Cosmos DB database account. */
|
/* Lists the MongoDB databases under an existing Azure Cosmos DB database account. */
|
||||||
export async function listMongoDBDatabases(
|
export async function listMongoDBDatabases(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Lists all of the available Cosmos DB Resource Provider operations. */
|
/* Lists all of the available Cosmos DB Resource Provider operations. */
|
||||||
export async function list(): Promise<Types.OperationListResult> {
|
export async function list(): Promise<Types.OperationListResult> {
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given partition key range id. */
|
/* Retrieves the metrics determined by the given filter for the given partition key range id. */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given partition key range id and region. */
|
/* Retrieves the metrics determined by the given filter for the given partition key range id and region. */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given database account. This url is only for PBS and Replication Latency data */
|
/* Retrieves the metrics determined by the given filter for the given database account. This url is only for PBS and Replication Latency data */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given account, source and target region. This url is only for PBS and Replication Latency data */
|
/* Retrieves the metrics determined by the given filter for the given account, source and target region. This url is only for PBS and Replication Latency data */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Retrieves the metrics determined by the given filter for the given account target region. This url is only for PBS and Replication Latency data */
|
/* Retrieves the metrics determined by the given filter for the given account target region. This url is only for PBS and Replication Latency data */
|
||||||
export async function listMetrics(
|
export async function listMetrics(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Lists the SQL databases under an existing Azure Cosmos DB database account. */
|
/* Lists the SQL databases under an existing Azure Cosmos DB database account. */
|
||||||
export async function listSqlDatabases(
|
export async function listSqlDatabases(
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { configContext } from "../../../../ConfigContext";
|
|
||||||
import { armRequest } from "../../request";
|
import { armRequest } from "../../request";
|
||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
const apiVersion = "2024-12-01-preview";
|
import { configContext } from "../../../../ConfigContext";
|
||||||
|
const apiVersion = "2025-05-01-preview";
|
||||||
|
|
||||||
/* Lists the Tables under an existing Azure Cosmos DB database account. */
|
/* Lists the Tables under an existing Azure Cosmos DB database account. */
|
||||||
export async function listTables(
|
export async function listTables(
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Run "npm run generateARMClients" to regenerate
|
Run "npm run generateARMClients" to regenerate
|
||||||
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
|
||||||
|
|
||||||
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
|
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2025-05-01-preview/cosmos-db.json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* The List operation response, that contains the client encryption keys and their properties. */
|
/* The List operation response, that contains the client encryption keys and their properties. */
|
||||||
@@ -580,6 +580,8 @@ export interface DatabaseAccountGetProperties {
|
|||||||
|
|
||||||
/* Flag to indicate enabling/disabling of Per-Region Per-partition autoscale Preview feature on the account */
|
/* Flag to indicate enabling/disabling of Per-Region Per-partition autoscale Preview feature on the account */
|
||||||
enablePerRegionPerPartitionAutoscale?: boolean;
|
enablePerRegionPerPartitionAutoscale?: boolean;
|
||||||
|
/* Flag to indicate if All Versions and Deletes Change feed feature is enabled on the account */
|
||||||
|
enableAllVersionsAndDeletesChangeFeed?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Properties to create and update Azure Cosmos DB database accounts. */
|
/* Properties to create and update Azure Cosmos DB database accounts. */
|
||||||
@@ -682,6 +684,8 @@ export interface DatabaseAccountCreateUpdateProperties {
|
|||||||
|
|
||||||
/* Flag to indicate enabling/disabling of Per-Region Per-partition autoscale Preview feature on the account */
|
/* Flag to indicate enabling/disabling of Per-Region Per-partition autoscale Preview feature on the account */
|
||||||
enablePerRegionPerPartitionAutoscale?: boolean;
|
enablePerRegionPerPartitionAutoscale?: boolean;
|
||||||
|
/* Flag to indicate if All Versions and Deletes Change feed feature is enabled on the account */
|
||||||
|
enableAllVersionsAndDeletesChangeFeed?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parameters to create and update Cosmos DB database accounts. */
|
/* Parameters to create and update Cosmos DB database accounts. */
|
||||||
@@ -787,6 +791,8 @@ export interface DatabaseAccountUpdateProperties {
|
|||||||
|
|
||||||
/* Flag to indicate enabling/disabling of Per-Region Per-partition autoscale Preview feature on the account */
|
/* Flag to indicate enabling/disabling of Per-Region Per-partition autoscale Preview feature on the account */
|
||||||
enablePerRegionPerPartitionAutoscale?: boolean;
|
enablePerRegionPerPartitionAutoscale?: boolean;
|
||||||
|
/* Flag to indicate if All Versions and Deletes Change feed feature is enabled on the account */
|
||||||
|
enableAllVersionsAndDeletesChangeFeed?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parameters for patching Azure Cosmos DB database account properties. */
|
/* Parameters for patching Azure Cosmos DB database account properties. */
|
||||||
@@ -1216,6 +1222,8 @@ export interface PhysicalPartitionThroughputInfoResource {
|
|||||||
id: string;
|
id: string;
|
||||||
/* Throughput of a physical partition */
|
/* Throughput of a physical partition */
|
||||||
throughput?: number;
|
throughput?: number;
|
||||||
|
/* Target throughput of a physical partition */
|
||||||
|
targetThroughput?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cosmos DB client encryption key resource object. */
|
/* Cosmos DB client encryption key resource object. */
|
||||||
@@ -1285,12 +1293,16 @@ export interface SqlContainerResource {
|
|||||||
/* The configuration for defining Materialized Views. This must be specified only for creating a Materialized View container. */
|
/* The configuration for defining Materialized Views. This must be specified only for creating a Materialized View container. */
|
||||||
materializedViewDefinition?: MaterializedViewDefinition;
|
materializedViewDefinition?: MaterializedViewDefinition;
|
||||||
|
|
||||||
|
/* Materialized Views defined on the container. */
|
||||||
|
materializedViews?: MaterializedViewDetails[];
|
||||||
|
|
||||||
/* List of computed properties */
|
/* List of computed properties */
|
||||||
computedProperties?: ComputedProperty[];
|
computedProperties?: ComputedProperty[];
|
||||||
|
|
||||||
/* The vector embedding policy for the container. */
|
/* The vector embedding policy for the container. */
|
||||||
vectorEmbeddingPolicy?: VectorEmbeddingPolicy;
|
vectorEmbeddingPolicy?: VectorEmbeddingPolicy;
|
||||||
|
|
||||||
|
/* The FullText policy for the container. */
|
||||||
fullTextPolicy?: FullTextPolicy;
|
fullTextPolicy?: FullTextPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1323,6 +1335,14 @@ export interface VectorEmbeddingPolicy {
|
|||||||
vectorEmbeddings?: VectorEmbedding[];
|
vectorEmbeddings?: VectorEmbedding[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cosmos DB FullText Policy */
|
||||||
|
export interface FullTextPolicy {
|
||||||
|
/* The default language for a full text paths. */
|
||||||
|
defaultLanguage?: string;
|
||||||
|
/* List of FullText Paths */
|
||||||
|
fullTextPaths?: FullTextPath[];
|
||||||
|
}
|
||||||
|
|
||||||
/* undocumented */
|
/* undocumented */
|
||||||
export interface ExcludedPath {
|
export interface ExcludedPath {
|
||||||
/* The path for which the indexing behavior applies to. Index paths typically start with root and end with wildcard (/path/*) */
|
/* The path for which the indexing behavior applies to. Index paths typically start with root and end with wildcard (/path/*) */
|
||||||
@@ -1361,7 +1381,7 @@ export interface VectorEmbedding {
|
|||||||
/* The path to the vector field in the document. */
|
/* The path to the vector field in the document. */
|
||||||
path: string;
|
path: string;
|
||||||
/* Indicates the data type of vector. */
|
/* Indicates the data type of vector. */
|
||||||
dataType: "float16" | "float32" | "uint8" | "int8";
|
dataType: "float32" | "uint8" | "int8";
|
||||||
|
|
||||||
/* The distance function to use for distance calculation in between vectors. */
|
/* The distance function to use for distance calculation in between vectors. */
|
||||||
distanceFunction: "euclidean" | "cosine" | "dotproduct";
|
distanceFunction: "euclidean" | "cosine" | "dotproduct";
|
||||||
@@ -1370,26 +1390,12 @@ export interface VectorEmbedding {
|
|||||||
dimensions: number;
|
dimensions: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FullTextPolicy {
|
/* Represents the full text path specification. */
|
||||||
/**
|
|
||||||
* The default language for the full text .
|
|
||||||
*/
|
|
||||||
defaultLanguage: string;
|
|
||||||
/**
|
|
||||||
* The paths to be indexed for full text search.
|
|
||||||
*/
|
|
||||||
fullTextPaths: FullTextPath[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FullTextPath {
|
export interface FullTextPath {
|
||||||
/**
|
/* The path to the full text field in the document. */
|
||||||
* The path to be indexed for full text search.
|
|
||||||
*/
|
|
||||||
path: string;
|
path: string;
|
||||||
/**
|
/* The language of the full text field in the document. */
|
||||||
* The language for the full text path.
|
language?: string;
|
||||||
*/
|
|
||||||
language: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* List of composite path */
|
/* List of composite path */
|
||||||
@@ -1493,6 +1499,14 @@ export interface MaterializedViewDefinition {
|
|||||||
definition: string;
|
definition: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* MaterializedViewDetails, contains Id & _rid fields of materialized view. */
|
||||||
|
export interface MaterializedViewDetails {
|
||||||
|
/* Id field of Materialized container. */
|
||||||
|
id?: string;
|
||||||
|
/* _rid field of Materialized container. */
|
||||||
|
_rid?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cosmos DB SQL storedProcedure resource object */
|
/* Cosmos DB SQL storedProcedure resource object */
|
||||||
export interface SqlStoredProcedureResource {
|
export interface SqlStoredProcedureResource {
|
||||||
/* Name of the Cosmos DB SQL storedProcedure */
|
/* Name of the Cosmos DB SQL storedProcedure */
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ import {
|
|||||||
getMsalInstance,
|
getMsalInstance,
|
||||||
} from "../Utils/AuthorizationUtils";
|
} from "../Utils/AuthorizationUtils";
|
||||||
import { isInvalidParentFrameOrigin, shouldProcessMessage } from "../Utils/MessageValidation";
|
import { isInvalidParentFrameOrigin, shouldProcessMessage } from "../Utils/MessageValidation";
|
||||||
import { getReadOnlyKeys, listKeys } from "../Utils/arm/generatedClients/cosmos/databaseAccounts";
|
import { get, getReadOnlyKeys, listKeys } from "../Utils/arm/generatedClients/cosmos/databaseAccounts";
|
||||||
|
import * as Types from "../Utils/arm/generatedClients/cosmos/types";
|
||||||
import { applyExplorerBindings } from "../applyExplorerBindings";
|
import { applyExplorerBindings } from "../applyExplorerBindings";
|
||||||
|
|
||||||
// This hook will create a new instance of Explorer.ts and bind it to the DOM
|
// This hook will create a new instance of Explorer.ts and bind it to the DOM
|
||||||
@@ -346,6 +347,14 @@ async function configureHostedWithAAD(config: AAD): Promise<Explorer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
// TO DO - Remove once we have ARG API support for enableMaterializedViews property
|
||||||
|
const databaseAccount: Types.DatabaseAccountGetResults = await get(
|
||||||
|
subscriptionId,
|
||||||
|
account.resourceGroup,
|
||||||
|
account.name,
|
||||||
|
);
|
||||||
|
config.databaseAccount.properties.enableMaterializedViews = databaseAccount.properties?.enableMaterializedViews;
|
||||||
|
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
databaseAccount: config.databaseAccount,
|
databaseAccount: config.databaseAccount,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export const useTabs: UseStore<TabsState> = create((set, get) => ({
|
|||||||
.forEach((tab) => tab.onCloseTabButtonClick()),
|
.forEach((tab) => tab.onCloseTabButtonClick()),
|
||||||
closeTab: (tab: TabsBase): void => {
|
closeTab: (tab: TabsBase): void => {
|
||||||
let tabIndex: number;
|
let tabIndex: number;
|
||||||
const { activeTab, openedTabs } = get();
|
const { activeTab, openedTabs, openedReactTabs } = get();
|
||||||
const updatedTabs = openedTabs.filter((openedTab, index) => {
|
const updatedTabs = openedTabs.filter((openedTab, index) => {
|
||||||
if (tab.tabId === openedTab.tabId) {
|
if (tab.tabId === openedTab.tabId) {
|
||||||
tabIndex = index;
|
tabIndex = index;
|
||||||
@@ -127,6 +127,10 @@ export const useTabs: UseStore<TabsState> = create((set, get) => ({
|
|||||||
|
|
||||||
set({ openedTabs: updatedTabs });
|
set({ openedTabs: updatedTabs });
|
||||||
|
|
||||||
|
if (updatedTabs.length === 0 && openedReactTabs.length > 0) {
|
||||||
|
set({ activeTab: undefined, activeReactTab: openedReactTabs[openedReactTabs.length - 1] });
|
||||||
|
}
|
||||||
|
|
||||||
get().persistTabsState();
|
get().persistTabsState();
|
||||||
},
|
},
|
||||||
closeAllNotebookTabs: (hardClose): void => {
|
closeAllNotebookTabs: (hardClose): void => {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ Results of this file should be checked into the repo.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// CHANGE THESE VALUES TO GENERATE NEW CLIENTS
|
// CHANGE THESE VALUES TO GENERATE NEW CLIENTS
|
||||||
const version = "2024-12-01-preview";
|
const version = "2025-05-01-preview";
|
||||||
/* The following are legal options for resourceName but you generally will only use cosmos:
|
/* The following are legal options for resourceName but you generally will only use cosmos:
|
||||||
"cosmos" | "managedCassandra" | "mongorbac" | "notebook" | "privateEndpointConnection" | "privateLinkResources" |
|
"cosmos" | "managedCassandra" | "mongorbac" | "notebook" | "privateEndpointConnection" | "privateLinkResources" |
|
||||||
"rbac" | "restorable" | "services" | "dataTransferService"
|
"rbac" | "restorable" | "services" | "dataTransferService"
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<clear />
|
<clear />
|
||||||
<add name="X-Xss-Protection" value="1; mode=block" />
|
<add name="X-Xss-Protection" value="1; mode=block" />
|
||||||
<add name="X-Content-Type-Options" value="nosniff" />
|
<add name="X-Content-Type-Options" value="nosniff" />
|
||||||
<add name="Content-Security-Policy" value="frame-src 'vscode:' frame-ancestors 'self' portal.azure.com *.portal.azure.com portal.azure.us portal.azure.cn portal.microsoftazure.de df.onecloud.azure-test.net *.fabric.microsoft.com *.powerbi.com *.analysis-df.windows.net dataexplorer-preview.azurewebsites.net" />
|
<add name="Content-Security-Policy" value="frame-ancestors 'self' portal.azure.com *.portal.azure.com portal.azure.us portal.azure.cn portal.microsoftazure.de df.onecloud.azure-test.net *.fabric.microsoft.com *.powerbi.com *.analysis-df.windows.net dataexplorer-preview.azurewebsites.net" />
|
||||||
</customHeaders>
|
</customHeaders>
|
||||||
<redirectHeaders>
|
<redirectHeaders>
|
||||||
<clear />
|
<clear />
|
||||||
|
|||||||
@@ -78,11 +78,18 @@ const typescriptRule = {
|
|||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const javascriptRule = {
|
||||||
|
test: /\.m?js$/,
|
||||||
|
resolve: {
|
||||||
|
fullySpecified: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
/** @type {(_env: Record<string, string>, argv: Record<string, unknown>) => import("webpack").Configuration} */
|
/** @type {(_env: Record<string, string>, argv: Record<string, unknown>) => import("webpack").Configuration} */
|
||||||
module.exports = function (_env = {}, argv = {}) {
|
module.exports = function (_env = {}, argv = {}) {
|
||||||
const mode = argv.mode || "development";
|
const mode = argv.mode || "development";
|
||||||
const rules = [fontRule, lessRule, imagesRule, cssRule, htmlRule, typescriptRule];
|
const rules = [fontRule, lessRule, imagesRule, cssRule, htmlRule, typescriptRule, javascriptRule];
|
||||||
const envVars = {
|
const envVars = {
|
||||||
GIT_SHA: gitSha,
|
GIT_SHA: gitSha,
|
||||||
PORT: process.env.PORT || "1234",
|
PORT: process.env.PORT || "1234",
|
||||||
|
|||||||
Reference in New Issue
Block a user