Compare commits

..

4 Commits

Author SHA1 Message Date
dependabot[bot]
246b3f1267 Bump react-redux from 7.1.3 to 8.1.1
Bumps [react-redux](https://github.com/reduxjs/react-redux) from 7.1.3 to 8.1.1.
- [Release notes](https://github.com/reduxjs/react-redux/releases)
- [Changelog](https://github.com/reduxjs/react-redux/blob/master/CHANGELOG.md)
- [Commits](https://github.com/reduxjs/react-redux/compare/v7.1.3...v8.1.1)

---
updated-dependencies:
- dependency-name: react-redux
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-21 23:37:17 +00:00
sindhuba
8092841ce5 Improve error message while deleting a collection (#1495) 2023-06-21 15:04:36 -07:00
vchske
4617fa9364 Update throughput settings tab with new elasticity properties (#1461)
* Adding RU thermometer to settings throughput tab

* Finalizing RU thermometer on throughput settings

* Updated snapshot

* Fixing formatting

* Fixing lint errors

* Rerun prettier

* Fixing Offer properties

* Fixing Types

* Updating ARM clients, and enabling new elasticity properties

* Updating snapshots

* Updating an issue caused by updating ARM client

* Latest changes based on feedback

* Fixing lint and unit tests

* Minor fix

* Minor text change

* Changed some formatting
2023-06-16 15:54:29 -07:00
victor-meng
a282ad9242 integrate copilot UI with backend (#1478) 2023-06-16 00:25:23 -07:00
52 changed files with 14304 additions and 1199 deletions

View File

@@ -37,7 +37,7 @@ module.exports = {
coverageThreshold: {
global: {
branches: 25,
functions: 25,
functions: 24,
lines: 28,
statements: 28,
},

200
package-lock.json generated
View File

@@ -93,7 +93,7 @@
"react-hotkeys": "2.0.0",
"react-i18next": "11.8.5",
"react-notification-system": "0.2.17",
"react-redux": "7.1.3",
"react-redux": "8.1.1",
"react-splitter-layout": "4.0.0",
"react-youtube": "9.0.1",
"redux": "4.0.4",
@@ -166,7 +166,7 @@
"jest-playwright-preset": "1.5.1",
"jest-trx-results-processor": "0.0.7",
"less": "3.8.1",
"less-loader": "11.1.3",
"less-loader": "4.1.0",
"less-vars-loader": "1.1.0",
"mini-css-extract-plugin": "2.1.0",
"monaco-editor-webpack-plugin": "1.7.0",
@@ -4229,9 +4229,9 @@
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/semver": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
"integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"optional": true,
"peer": true,
"dependencies": {
@@ -5578,9 +5578,9 @@
}
},
"node_modules/@octokit/core": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz",
"integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==",
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz",
"integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==",
"peer": true,
"dependencies": {
"@octokit/auth-token": "^3.0.0",
@@ -5693,9 +5693,9 @@
"integrity": "sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw=="
},
"node_modules/@octokit/request": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz",
"integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==",
"version": "6.2.8",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz",
"integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==",
"peer": true,
"dependencies": {
"@octokit/endpoint": "^7.0.0",
@@ -5957,9 +5957,9 @@
}
},
"node_modules/@octokit/types": {
"version": "9.3.1",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.1.tgz",
"integrity": "sha512-zfJzyXLHC42sWcn2kS+oZ/DRvFZBYCCbfInZtwp1Uopl1qh6pRg4NSP/wFX1xCOpXvEkctiG1sxlSlkZmzvxdw==",
"version": "9.3.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz",
"integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==",
"peer": true,
"dependencies": {
"@octokit/openapi-types": "^18.0.0"
@@ -6882,7 +6882,6 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"devOptional": true,
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
@@ -7357,6 +7356,11 @@
"resolved": "https://registry.npmjs.org/@types/ungap__url-search-params/-/ungap__url-search-params-0.1.0.tgz",
"integrity": "sha512-mTtzm7iHpnXk47opmJFNFB854RZD5lXpkkwsxnlCmz2x6MMpVYG3KbYlOAmW3+96dIvPNrD2a7qNLuKumTF2aA=="
},
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@types/uuid": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz",
@@ -7937,9 +7941,9 @@
}
},
"node_modules/acorn": {
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
"integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
"bin": {
"acorn": "bin/acorn"
},
@@ -22695,20 +22699,21 @@
}
},
"node_modules/less-loader": {
"version": "11.1.3",
"resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.3.tgz",
"integrity": "sha512-A5b7O8dH9xpxvkosNrP0dFp2i/dISOJa9WwGF3WJflfqIERE2ybxh1BFDj5CovC2+jCE4M354mk90hN6ziXlVw==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz",
"integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==",
"dev": true,
"engines": {
"node": ">= 14.15.0"
"dependencies": {
"clone": "^2.1.1",
"loader-utils": "^1.1.0",
"pify": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
"engines": {
"node": ">= 4.8 < 5.0.0 || >= 5.10"
},
"peerDependencies": {
"less": "^3.5.0 || ^4.0.0",
"webpack": "^5.0.0"
"less": "^2.3.1 || ^3.0.0",
"webpack": "^2.0.0 || ^3.0.0 || ^4.0.0"
}
},
"node_modules/less-vars-loader": {
@@ -25218,9 +25223,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.35.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.0.tgz",
"integrity": "sha512-muMXyPmIx/2DPrCHOD1H1ePT01o7OdKxKj2ebmCAYvqhUy+Y1bpal7B0rdoxros7YrXI294JT/DWw2LqyiqTPA==",
"version": "1.35.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz",
"integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
@@ -26525,30 +26530,48 @@
}
},
"node_modules/react-redux": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.1.3.tgz",
"integrity": "sha512-uI1wca+ECG9RoVkWQFF4jDMqmaw0/qnvaSvOoL/GA4dNxf6LoV8sUAcNDvE5NWKs4hFpn0t6wswNQnY3f7HT3w==",
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.1.tgz",
"integrity": "sha512-5W0QaKtEhj+3bC0Nj0NkqkhIv8gLADH/2kYFMTHxCVqQILiWzLv6MaLuV5wJU3BQEdHKzTfcvPN0WMS6SC1oyA==",
"dependencies": {
"@babel/runtime": "^7.5.5",
"hoist-non-react-statics": "^3.3.0",
"invariant": "^2.2.4",
"loose-envify": "^1.4.0",
"prop-types": "^15.7.2",
"react-is": "^16.9.0"
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"react": "^16.8.3",
"redux": "^2.0.0 || ^3.0.0 || ^4.0.0-0"
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0",
"react-native": ">=0.59",
"redux": "^4 || ^5.0.0-beta.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-redux/node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/react-splitter-layout": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/react-splitter-layout/-/react-splitter-layout-4.0.0.tgz",
@@ -30313,6 +30336,14 @@
"node": ">=0.10.0"
}
},
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
@@ -35449,9 +35480,9 @@
}
},
"semver": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
"integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
"version": "7.5.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
"integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"optional": true,
"peer": true,
"requires": {
@@ -36603,9 +36634,9 @@
"peer": true
},
"@octokit/core": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz",
"integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==",
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz",
"integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==",
"peer": true,
"requires": {
"@octokit/auth-token": "^3.0.0",
@@ -36707,9 +36738,9 @@
}
},
"@octokit/request": {
"version": "6.2.5",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz",
"integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==",
"version": "6.2.8",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz",
"integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==",
"peer": true,
"requires": {
"@octokit/endpoint": "^7.0.0",
@@ -36953,9 +36984,9 @@
}
},
"@octokit/types": {
"version": "9.3.1",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.1.tgz",
"integrity": "sha512-zfJzyXLHC42sWcn2kS+oZ/DRvFZBYCCbfInZtwp1Uopl1qh6pRg4NSP/wFX1xCOpXvEkctiG1sxlSlkZmzvxdw==",
"version": "9.3.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz",
"integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==",
"peer": true,
"requires": {
"@octokit/openapi-types": "^18.0.0"
@@ -37811,7 +37842,6 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"devOptional": true,
"requires": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
@@ -38255,6 +38285,11 @@
"resolved": "https://registry.npmjs.org/@types/ungap__url-search-params/-/ungap__url-search-params-0.1.0.tgz",
"integrity": "sha512-mTtzm7iHpnXk47opmJFNFB854RZD5lXpkkwsxnlCmz2x6MMpVYG3KbYlOAmW3+96dIvPNrD2a7qNLuKumTF2aA=="
},
"@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"@types/uuid": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz",
@@ -38693,9 +38728,9 @@
}
},
"acorn": {
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw=="
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
"integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ=="
},
"acorn-globals": {
"version": "4.3.4",
@@ -50310,11 +50345,15 @@
}
},
"less-loader": {
"version": "11.1.3",
"resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.3.tgz",
"integrity": "sha512-A5b7O8dH9xpxvkosNrP0dFp2i/dISOJa9WwGF3WJflfqIERE2ybxh1BFDj5CovC2+jCE4M354mk90hN6ziXlVw==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz",
"integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==",
"dev": true,
"requires": {}
"requires": {
"clone": "^2.1.1",
"loader-utils": "^1.1.0",
"pify": "^3.0.0"
}
},
"less-vars-loader": {
"version": "1.1.0",
@@ -52306,9 +52345,9 @@
}
},
"playwright-core": {
"version": "1.35.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.0.tgz",
"integrity": "sha512-muMXyPmIx/2DPrCHOD1H1ePT01o7OdKxKj2ebmCAYvqhUy+Y1bpal7B0rdoxros7YrXI294JT/DWw2LqyiqTPA==",
"version": "1.35.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz",
"integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==",
"dev": true
},
"plotly.js-cartesian-dist-min": {
@@ -53290,16 +53329,23 @@
}
},
"react-redux": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.1.3.tgz",
"integrity": "sha512-uI1wca+ECG9RoVkWQFF4jDMqmaw0/qnvaSvOoL/GA4dNxf6LoV8sUAcNDvE5NWKs4hFpn0t6wswNQnY3f7HT3w==",
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.1.tgz",
"integrity": "sha512-5W0QaKtEhj+3bC0Nj0NkqkhIv8gLADH/2kYFMTHxCVqQILiWzLv6MaLuV5wJU3BQEdHKzTfcvPN0WMS6SC1oyA==",
"requires": {
"@babel/runtime": "^7.5.5",
"hoist-non-react-statics": "^3.3.0",
"invariant": "^2.2.4",
"loose-envify": "^1.4.0",
"prop-types": "^15.7.2",
"react-is": "^16.9.0"
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"dependencies": {
"react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
}
}
},
"react-splitter-layout": {
@@ -56271,6 +56317,12 @@
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
},
"use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"requires": {}
},
"util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",

View File

@@ -89,7 +89,7 @@
"react-hotkeys": "2.0.0",
"react-i18next": "11.8.5",
"react-notification-system": "0.2.17",
"react-redux": "7.1.3",
"react-redux": "8.1.1",
"react-splitter-layout": "4.0.0",
"react-youtube": "9.0.1",
"redux": "4.0.4",
@@ -162,7 +162,7 @@
"jest-playwright-preset": "1.5.1",
"jest-trx-results-processor": "0.0.7",
"less": "3.8.1",
"less-loader": "11.1.3",
"less-loader": "4.1.0",
"less-vars-loader": "1.1.0",
"mini-css-extract-plugin": "2.1.0",
"monaco-editor-webpack-plugin": "1.7.0",
@@ -212,7 +212,7 @@
"strict:find": "node ./strict-null-checks/find.js",
"strict:add": "node ./strict-null-checks/auto-add.js",
"compile:fullStrict": "tsc -p ./tsconfig.json --strictNullChecks",
"generateARMClients": "npx ts-node --compiler-options '{\"module\":\"commonjs\"}' utils/armClientGenerator/generator.ts"
"generateARMClients": "npx ts-node utils/armClientGenerator/generator.ts"
},
"repository": {
"type": "git",

File diff suppressed because it is too large Load Diff

View File

@@ -431,3 +431,88 @@ export class JunoEndpoints {
export const QueryCopilotSampleDatabaseId = "CopilotSampleDb";
export const QueryCopilotSampleContainerId = "SampleContainer";
export const QueryCopilotSampleContainerSchema = {
product: {
sampleData: {
id: "de6fadec-0384-43c8-93ea-16c0170b5460",
name: "Premium Phone Mini (Red)",
price: 652.04,
category: "Electronics",
description:
"This Premium Phone Mini (Red) is designed by the company under agreement with the FCC, so we'd give it a pass in either direction, but no one should be using this handset without a compatible handset. All in all, this phone is one of the most affordable Android handsets out there at $100. Check them out.\n\n9. HTC One M9 4",
stock: 74,
countryOfOrigin: "Mexico",
firstAvailable: "2018-07-07 17:42:28",
priceHistory: [592.81],
customerRatings: [
{ username: "dannyhowell", stars: 1, date: "2022-03-12 17:01:23", verifiedUser: true },
{ username: "lindsay26", stars: 1, date: "2022-12-29 07:18:20", verifiedUser: false },
{ username: "smithmiguel", stars: 3, date: "2022-09-08 11:43:27", verifiedUser: false },
{ username: "julie07", stars: 3, date: "2021-03-14 23:54:10", verifiedUser: true },
{ username: "kelly93", stars: 3, date: "2022-11-05 12:45:43", verifiedUser: false },
{ username: "katherinereynolds", stars: 2, date: "2022-09-14 11:49:36", verifiedUser: false },
{ username: "chandlerkenneth", stars: 1, date: "2022-01-14 12:14:43", verifiedUser: true },
],
rareProperty: true,
},
schema: {
properties: {
id: {
type: "string",
},
name: {
type: "string",
},
price: {
type: "number",
},
category: {
type: "string",
},
description: {
type: "string",
},
stock: {
type: "number",
},
countryOfOrigin: {
type: "string",
},
firstAvailable: {
type: "string",
},
priceHistory: {
items: {
type: "number",
},
type: "array",
},
customerRatings: {
items: {
properties: {
username: {
type: "string",
},
stars: {
type: "number",
},
date: {
type: "string",
},
verifiedUser: {
type: "boolean",
},
},
type: "object",
},
type: "array",
},
rareProperty: {
type: "boolean",
},
},
type: "object",
},
},
};

View File

@@ -96,6 +96,14 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
? parseInt(resource.minimumThroughput)
: resource.minimumThroughput;
const autoscaleSettings = resource.autoscaleSettings;
const instantMaximumThroughput: number =
typeof resource.instantMaximumThroughput === "string"
? parseInt(resource.instantMaximumThroughput)
: resource.instantMaximumThroughput;
const softAllowedMaximumThroughput: number =
typeof resource.softAllowedMaximumThroughput === "string"
? parseInt(resource.softAllowedMaximumThroughput)
: resource.softAllowedMaximumThroughput;
if (autoscaleSettings) {
return {
@@ -104,6 +112,8 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
manualThroughput: undefined,
minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput,
softAllowedMaximumThroughput,
};
}
@@ -113,6 +123,8 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
manualThroughput: resource.throughput,
minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput,
softAllowedMaximumThroughput,
};
}

View File

@@ -68,6 +68,14 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
? parseInt(resource.minimumThroughput)
: resource.minimumThroughput;
const autoscaleSettings = resource.autoscaleSettings;
const instantMaximumThroughput: number =
typeof resource.instantMaximumThroughput === "string"
? parseInt(resource.instantMaximumThroughput)
: resource.instantMaximumThroughput;
const softAllowedMaximumThroughput: number =
typeof resource.softAllowedMaximumThroughput === "string"
? parseInt(resource.softAllowedMaximumThroughput)
: resource.softAllowedMaximumThroughput;
if (autoscaleSettings) {
return {
@@ -76,6 +84,8 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
manualThroughput: undefined,
minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput,
softAllowedMaximumThroughput,
};
}
@@ -85,6 +95,8 @@ const readDatabaseOfferWithARM = async (databaseId: string): Promise<Offer> => {
manualThroughput: resource.throughput,
minimumThroughput,
offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput,
softAllowedMaximumThroughput,
};
}

View File

@@ -1,8 +1,9 @@
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
import { CloudError, SqlStoredProcedureListResult } from "Utils/arm/generatedClients/cosmos/types";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { listSqlStoredProcedures } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { listSqlStoredProcedures } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
@@ -24,7 +25,13 @@ export async function readStoredProcedures(
databaseId,
collectionId
);
return rpResponse?.value?.map((sproc) => sproc.properties?.resource as StoredProcedureDefinition & Resource);
const listResult = rpResponse as SqlStoredProcedureListResult;
if (listResult) {
return listResult?.value?.map((sproc) => sproc.properties?.resource as StoredProcedureDefinition & Resource);
}
const cloudError = rpResponse as CloudError;
throw new Error(cloudError?.error?.message);
}
const response = await client()

View File

@@ -242,6 +242,8 @@ export interface Offer {
minimumThroughput: number | undefined;
offerDefinition?: SDKOfferDefinition;
offerReplacePending: boolean;
instantMaximumThroughput?: number;
softAllowedMaximumThroughput?: number;
}
export interface SDKOfferDefinition extends Resource {

View File

@@ -1,46 +1,29 @@
import { shallow } from "enzyme";
import React from "react";
import { IColumn, Text } from "@fluentui/react";
import {
getAutoPilotV3SpendElement,
getEstimatedSpendingElement,
manualToAutoscaleDisclaimerElement,
ttlWarning,
indexingPolicynUnsavedWarningMessage,
updateThroughputBeyondLimitWarningMessage,
updateThroughputDelayedApplyWarningMessage,
getThroughputApplyDelayedMessage,
getThroughputApplyShortDelayMessage,
getThroughputApplyLongDelayMessage,
getToolTipContainer,
conflictResolutionCustomToolTip,
changeFeedPolicyToolTip,
conflictResolutionLwwTooltip,
mongoIndexingPolicyDisclaimer,
mongoIndexingPolicyAADError,
mongoIndexTransformationRefreshingMessage,
renderMongoIndexTransformationRefreshMessage,
ManualEstimatedSpendingDisplayProps,
PriceBreakdown,
changeFeedPolicyToolTip,
conflictResolutionCustomToolTip,
conflictResolutionLwwTooltip,
getEstimatedSpendingElement,
getRuPriceBreakdown,
getThroughputApplyDelayedMessage,
getThroughputApplyLongDelayMessage,
getThroughputApplyShortDelayMessage,
getToolTipContainer,
indexingPolicynUnsavedWarningMessage,
manualToAutoscaleDisclaimerElement,
mongoIndexTransformationRefreshingMessage,
mongoIndexingPolicyAADError,
mongoIndexingPolicyDisclaimer,
renderMongoIndexTransformationRefreshMessage,
ttlWarning,
updateThroughputDelayedApplyWarningMessage,
} from "./SettingsRenderUtils";
class SettingsRenderUtilsTestComponent extends React.Component {
public render(): JSX.Element {
const estimatedSpendingColumns: IColumn[] = [
{ key: "costType", name: "", fieldName: "costType", minWidth: 100, maxWidth: 200, isResizable: true },
{ key: "hourly", name: "Hourly", fieldName: "hourly", minWidth: 100, maxWidth: 200, isResizable: true },
{ key: "daily", name: "Daily", fieldName: "daily", minWidth: 100, maxWidth: 200, isResizable: true },
{ key: "monthly", name: "Monthly", fieldName: "monthly", minWidth: 100, maxWidth: 200, isResizable: true },
];
const estimatedSpendingItems: ManualEstimatedSpendingDisplayProps[] = [
{
costType: <Text>Current Cost</Text>,
hourly: <Text>$ 1.02</Text>,
daily: <Text>$ 24.48</Text>,
monthly: <Text>$ 744.6</Text>,
},
];
const costElement: JSX.Element = <></>;
const priceBreakdown: PriceBreakdown = {
hourlyPrice: 1.02,
dailyPrice: 24.48,
@@ -52,17 +35,11 @@ class SettingsRenderUtilsTestComponent extends React.Component {
return (
<>
{getAutoPilotV3SpendElement(1000, false)}
{getAutoPilotV3SpendElement(undefined, false)}
{getAutoPilotV3SpendElement(1000, true)}
{getAutoPilotV3SpendElement(undefined, true)}
{getEstimatedSpendingElement(estimatedSpendingColumns, estimatedSpendingItems, 1000, 2, priceBreakdown, false)}
{getEstimatedSpendingElement(costElement, 1000, 2, priceBreakdown, false)}
{manualToAutoscaleDisclaimerElement}
{ttlWarning}
{indexingPolicynUnsavedWarningMessage}
{updateThroughputBeyondLimitWarningMessage}
{updateThroughputDelayedApplyWarningMessage}
{getThroughputApplyDelayedMessage(false, 1000, "RU/s", "sampleDb", "sampleCollection", 2000)}

View File

@@ -1,10 +1,7 @@
import {
DetailsList,
DetailsListLayoutMode,
DetailsRow,
ICheckboxStyles,
IChoiceGroupStyles,
IColumn,
IDetailsColumnStyles,
IDetailsListStyles,
IDetailsRowProps,
@@ -20,7 +17,6 @@ import {
Link,
MessageBar,
MessageBarType,
SelectionMode,
Spinner,
SpinnerSize,
Stack,
@@ -28,8 +24,7 @@ import {
} from "@fluentui/react";
import * as React from "react";
import { StyleConstants, Urls } from "../../../Common/Constants";
import { AutopilotDocumentation, hoursInAMonth } from "../../../Shared/Constants";
import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils";
import { hoursInAMonth } from "../../../Shared/Constants";
import {
computeRUUsagePriceHourly,
estimatedCostDisclaimer,
@@ -103,6 +98,10 @@ export const checkBoxAndInputStackProps: Partial<IStackProps> = {
tokens: { childrenGap: 10 },
};
export const relaxedSpacingStackProps: Partial<IStackProps> = {
tokens: { childrenGap: 20 },
};
export const toolTipLabelStackTokens: IStackTokens = {
childrenGap: 6,
};
@@ -174,41 +173,6 @@ export function onRenderRow(props: IDetailsRowProps): JSX.Element {
return <DetailsRow {...props} styles={transparentDetailsRowStyles} />;
}
export const getAutoPilotV3SpendElement = (
maxAutoPilotThroughputSet: number,
isDatabaseThroughput: boolean,
requestUnitsUsageCostElement?: JSX.Element
): JSX.Element => {
if (!maxAutoPilotThroughputSet) {
return <></>;
}
const resource: string = isDatabaseThroughput ? "database" : "container";
return (
<>
<Text>
Your {resource} throughput will automatically scale from{" "}
<b>
{AutoPilotUtils.getMinRUsBasedOnUserInput(maxAutoPilotThroughputSet)} RU/s (10% of max RU/s) -{" "}
{maxAutoPilotThroughputSet} RU/s
</b>{" "}
based on usage.
<br />
</Text>
{requestUnitsUsageCostElement}
<Text>
After the first {AutoPilotUtils.getStorageBasedOnUserInput(maxAutoPilotThroughputSet)} GB of data stored, the
max RU/s will be automatically upgraded based on the new storage value.
<Link href={AutopilotDocumentation.Url} target="_blank">
{" "}
Learn more
</Link>
.
</Text>
</>
);
};
export const getRuPriceBreakdown = (
throughput: number,
serverId: string,
@@ -238,8 +202,7 @@ export const getRuPriceBreakdown = (
};
export const getEstimatedSpendingElement = (
estimatedSpendingColumns: IColumn[],
estimatedSpendingItems: EstimatedSpendingDisplayProps[],
costElement: JSX.Element,
throughput: number,
numberOfRegions: number,
priceBreakdown: PriceBreakdown,
@@ -247,22 +210,25 @@ export const getEstimatedSpendingElement = (
): JSX.Element => {
const ruRange: string = isAutoscale ? throughput / 10 + " RU/s - " : "";
return (
<Stack {...addMongoIndexStackProps} styles={mediumWidthStackStyles}>
<DetailsList
disableSelectionZone
items={estimatedSpendingItems}
columns={estimatedSpendingColumns}
selectionMode={SelectionMode.none}
layoutMode={DetailsListLayoutMode.justified}
onRenderRow={onRenderRow}
/>
<Text id="throughputSpendElement">
({"regions: "} {numberOfRegions}, {ruRange}
{throughput} RU/s, {priceBreakdown.currencySign}
{priceBreakdown.pricePerRu}/RU)
</Text>
<Text>
<em>{estimatedCostDisclaimer}</em>
<Stack>
<Text style={{ fontWeight: 600 }}>Cost estimate*</Text>
{costElement}
<Text style={{ fontWeight: 600, marginTop: 15 }}>How we calculate this</Text>
<Stack id="throughputSpendElement" style={{ marginTop: 5 }}>
<span>
{numberOfRegions} region{numberOfRegions > 1 && <span>s</span>}
</span>
<span>
{ruRange}
{throughput} RU/s
</span>
<span>
{priceBreakdown.currencySign}
{priceBreakdown.pricePerRu}/RU
</span>
</Stack>
<Text style={{ marginTop: 15 }}>
<em>*{estimatedCostDisclaimer}</em>
</Text>
</Stack>
);
@@ -293,14 +259,6 @@ export const indexingPolicynUnsavedWarningMessage: JSX.Element = (
</Text>
);
export const updateThroughputBeyondLimitWarningMessage: JSX.Element = (
<Text styles={infoAndToolTipTextStyle} id="updateThroughputBeyondLimitWarningMessage">
You are about to request an increase in throughput beyond the pre-allocated capacity. The service will scale out and
increase throughput for the selected container. This operation will take 1-3 business days to complete. You can
track the status of this request in Notifications.
</Text>
);
export const updateThroughputDelayedApplyWarningMessage: JSX.Element = (
<Text styles={infoAndToolTipTextStyle} id="updateThroughputDelayedApplyWarningMessage">
You are about to request an increase in throughput beyond the pre-allocated capacity. This operation will take some
@@ -308,6 +266,61 @@ export const updateThroughputDelayedApplyWarningMessage: JSX.Element = (
</Text>
);
export const getUpdateThroughputBeyondInstantLimitMessage = (instantMaximumThroughput: number): JSX.Element => {
return (
<Text styles={infoAndToolTipTextStyle} id="updateThroughputDelayedApplyWarningMessage">
Scaling up will take 4-6 hours as it exceeds what Azure Cosmos DB can instantly support currently based on your
number of physical partitions. You can increase your throughput to {instantMaximumThroughput} instantly or proceed
with this value and wait until the scale-up is completed.
</Text>
);
};
export const getUpdateThroughputBeyondSupportLimitMessage = (
instantMaximumThroughput: number,
maximumThroughput: number
): JSX.Element => {
return (
<>
<Text styles={infoAndToolTipTextStyle} id="updateThroughputDelayedApplyWarningMessage">
Your request to increase throughput exceeds the pre-allocated capacity which may take longer than expected.
There are three options you can choose from to proceed:
</Text>
<ol style={{ fontSize: 14, color: "windowtext", marginTop: "5px" }}>
<li>You can instantly scale up to {instantMaximumThroughput} RU/s.</li>
{instantMaximumThroughput < maximumThroughput && (
<li>You can asynchronously scale up to any value under {maximumThroughput} RU/s in 4-6 hours.</li>
)}
<li>
Your current quota max is {maximumThroughput} RU/s. To go over this limit, you must request a quota increase
and the Azure Cosmos DB team will review.
<Link
href="https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/create-support-request-quota-increase"
target="_blank"
>
Learn more
</Link>
</li>
</ol>
</>
);
};
export const getUpdateThroughputBelowMinimumMessage = (minimum: number): JSX.Element => {
return (
<Text styles={infoAndToolTipTextStyle}>
You are not able to lower throughput below your current minimum of {minimum} RU/s. For more information on this
limit, please refer to our service quote documentation.
<Link
href="https://learn.microsoft.com/en-us/azure/cosmos-db/concepts-limits#minimum-throughput-limits"
target="_blank"
>
Learn more
</Link>
</Text>
);
};
export const saveThroughputWarningMessage: JSX.Element = (
<Text styles={infoAndToolTipTextStyle}>
Your bill will be affected as you update your throughput settings. Please review the updated cost estimate below
@@ -499,7 +512,11 @@ export const getTextFieldStyles = (current: isDirtyTypes, baseline: isDirtyTypes
},
});
export const getChoiceGroupStyles = (current: isDirtyTypes, baseline: isDirtyTypes): Partial<IChoiceGroupStyles> => ({
export const getChoiceGroupStyles = (
current: isDirtyTypes,
baseline: isDirtyTypes,
isHorizontal?: boolean
): Partial<IChoiceGroupStyles> => ({
flexContainer: [
{
selectors: {
@@ -516,6 +533,8 @@ export const getChoiceGroupStyles = (current: isDirtyTypes, baseline: isDirtyTyp
padding: "2px 5px",
},
},
display: isHorizontal ? "inline-flex" : "default",
columnGap: isHorizontal ? "30px" : "default",
},
],
});

View File

@@ -3,7 +3,6 @@ import ko from "knockout";
import React from "react";
import * as Constants from "../../../../Common/Constants";
import * as DataModels from "../../../../Contracts/DataModels";
import * as SharedConstants from "../../../../Shared/Constants";
import { updateUserContext } from "../../../../UserContext";
import Explorer from "../../../Explorer";
import { throughputUnit } from "../SettingsRenderUtils";
@@ -12,7 +11,6 @@ import { ScaleComponent, ScaleComponentProps } from "./ScaleComponent";
import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component";
describe("ScaleComponent", () => {
const nonNationalCloudContainer = new Explorer();
const targetThroughput = 6000;
const baseProps: ScaleComponentProps = {
@@ -125,11 +123,4 @@ describe("ScaleComponent", () => {
scaleComponent = new ScaleComponent(newProps);
expect(scaleComponent.canThroughputExceedMaximumValue()).toEqual(true);
});
it("getThroughputWarningMessage", () => {
const throughputBeyondLimit = SharedConstants.CollectionCreation.DefaultCollectionRUs1Million + 1000;
const newProps = { ...baseProps, container: nonNationalCloudContainer, throughput: throughputBeyondLimit };
const scaleComponent = new ScaleComponent(newProps);
expect(scaleComponent.getThroughputWarningMessage().props.id).toEqual("updateThroughputBeyondLimitWarningMessage");
});
});

View File

@@ -1,7 +1,7 @@
import { Label, Link, MessageBar, MessageBarType, Stack, Text, TextField } from "@fluentui/react";
import { Link, MessageBar, MessageBarType, Stack, Text, TextField } from "@fluentui/react";
import * as React from "react";
import * as Constants from "../../../../Common/Constants";
import { configContext, Platform } from "../../../../ConfigContext";
import { Platform, configContext } from "../../../../ConfigContext";
import * as DataModels from "../../../../Contracts/DataModels";
import * as ViewModels from "../../../../Contracts/ViewModels";
import * as SharedConstants from "../../../../Shared/Constants";
@@ -15,7 +15,6 @@ import {
subComponentStackProps,
throughputUnit,
titleAndInputStackProps,
updateThroughputBeyondLimitWarningMessage,
} from "../SettingsRenderUtils";
import { hasDatabaseSharedThroughput } from "../SettingsUtils";
import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component";
@@ -68,16 +67,6 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
return !!enableAutoScaleCapability;
};
private getStorageCapacityTitle = (): JSX.Element => {
const capacity: string = this.props.isFixedContainer ? "Fixed" : "Unlimited";
return (
<Stack {...titleAndInputStackProps}>
<Label>Storage capacity</Label>
<Text>{capacity}</Text>
</Stack>
);
};
public getMaxRUs = (): number => {
if (userContext.isTryCosmosDBSubscription) {
return Constants.TryCosmosExperience.maxRU;
@@ -131,18 +120,6 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
return undefined;
};
public getThroughputWarningMessage = (): JSX.Element => {
const throughputExceedsBackendLimits: boolean =
this.canThroughputExceedMaximumValue() &&
this.props.throughput > SharedConstants.CollectionCreation.DefaultCollectionRUs1Million;
if (throughputExceedsBackendLimits && !this.props.isFixedContainer) {
return updateThroughputBeyondLimitWarningMessage;
}
return undefined;
};
public getLongDelayMessage = (): JSX.Element => {
const matches: string[] = this.props.initialNotification?.description.match(
`Throughput update for (.*) ${throughputUnit}`
@@ -188,9 +165,10 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
spendAckChecked={false}
onScaleSaveableChange={this.props.onScaleSaveableChange}
onScaleDiscardableChange={this.props.onScaleDiscardableChange}
getThroughputWarningMessage={this.getThroughputWarningMessage}
usageSizeInKB={this.props.collection?.usageSizeInKB()}
throughputError={this.props.throughputError}
instantMaximumThroughput={this.offer?.instantMaximumThroughput}
softAllowedMaximumThroughput={this.offer?.softAllowedMaximumThroughput}
/>
);
@@ -229,12 +207,7 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
{this.getInitialNotificationElement() && (
<MessageBar messageBarType={MessageBarType.warning}>{this.getInitialNotificationElement()}</MessageBar>
)}
{!this.isAutoScaleEnabled() && (
<Stack {...subComponentStackProps}>
{this.getThroughputInputComponent()}
{!this.props.database && this.getStorageCapacityTitle()}
</Stack>
)}
{!this.isAutoScaleEnabled() && <Stack {...subComponentStackProps}>{this.getThroughputInputComponent()}</Stack>}
{/* TODO: Replace link with call to the Azure Support blade */}
{this.isAutoScaleEnabled() && (

View File

@@ -42,7 +42,8 @@ describe("ThroughputInputAutoPilotV3Component", () => {
onScaleDiscardableChange: () => {
return;
},
getThroughputWarningMessage: () => undefined,
instantMaximumThroughput: 5000,
softAllowedMaximumThroughput: 1000000,
};
it("throughput input visible", () => {

View File

@@ -3,10 +3,14 @@ import {
ChoiceGroup,
FontIcon,
IChoiceGroupOption,
IColumn,
IProgressIndicatorStyles,
ISeparatorStyles,
Label,
Link,
MessageBar,
MessageBarType,
ProgressIndicator,
Separator,
Stack,
Text,
TextField,
@@ -23,24 +27,24 @@ import { autoPilotThroughput1K } from "../../../../../Utils/AutoPilotUtils";
import { calculateEstimateNumber, usageInGB } from "../../../../../Utils/PricingUtils";
import { Int32 } from "../../../../Panes/Tables/Validators/EntityPropertyValidationCommon";
import {
AutoscaleEstimatedSpendingDisplayProps,
PriceBreakdown,
checkBoxAndInputStackProps,
getAutoPilotV3SpendElement,
getChoiceGroupStyles,
getEstimatedSpendingElement,
getRuPriceBreakdown,
getTextFieldStyles,
getToolTipContainer,
ManualEstimatedSpendingDisplayProps,
getUpdateThroughputBelowMinimumMessage,
getUpdateThroughputBeyondInstantLimitMessage,
getUpdateThroughputBeyondSupportLimitMessage,
manualToAutoscaleDisclaimerElement,
messageBarStyles,
noLeftPaddingCheckBoxStyle,
PriceBreakdown,
relaxedSpacingStackProps,
saveThroughputWarningMessage,
titleAndInputStackProps,
transparentDetailsHeaderStyle,
} from "../../SettingsRenderUtils";
import { getSanitizedInputValue, IsComponentDirtyResult, isDirty } from "../../SettingsUtils";
import { IsComponentDirtyResult, getSanitizedInputValue, isDirty } from "../../SettingsUtils";
import { ToolTipLabelComponent } from "../ToolTipLabelComponent";
export interface ThroughputInputAutoPilotV3Props {
@@ -73,9 +77,10 @@ export interface ThroughputInputAutoPilotV3Props {
onMaxAutoPilotThroughputChange: (newThroughput: number) => void;
onScaleSaveableChange: (isScaleSaveable: boolean) => void;
onScaleDiscardableChange: (isScaleDiscardable: boolean) => void;
getThroughputWarningMessage: () => JSX.Element;
usageSizeInKB: number;
throughputError?: string;
instantMaximumThroughput: number;
softAllowedMaximumThroughput: number;
}
interface ThroughputInputAutoPilotV3State {
@@ -127,7 +132,10 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
} else if (this.props.isAutoPilotSelected) {
if (isDirty(this.props.maxAutoPilotThroughput, this.props.maxAutoPilotThroughputBaseline)) {
isDiscardable = true;
if (AutoPilotUtils.isValidAutoPilotThroughput(this.props.maxAutoPilotThroughput)) {
if (
this.props.maxAutoPilotThroughput <= this.props.softAllowedMaximumThroughput &&
AutoPilotUtils.isValidAutoPilotThroughput(this.props.maxAutoPilotThroughput)
) {
isSaveable = true;
}
}
@@ -186,7 +194,15 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
let estimatedSpend: JSX.Element;
if (!this.props.isAutoPilotSelected) {
if (this.props.isAutoPilotSelected) {
estimatedSpend = this.getEstimatedAutoscaleSpendElement(
this.props.maxAutoPilotThroughputBaseline,
userContext.portalEnv,
regions,
multimaster,
isDirty ? this.props.maxAutoPilotThroughput : undefined
);
} else {
estimatedSpend = this.getEstimatedManualSpendElement(
// if migrating from autoscale to manual, we use the autoscale RUs value as that is what will be set...
this.overrideWithAutoPilotSettings() ? this.props.maxAutoPilotThroughput : this.props.throughputBaseline,
@@ -195,14 +211,6 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
multimaster,
isDirty ? this.props.throughput : undefined
);
} else {
estimatedSpend = this.getEstimatedAutoscaleSpendElement(
this.props.maxAutoPilotThroughputBaseline,
userContext.portalEnv,
regions,
multimaster,
isDirty ? this.props.maxAutoPilotThroughput : undefined
);
}
return estimatedSpend;
};
@@ -215,52 +223,8 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
newThroughput?: number
): JSX.Element => {
const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, true);
const estimatedSpendingColumns: IColumn[] = [
{
key: "costType",
name: "",
fieldName: "costType",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "minPerMonth",
name: "Min Per Month",
fieldName: "minPerMonth",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "maxPerMonth",
name: "Max Per Month",
fieldName: "maxPerMonth",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
];
const estimatedSpendingItems: AutoscaleEstimatedSpendingDisplayProps[] = [
{
costType: <Text>Current Cost</Text>,
minPerMonth: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice / 10)}
</Text>
),
maxPerMonth: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)}
</Text>
),
},
];
if (newThroughput) {
const newThroughputCostElement = (): JSX.Element => {
const newPrices: PriceBreakdown = getRuPriceBreakdown(
newThroughput,
serverId,
@@ -268,37 +232,40 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
isMultimaster,
true
);
estimatedSpendingItems.unshift({
costType: (
<Text>
<b>Updated Cost</b>
</Text>
),
minPerMonth: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice / 10)}
</b>
</Text>
),
maxPerMonth: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)}
</b>
</Text>
),
});
}
return (
<div>
<Text style={{ fontWeight: 600 }}>Updated cost per month</Text>
<Stack horizontal style={{ marginTop: 5, marginBottom: 10 }}>
<Text style={{ width: "50%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice / 10)} min
</Text>
<Text style={{ width: "50%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)} max
</Text>
</Stack>
</div>
);
};
return getEstimatedSpendingElement(
estimatedSpendingColumns,
estimatedSpendingItems,
newThroughput ?? throughput,
numberOfRegions,
prices,
true
);
const costElement = (): JSX.Element => {
const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, true);
return (
<Stack {...checkBoxAndInputStackProps} style={{ marginTop: 15 }}>
{newThroughput && newThroughputCostElement()}
<Text style={{ fontWeight: 600 }}>Current cost per month</Text>
<Stack horizontal style={{ marginTop: 5 }}>
<Text style={{ width: "50%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice / 10)} min
</Text>
<Text style={{ width: "50%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)} max
</Text>
</Stack>
</Stack>
);
};
return getEstimatedSpendingElement(costElement(), newThroughput ?? throughput, numberOfRegions, prices, true);
};
private getEstimatedManualSpendElement = (
@@ -309,122 +276,55 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
newThroughput?: number
): JSX.Element => {
const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, false);
const estimatedSpendingColumns: IColumn[] = [
{
key: "costType",
name: "",
fieldName: "costType",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "hourly",
name: "Hourly",
fieldName: "hourly",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "daily",
name: "Daily",
fieldName: "daily",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
{
key: "monthly",
name: "Monthly",
fieldName: "monthly",
minWidth: 100,
maxWidth: 200,
isResizable: true,
styles: transparentDetailsHeaderStyle,
},
];
const estimatedSpendingItems: ManualEstimatedSpendingDisplayProps[] = [
{
costType: <Text>Current Cost</Text>,
hourly: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.hourlyPrice)}
</Text>
),
daily: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.dailyPrice)}
</Text>
),
monthly: (
<Text>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)}
</Text>
),
},
];
if (newThroughput) {
const newThroughputCostElement = (): JSX.Element => {
const newPrices: PriceBreakdown = getRuPriceBreakdown(
newThroughput,
serverId,
numberOfRegions,
isMultimaster,
false
true
);
estimatedSpendingItems.unshift({
costType: (
<Text>
<b>Updated Cost</b>
</Text>
),
hourly: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.hourlyPrice)}
</b>
</Text>
),
daily: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.dailyPrice)}
</b>
</Text>
),
monthly: (
<Text>
<b>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)}
</b>
</Text>
),
});
}
return (
<div>
<Text style={{ fontWeight: 600 }}>Updated cost per month</Text>
<Stack horizontal style={{ marginTop: 5, marginBottom: 10 }}>
<Text style={{ width: "33%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.hourlyPrice)}/hr
</Text>
<Text style={{ width: "33%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.dailyPrice)}/day
</Text>
<Text style={{ width: "33%" }}>
{newPrices.currencySign} {calculateEstimateNumber(newPrices.monthlyPrice)}/mo
</Text>
</Stack>
</div>
);
};
return getEstimatedSpendingElement(
estimatedSpendingColumns,
estimatedSpendingItems,
newThroughput ?? throughput,
numberOfRegions,
prices,
false
);
};
const costElement = (): JSX.Element => {
const prices: PriceBreakdown = getRuPriceBreakdown(throughput, serverId, numberOfRegions, isMultimaster, true);
return (
<Stack {...checkBoxAndInputStackProps} style={{ marginTop: 15 }}>
{newThroughput && newThroughputCostElement()}
<Text style={{ fontWeight: 600 }}>Current cost per month</Text>
<Stack horizontal style={{ marginTop: 5 }}>
<Text style={{ width: "33%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.hourlyPrice)}/hr
</Text>
<Text style={{ width: "33%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.dailyPrice)}/day
</Text>
<Text style={{ width: "33%" }}>
{prices.currencySign} {calculateEstimateNumber(prices.monthlyPrice)}/mo
</Text>
</Stack>
</Stack>
);
};
private getAutoPilotUsageCost = (): JSX.Element => {
if (!this.props.maxAutoPilotThroughput) {
return <></>;
}
return getAutoPilotV3SpendElement(
this.props.maxAutoPilotThroughput,
false /* isDatabaseThroughput */,
!this.props.isEmulator ? this.getRequestUnitsUsageCost() : <></>
);
return getEstimatedSpendingElement(costElement(), newThroughput ?? throughput, numberOfRegions, prices, false);
};
private onAutoPilotThroughputChange = (
@@ -511,7 +411,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
onChange={this.onChoiceGroupChange}
required={this.props.showAsMandatory}
ariaLabelledBy={labelId}
styles={getChoiceGroupStyles(this.props.wasAutopilotOriginallySet, this.props.isAutoPilotSelected)}
styles={getChoiceGroupStyles(this.props.wasAutopilotOriginallySet, this.props.isAutoPilotSelected, true)}
/>
</Stack>
);
@@ -520,97 +420,266 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
private onSpendAckChecked = (ev?: React.FormEvent<HTMLElement | HTMLInputElement>, checked?: boolean): void =>
this.setState({ spendAckChecked: checked });
private renderAutoPilotInput = (): JSX.Element => (
<>
<Text>
Provision maximum RU/s required by this resource. Estimate your required RU/s with
<Link target="_blank" href="https://cosmos.azure.com/capacitycalculator/">
{` capacity calculator`}
</Link>
</Text>
<TextField
label="Max RU/s"
required
type="number"
id="autopilotInput"
key="auto pilot throughput input"
styles={getTextFieldStyles(this.props.maxAutoPilotThroughput, this.props.maxAutoPilotThroughputBaseline)}
disabled={this.overrideWithProvisionedThroughputSettings()}
step={AutoPilotUtils.autoPilotIncrementStep}
value={this.overrideWithProvisionedThroughputSettings() ? "" : this.props.maxAutoPilotThroughput?.toString()}
onChange={this.onAutoPilotThroughputChange}
min={autoPilotThroughput1K}
errorMessage={this.props.throughputError}
private getStorageCapacityTitle = (): JSX.Element => {
const capacity: string = this.props.isFixed ? "Fixed" : "Unlimited";
return (
<Stack {...titleAndInputStackProps}>
<Label>Storage capacity</Label>
<Text>{capacity}</Text>
</Stack>
);
};
private thoughputRangeSeparatorStyles: Partial<ISeparatorStyles> = {
root: [
{
selectors: {
"::before": {
backgroundColor: "rgb(200, 200, 200)",
height: "3px",
marginTop: "-1px",
},
},
},
],
};
private currentThroughputValue = (): number => {
return this.props.isAutoPilotSelected
? this.props.maxAutoPilotThroughput
: this.overrideWithAutoPilotSettings()
? this.props.maxAutoPilotThroughputBaseline
: this.props.throughput;
};
private getCurrentRuRange = (): "below" | "instant" | "delayed" | "requireSupport" => {
if (this.currentThroughputValue() < this.props.minimum) {
return "below";
}
if (
this.currentThroughputValue() >= this.props.minimum &&
this.currentThroughputValue() <= this.props.instantMaximumThroughput
) {
return "instant";
}
if (this.currentThroughputValue() > this.props.softAllowedMaximumThroughput) {
return "requireSupport";
}
return "delayed";
};
private getRuThermometerStyles = (): Partial<IProgressIndicatorStyles> => ({
progressBar: [
{
backgroundColor:
this.getCurrentRuRange() === "instant"
? "rgb(0, 120, 212)"
: this.getCurrentRuRange() === "delayed"
? "rgb(255 216 109)"
: "rgb(251, 217, 203)",
},
],
});
private getRuThermometerPercentValue = (): number => {
let percentValue: number;
const currentRus = this.currentThroughputValue();
switch (this.getCurrentRuRange()) {
case "below":
percentValue = 0;
break;
case "instant": {
const percentOfInstantRange: number = currentRus / this.props.instantMaximumThroughput;
percentValue = percentOfInstantRange * 0.34;
break;
}
case "delayed": {
const adjustedMax = this.props.softAllowedMaximumThroughput - this.props.instantMaximumThroughput;
const adjustedRus = currentRus - this.props.instantMaximumThroughput;
const percentOfDelayedRange = adjustedRus / adjustedMax;
const adjustedPercent = percentOfDelayedRange * 0.66;
percentValue = adjustedPercent + 0.34;
break;
}
default:
// over maximum
percentValue = 1;
}
return percentValue;
};
private getRUThermometer = (): JSX.Element => (
<Stack>
<Stack horizontal>
<Stack.Item style={{ width: "34%" }}>
<span>{this.props.minimum.toLocaleString()}</span>
</Stack.Item>
<Stack.Item style={{ width: "66%" }}>
<span style={{ float: "left", transform: "translateX(-50%)" }}>
{this.props.instantMaximumThroughput.toLocaleString()}
</span>
<span style={{ float: "right" }}>{this.props.softAllowedMaximumThroughput.toLocaleString()}</span>
</Stack.Item>
</Stack>
<ProgressIndicator
barHeight={20}
percentComplete={this.getRuThermometerPercentValue()}
styles={this.getRuThermometerStyles()}
/>
{!this.overrideWithProvisionedThroughputSettings() && this.getAutoPilotUsageCost()}
{this.minRUperGBSurvey()}
{this.props.spendAckVisible && (
<Checkbox
id="spendAckCheckBox"
styles={noLeftPaddingCheckBoxStyle}
label={this.props.spendAckText}
checked={this.state.spendAckChecked}
onChange={this.onSpendAckChecked}
<Stack horizontal>
<Stack.Item style={{ width: "34%", paddingRight: "5px" }}>
<Separator styles={this.thoughputRangeSeparatorStyles}>Instant</Separator>
</Stack.Item>
<Stack.Item style={{ width: "66%", paddingLeft: "5px" }}>
<Separator styles={this.thoughputRangeSeparatorStyles}>4-6 hrs</Separator>
</Stack.Item>
</Stack>
</Stack>
);
private showThroughputWarning = (): boolean => {
return (
this.currentThroughputValue() > this.props.instantMaximumThroughput ||
this.currentThroughputValue() < this.props.minimum
);
};
private getThroughputWarningMessageText = (): JSX.Element => {
switch (this.getCurrentRuRange()) {
case "below":
return getUpdateThroughputBelowMinimumMessage(this.props.minimum);
case "delayed":
return getUpdateThroughputBeyondInstantLimitMessage(this.props.instantMaximumThroughput);
case "requireSupport":
return getUpdateThroughputBeyondSupportLimitMessage(
this.props.instantMaximumThroughput,
this.props.softAllowedMaximumThroughput
);
default:
return <></>;
}
};
private getThroughputWarningMessageBar = (): JSX.Element => {
const isSevereWarning: boolean =
this.currentThroughputValue() > this.props.softAllowedMaximumThroughput ||
this.currentThroughputValue() < this.props.minimum;
return (
<MessageBar messageBarType={isSevereWarning ? MessageBarType.severeWarning : MessageBarType.warning}>
{this.getThroughputWarningMessageText()}
</MessageBar>
);
};
private getThroughputTextField = (): JSX.Element => (
<>
{this.props.isAutoPilotSelected ? (
<TextField
label="Maximum RU/s required by this resource"
required
type="number"
id="autopilotInput"
key="auto pilot throughput input"
styles={getTextFieldStyles(this.props.maxAutoPilotThroughput, this.props.maxAutoPilotThroughputBaseline)}
disabled={this.overrideWithProvisionedThroughputSettings()}
step={AutoPilotUtils.autoPilotIncrementStep}
value={this.overrideWithProvisionedThroughputSettings() ? "" : this.props.maxAutoPilotThroughput?.toString()}
onChange={this.onAutoPilotThroughputChange}
min={autoPilotThroughput1K}
onGetErrorMessage={(value: string) => {
const sanitizedValue = getSanitizedInputValue(value);
return sanitizedValue % 1000
? "Throughput value must be in increments of 1000"
: this.props.throughputError;
}}
validateOnLoad={false}
/>
) : (
<TextField
required
type="number"
id="throughputInput"
key="provisioned throughput input"
styles={getTextFieldStyles(this.props.throughput, this.props.throughputBaseline)}
disabled={this.overrideWithAutoPilotSettings()}
step={this.step}
value={
this.overrideWithAutoPilotSettings()
? this.props.maxAutoPilotThroughputBaseline?.toString()
: this.props.throughput?.toString()
}
onChange={this.onThroughputChange}
min={this.props.minimum}
errorMessage={this.props.throughputError}
/>
)}
{this.props.isFixed && <p>When using a collection with fixed storage capacity, you can set up to 10,000 RU/s.</p>}
</>
);
private renderThroughputInput = (): JSX.Element => (
<Stack {...titleAndInputStackProps}>
<Text>
Estimate your required throughput with
<Link target="_blank" href="https://cosmos.azure.com/capacitycalculator/">
{` capacity calculator`} <FontIcon iconName="NavigateExternalInline" />
</Link>
</Text>
<TextField
required
type="number"
id="throughputInput"
key="provisioned throughput input"
styles={getTextFieldStyles(this.props.throughput, this.props.throughputBaseline)}
disabled={this.overrideWithAutoPilotSettings()}
step={this.step}
value={
this.overrideWithAutoPilotSettings()
? this.props.maxAutoPilotThroughputBaseline?.toString()
: this.props.throughput?.toString()
}
onChange={this.onThroughputChange}
min={this.props.minimum}
errorMessage={this.props.throughputError}
/>
{this.state.exceedFreeTierThroughput && (
<MessageBar
messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}
styles={messageBarStyles}
>
{`Billing will apply if you provision more than ${SharedConstants.FreeTierLimits.RU} RU/s of manual throughput, or if the resource scales beyond ${SharedConstants.FreeTierLimits.RU} RU/s with autoscale.`}
</MessageBar>
)}
{this.props.getThroughputWarningMessage() && (
<MessageBar
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
styles={messageBarStyles}
>
{this.props.getThroughputWarningMessage()}
</MessageBar>
)}
{!this.props.isEmulator && this.getRequestUnitsUsageCost()}
{this.minRUperGBSurvey()}
{this.props.spendAckVisible && (
<Checkbox
id="spendAckCheckBox"
styles={noLeftPaddingCheckBoxStyle}
label={this.props.spendAckText}
checked={this.state.spendAckChecked}
onChange={this.onSpendAckChecked}
/>
)}
<br />
{this.props.isFixed && <p>When using a collection with fixed storage capacity, you can set up to 10,000 RU/s.</p>}
private renderThroughputComponent = (): JSX.Element => (
<Stack horizontal>
<Stack.Item style={{ width: "70%", maxWidth: "700px" }}>
<Stack {...relaxedSpacingStackProps} style={{ paddingRight: "50px" }}>
{this.getThroughputTextField()}
{this.props.instantMaximumThroughput && (
<Stack>
{this.getRUThermometer()}
{this.showThroughputWarning() && this.getThroughputWarningMessageBar()}
</Stack>
)}
{this.props.isAutoPilotSelected ? (
<Text style={{ marginTop: "40px" }}>
Based on usage, your {this.props.collectionName ? "container" : "database"} throughput will scale from{" "}
<b>
{AutoPilotUtils.getMinRUsBasedOnUserInput(this.props.maxAutoPilotThroughput)} RU/s (10% of max RU/s) -{" "}
{this.props.maxAutoPilotThroughput} RU/s
</b>
<br />
</Text>
) : (
<>
{this.state.exceedFreeTierThroughput && (
<MessageBar
messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}
styles={messageBarStyles}
style={{ marginTop: "40px" }}
>
{`Billing will apply if you provision more than ${SharedConstants.FreeTierLimits.RU} RU/s of manual throughput, or if the resource scales beyond ${SharedConstants.FreeTierLimits.RU} RU/s with autoscale.`}
</MessageBar>
)}
</>
)}
{!this.overrideWithProvisionedThroughputSettings() && (
<Text>
Estimate your required RU/s with
<Link target="_blank" href="https://cosmos.azure.com/capacitycalculator/">
{` capacity calculator`} <FontIcon iconName="NavigateExternalInline" />
</Link>
</Text>
)}
{this.minRUperGBSurvey()}
{this.props.spendAckVisible && (
<Checkbox
id="spendAckCheckBox"
styles={noLeftPaddingCheckBoxStyle}
label={this.props.spendAckText}
checked={this.state.spendAckChecked}
onChange={this.onSpendAckChecked}
/>
)}
{this.props.isFixed && (
<p>When using a collection with fixed storage capacity, you can set up to 10,000 RU/s.</p>
)}
{this.props.collectionName && (
<Stack.Item style={{ marginTop: "40px" }}>{this.getStorageCapacityTitle()}</Stack.Item>
)}
</Stack>
</Stack.Item>
<Stack.Item style={{ width: "30%", maxWidth: "300px" }}>
{!this.props.isEmulator ? this.getRequestUnitsUsageCost() : <></>}
</Stack.Item>
</Stack>
);
@@ -640,7 +709,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
{this.renderWarningMessage()}
{this.renderThroughputModeChoices()}
{this.props.isAutoPilotSelected ? this.renderAutoPilotInput() : this.renderThroughputInput()}
{this.renderThroughputComponent()}
</Stack>
);
}

View File

@@ -28,6 +28,8 @@ exports[`ConflictResolutionComponent Path text field displayed 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": undefined,
@@ -100,6 +102,8 @@ exports[`ConflictResolutionComponent Sproc text field displayed 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",

View File

@@ -39,7 +39,6 @@ exports[`ScaleComponent renders with correct initial notification 1`] = `
canExceedMaximumValue={true}
collectionName="test"
databaseName="test"
getThroughputWarningMessage={[Function]}
isAutoPilotSelected={false}
isEmulator={false}
isEnabled={true}
@@ -60,20 +59,6 @@ exports[`ScaleComponent renders with correct initial notification 1`] = `
usageSizeInKB={100}
wasAutopilotOriginallySet={true}
/>
<Stack
tokens={
Object {
"childrenGap": 5,
}
}
>
<StyledLabelBase>
Storage capacity
</StyledLabelBase>
<Text>
Unlimited
</Text>
</Stack>
</Stack>
</Stack>
`;

View File

@@ -40,6 +40,8 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -106,6 +108,8 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -168,6 +172,8 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -267,6 +273,8 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -333,6 +341,8 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -385,6 +395,8 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": undefined,
@@ -448,6 +460,8 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -547,6 +561,8 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -613,6 +629,8 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -665,6 +683,8 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -789,6 +809,8 @@ exports[`SubSettingsComponent renders 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -855,6 +877,8 @@ exports[`SubSettingsComponent renders 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -907,6 +931,8 @@ exports[`SubSettingsComponent renders 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -995,6 +1021,8 @@ exports[`SubSettingsComponent renders 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -1094,6 +1122,8 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": undefined,
@@ -1135,6 +1165,8 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -1187,6 +1219,8 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",
@@ -1275,6 +1309,8 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
Object {
"flexContainer": Array [
Object {
"columnGap": "default",
"display": "default",
"selectors": Object {
".ms-ChoiceField-field.is-checked::after": Object {
"borderColor": "",

View File

@@ -2,154 +2,60 @@
exports[`SettingsUtils functions render 1`] = `
<Fragment>
<Text>
Your
container
throughput will automatically scale from
<b>
100
RU/s (10% of max RU/s) -
1000
RU/s
</b>
based on usage.
<br />
</Text>
<Text>
After the first
10
GB of data stored, the max RU/s will be automatically upgraded based on the new storage value.
<StyledLinkBase
href="https://aka.ms/cosmos-autoscale-info"
target="_blank"
>
Learn more
</StyledLinkBase>
.
</Text>
<Text>
Your
database
throughput will automatically scale from
<b>
100
RU/s (10% of max RU/s) -
1000
RU/s
</b>
based on usage.
<br />
</Text>
<Text>
After the first
10
GB of data stored, the max RU/s will be automatically upgraded based on the new storage value.
<StyledLinkBase
href="https://aka.ms/cosmos-autoscale-info"
target="_blank"
>
Learn more
</StyledLinkBase>
.
</Text>
<Stack
styles={
Object {
"root": Object {
"width": 600,
},
}
}
tokens={
Object {
"childrenGap": 10,
}
}
>
<StyledWithViewportComponent
columns={
Array [
Object {
"fieldName": "costType",
"isResizable": true,
"key": "costType",
"maxWidth": 200,
"minWidth": 100,
"name": "",
},
Object {
"fieldName": "hourly",
"isResizable": true,
"key": "hourly",
"maxWidth": 200,
"minWidth": 100,
"name": "Hourly",
},
Object {
"fieldName": "daily",
"isResizable": true,
"key": "daily",
"maxWidth": 200,
"minWidth": 100,
"name": "Daily",
},
Object {
"fieldName": "monthly",
"isResizable": true,
"key": "monthly",
"maxWidth": 200,
"minWidth": 100,
"name": "Monthly",
},
]
}
disableSelectionZone={true}
items={
Array [
Object {
"costType": <Text>
Current Cost
</Text>,
"daily": <Text>
$ 24.48
</Text>,
"hourly": <Text>
$ 1.02
</Text>,
"monthly": <Text>
$ 744.6
</Text>,
},
]
}
layoutMode={1}
onRenderRow={[Function]}
selectionMode={0}
/>
<Stack>
<Text
id="throughputSpendElement"
style={
Object {
"fontWeight": 600,
}
}
>
(
regions:
2
,
1000
RU/s,
¥
0.00051
/RU)
Cost estimate*
</Text>
<Text>
<Text
style={
Object {
"fontWeight": 600,
"marginTop": 15,
}
}
>
How we calculate this
</Text>
<Stack
id="throughputSpendElement"
style={
Object {
"marginTop": 5,
}
}
>
<span>
2
region
<span>
s
</span>
</span>
<span>
1000
RU/s
</span>
<span>
¥
0.00051
/RU
</span>
</Stack>
<Text
style={
Object {
"marginTop": 15,
}
}
>
<em>
*
This cost is an estimate and may vary based on the regions where your account is deployed and potential discounts applied to your account
</em>
</Text>
@@ -205,19 +111,6 @@ exports[`SettingsUtils functions render 1`] = `
>
You have not saved the latest changes made to your indexing policy. Please click save to confirm the changes.
</Text>
<Text
id="updateThroughputBeyondLimitWarningMessage"
styles={
Object {
"root": Object {
"color": "windowtext",
"fontSize": 14,
},
}
}
>
You are about to request an increase in throughput beyond the pre-allocated capacity. The service will scale out and increase throughput for the selected container. This operation will take 1-3 business days to complete. You can track the status of this request in Notifications.
</Text>
<Text
id="updateThroughputDelayedApplyWarningMessage"
styles={

View File

@@ -22,10 +22,17 @@ export class ContainerSampleGenerator {
/**
* Factory function to load the json data file
*/
public static async createSampleGeneratorAsync(container: Explorer): Promise<ContainerSampleGenerator> {
public static async createSampleGeneratorAsync(
container: Explorer,
isCopilot?: boolean
): Promise<ContainerSampleGenerator> {
const generator = new ContainerSampleGenerator(container);
let dataFileContent: any;
if (userContext.apiType === "Gremlin") {
if (isCopilot) {
dataFileContent = await import(
/* webpackChunkName: "queryCopilotSampleData" */ "../../../sampleData/queryCopilotSampleData.json"
);
} else if (userContext.apiType === "Gremlin") {
dataFileContent = await import(
/* webpackChunkName: "gremlinSampleJsonData" */ "../../../sampleData/gremlinSampleData.json"
);

View File

@@ -1,18 +1,18 @@
import { Text, TextField } from "@fluentui/react";
import { useBoolean } from "@fluentui/react-hooks";
import { Areas } from "Common/Constants";
import { deleteDatabase } from "Common/dataAccess/deleteDatabase";
import DeleteFeedback from "Common/DeleteFeedback";
import { getErrorMessage, getErrorStack } from "Common/ErrorHandlingUtils";
import { deleteDatabase } from "Common/dataAccess/deleteDatabase";
import { Collection, Database } from "Contracts/ViewModels";
import { useSidePanel } from "hooks/useSidePanel";
import { useTabs } from "hooks/useTabs";
import React, { FunctionComponent, useState } from "react";
import { DefaultExperienceUtility } from "Shared/DefaultExperienceUtility";
import { Action, ActionModifiers } from "Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "Shared/Telemetry/TelemetryProcessor";
import { userContext } from "UserContext";
import { logConsoleError } from "Utils/NotificationConsoleUtils";
import { useSidePanel } from "hooks/useSidePanel";
import { useTabs } from "hooks/useTabs";
import React, { FunctionComponent, useState } from "react";
import { useDatabases } from "../useDatabases";
import { useSelectedNode } from "../useSelectedNode";
import { PanelInfoErrorComponent, PanelInfoErrorProps } from "./PanelInfoErrorComponent";
@@ -36,8 +36,13 @@ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseCo
const submit = async (): Promise<void> => {
if (selectedDatabase?.id() && databaseInput !== selectedDatabase.id()) {
setFormError("Input database name does not match the selected database");
setFormError(
`Input database name "${databaseInput}" does not match the selected database "${selectedDatabase.id()}"`
);
logConsoleError(`Error while deleting collection ${selectedDatabase && selectedDatabase.id()}`);
logConsoleError(
`Input database name "${databaseInput}" does not match the selected database "${selectedDatabase.id()}"`
);
return;
}
setFormError("");

View File

@@ -48,6 +48,7 @@ export const QueryCopilotCarousel: React.FC<QueryCopilotCarouselProps> = ({
}: QueryCopilotCarouselProps): JSX.Element => {
const [page, setPage] = useState<number>(1);
const [isCreatingDatabase, setIsCreatingDatabase] = useState<boolean>(false);
const [spinnerText, setSpinnerText] = useState<string>("");
const [selectedPrompt, setSelectedPrompt] = useState<number>(1);
const getHeaderText = (): string => {
@@ -84,6 +85,7 @@ export const QueryCopilotCarousel: React.FC<QueryCopilotCarouselProps> = ({
try {
setIsCreatingDatabase(true);
setSpinnerText("Setting up your database...");
const params: DataModels.CreateCollectionParams = {
createNewDatabase: true,
collectionId: "SampleContainer",
@@ -93,7 +95,7 @@ export const QueryCopilotCarousel: React.FC<QueryCopilotCarouselProps> = ({
offerThroughput: undefined,
indexingPolicy: AllPropertiesIndexed,
partitionKey: {
paths: ["/CategoryId"],
paths: ["/categoryId"],
kind: "Hash",
version: 2,
},
@@ -101,22 +103,22 @@ export const QueryCopilotCarousel: React.FC<QueryCopilotCarouselProps> = ({
await createCollection(params);
await explorer.refreshAllDatabases();
const database = useDatabases.getState().findDatabaseWithId(QueryCopilotSampleDatabaseId);
// populate sample container with sample data
await database.loadCollections();
const collection = database.findCollectionWithId("SampleContainer");
collection.isSampleCollection = true;
const sampleGenerator = await ContainerSampleGenerator.createSampleGeneratorAsync(explorer);
await sampleGenerator.populateContainerAsync(collection, "/CategoryId");
// auto-expand sample database + container and show teaching bubble
setSpinnerText("Adding sample data set...");
const sampleGenerator = await ContainerSampleGenerator.createSampleGeneratorAsync(explorer, true);
await sampleGenerator.populateContainerAsync(collection);
await database.expandDatabase();
collection.expandCollection();
useDatabases.getState().updateDatabase(database);
} catch (error) {
//TODO: show error in UI
handleError(error, "Query copilot quickstart");
handleError(error, "QueryCopilotCreateSampleDB");
throw error;
} finally {
setIsCreatingDatabase(false);
setSpinnerText("");
}
};
@@ -183,7 +185,7 @@ export const QueryCopilotCarousel: React.FC<QueryCopilotCarouselProps> = ({
<Text style={{ fontSize: 13, fontWeight: 600, marginTop: 16 }}>Container Id</Text>
<Text style={{ fontSize: 13 }}>SampleContainer</Text>
<Text style={{ fontSize: 13, fontWeight: 600, marginTop: 16 }}>Partition key</Text>
<Text style={{ fontSize: 13 }}>CategoryId</Text>
<Text style={{ fontSize: 13 }}>categoryId</Text>
</Stack>
);
case 3:
@@ -267,7 +269,7 @@ export const QueryCopilotCarousel: React.FC<QueryCopilotCarouselProps> = ({
disabled={isCreatingDatabase}
/>
{isCreatingDatabase && <Spinner style={{ marginLeft: 8 }} />}
{isCreatingDatabase && <Text style={{ marginLeft: 8, color: "#0078D4" }}>Setting up your database...</Text>}
{isCreatingDatabase && <Text style={{ marginLeft: 8, color: "#0078D4" }}>{spinnerText}</Text>}
</Stack>
</Stack>
</Modal>

View File

@@ -0,0 +1,105 @@
import {
Checkbox,
ChoiceGroup,
DefaultButton,
IconButton,
Link,
Modal,
PrimaryButton,
Stack,
Text,
TextField,
} from "@fluentui/react";
import { submitFeedback } from "Explorer/QueryCopilot/QueryCopilotUtilities";
import { useQueryCopilot } from "hooks/useQueryCopilot";
import React from "react";
export const QueryCopilotFeedbackModal: React.FC = (): JSX.Element => {
const {
generatedQuery,
userPrompt,
likeQuery,
showFeedbackModal,
closeFeedbackModal,
setHideFeedbackModalForLikedQueries,
} = useQueryCopilot();
const [isContactAllowed, setIsContactAllowed] = React.useState<boolean>(true);
const [description, setDescription] = React.useState<string>("");
const [doNotShowAgainChecked, setDoNotShowAgainChecked] = React.useState<boolean>(false);
return (
<Modal isOpen={showFeedbackModal}>
<Stack style={{ padding: 24 }}>
<Stack horizontal horizontalAlign="space-between">
<Text style={{ fontSize: 20, fontWeight: 600, marginBottom: 20 }}>Send feedback to Microsoft</Text>
<IconButton iconProps={{ iconName: "Cancel" }} onClick={() => closeFeedbackModal()} />
</Stack>
<Text style={{ fontSize: 14, marginBottom: 14 }}>Your feedback will help improve the experience.</Text>
<TextField
styles={{ root: { marginBottom: 14 } }}
label="Description"
required
placeholder="Provide more details"
value={description}
onChange={(_, newValue) => setDescription(newValue)}
multiline
rows={3}
/>
<TextField
styles={{ root: { marginBottom: 14 } }}
label="Query generated"
defaultValue={generatedQuery}
readOnly
/>
<ChoiceGroup
styles={{
root: {
marginBottom: 14,
},
flexContainer: {
selectors: {
".ms-ChoiceField-field::before": { marginTop: 4 },
".ms-ChoiceField-field::after": { marginTop: 4 },
".ms-ChoiceFieldLabel": { paddingLeft: 6 },
},
},
}}
label="May we contact you about your feedback?"
options={[
{ key: "yes", text: "Yes, you may contact me." },
{ key: "no", text: "No, do not contact me." },
]}
selectedKey={isContactAllowed ? "yes" : "no"}
onChange={(_, option) => setIsContactAllowed(option.key === "yes")}
></ChoiceGroup>
<Text style={{ fontSize: 12, marginBottom: 14 }}>
By pressing submit, your feedback will be used to improve Microsoft products and services. IT admins for your
organization will be able to view and manage your feedback data.{" "}
<Link href="" target="_blank">
Privacy statement
</Link>
</Text>
{likeQuery && (
<Checkbox
styles={{ label: { paddingLeft: 0 }, root: { marginBottom: 14 } }}
label="Don't show me this next time"
checked={doNotShowAgainChecked}
onChange={(_, checked) => setDoNotShowAgainChecked(checked)}
/>
)}
<Stack horizontal horizontalAlign="end">
<PrimaryButton
styles={{ root: { marginRight: 8 } }}
onClick={() => {
closeFeedbackModal();
setHideFeedbackModalForLikedQueries(doNotShowAgainChecked);
submitFeedback({ generatedQuery, likeQuery, description, userPrompt });
}}
>
Submit
</PrimaryButton>
<DefaultButton onClick={() => closeFeedbackModal()}>Cancel</DefaultButton>
</Stack>
</Stack>
</Modal>
);
};

View File

@@ -1,7 +1,23 @@
/* eslint-disable no-console */
import { FeedOptions } from "@azure/cosmos";
import { IconButton, Image, Link, Stack, Text, TextField } from "@fluentui/react";
import { QueryCopilotSampleContainerId, QueryCopilotSampleDatabaseId } from "Common/Constants";
import {
Callout,
CommandBarButton,
DirectionalHint,
IconButton,
Image,
Link,
Separator,
Spinner,
Stack,
Text,
TextField,
} from "@fluentui/react";
import {
QueryCopilotSampleContainerId,
QueryCopilotSampleContainerSchema,
QueryCopilotSampleDatabaseId,
} from "Common/Constants";
import { getErrorMessage, handleError } from "Common/ErrorHandlingUtils";
import { shouldEnableCrossPartitionKey } from "Common/HeadersUtility";
import { MinimalQueryIterator } from "Common/IteratorUtilities";
@@ -13,8 +29,10 @@ import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
import Explorer from "Explorer/Explorer";
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
import { SaveQueryPane } from "Explorer/Panes/SaveQueryPane/SaveQueryPane";
import { submitFeedback } from "Explorer/QueryCopilot/QueryCopilotUtilities";
import { QueryResultSection } from "Explorer/Tabs/QueryTab/QueryResultSection";
import { queryPagesUntilContentPresent } from "Utils/QueryUtils";
import { useQueryCopilot } from "hooks/useQueryCopilot";
import { useSidePanel } from "hooks/useSidePanel";
import React, { useState } from "react";
import SplitterLayout from "react-splitter-layout";
@@ -27,28 +45,62 @@ interface QueryCopilotTabProps {
explorer: Explorer;
}
interface GenerateSQLQueryResponse {
apiVersion: string;
sql: string;
explanation: string;
generateStart: string;
generateEnd: string;
}
export const QueryCopilotTab: React.FC<QueryCopilotTabProps> = ({
initialInput,
explorer,
}: QueryCopilotTabProps): JSX.Element => {
const hideFeedbackModalForLikedQueries = useQueryCopilot((state) => state.hideFeedbackModalForLikedQueries);
const [userInput, setUserInput] = useState<string>(initialInput || "");
const [generatedQuery, setGeneratedQuery] = useState<string>("");
const [query, setQuery] = useState<string>("");
const [selectedQuery, setSelectedQuery] = useState<string>("");
const [isGeneratingQuery, setIsGeneratingQuery] = useState<boolean>(false);
const [isExecuting, setIsExecuting] = useState<boolean>(false);
const [likeQuery, setLikeQuery] = useState<boolean>();
const [showCallout, setShowCallout] = useState<boolean>(false);
const [queryIterator, setQueryIterator] = useState<MinimalQueryIterator>();
const [queryResults, setQueryResults] = useState<QueryResults>();
const [errorMessage, setErrorMessage] = useState<string>("");
const generateQuery = (): string => {
switch (userInput) {
case "Write a query to return all records in this table":
return "SELECT * FROM c";
case "Write a query to return all records in this table created in the last thirty days":
return "SELECT * FROM c WHERE c._ts > (DATEDIFF(s, '1970-01-01T00:00:00Z', GETUTCDATE()) - 2592000) * 1000";
case `Write a query to return all records in this table created in the last thirty days which also have the record owner as "Contoso"`:
return `SELECT * FROM c WHERE c.owner = "Contoso" AND c._ts > (DATEDIFF(s, '1970-01-01T00:00:00Z', GETUTCDATE()) - 2592000) * 1000`;
default:
return "";
const generateSQLQuery = async (): Promise<void> => {
try {
setIsGeneratingQuery(true);
const payload = {
containerSchema: QueryCopilotSampleContainerSchema,
userPrompt: userInput,
};
const response = await fetch("https://copilotorchestrater.azurewebsites.net/generateSQLQuery", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify(payload),
});
const generateSQLQueryResponse: GenerateSQLQueryResponse = await response?.json();
if (generateSQLQueryResponse?.sql) {
let query = `-- ${userInput}\r\n`;
if (generateSQLQueryResponse.explanation) {
query += "-- **Explanation of query**\r\n";
query += `-- ${generateSQLQueryResponse.explanation}\r\n`;
}
query += generateSQLQueryResponse.sql;
setQuery(query);
setGeneratedQuery(generateSQLQueryResponse.sql);
}
} catch (error) {
handleError(error, "executeNaturalLanguageQuery");
throw error;
} finally {
setIsGeneratingQuery(false);
}
};
@@ -110,7 +162,13 @@ export const QueryCopilotTab: React.FC<QueryCopilotTabProps> = ({
React.useEffect(() => {
useCommandBar.getState().setContextButtons(getCommandbarButtons());
}, [query]);
}, [query, selectedQuery]);
React.useEffect(() => {
if (initialInput) {
generateSQLQuery();
}
}, []);
return (
<Stack className="tab-pane" style={{ padding: 24, width: "100%", height: "100%" }}>
@@ -124,12 +182,15 @@ export const QueryCopilotTab: React.FC<QueryCopilotTabProps> = ({
onChange={(_, newValue) => setUserInput(newValue)}
style={{ lineHeight: 30 }}
styles={{ root: { width: "90%" } }}
disabled={isGeneratingQuery}
/>
<IconButton
iconProps={{ iconName: "Send" }}
disabled={isGeneratingQuery}
style={{ marginLeft: 8 }}
onClick={() => setQuery(generateQuery())}
onClick={() => generateSQLQuery()}
/>
{isGeneratingQuery && <Spinner style={{ marginLeft: 8 }} />}
</Stack>
<Text style={{ marginTop: 8, marginBottom: 24, fontSize: 12 }}>
AI-generated content can have mistakes. Make sure it&apos;s accurate and appropriate before using it.{" "}
@@ -138,6 +199,57 @@ export const QueryCopilotTab: React.FC<QueryCopilotTabProps> = ({
</Link>
</Text>
<Stack style={{ backgroundColor: "#FFF8F0", padding: "2px 8px" }} horizontal verticalAlign="center">
<Text style={{ fontWeight: 600, fontSize: 12 }}>Provide feedback on the query generated</Text>
{showCallout && !hideFeedbackModalForLikedQueries && (
<Callout
style={{ padding: 8 }}
target="#likeBtn"
onDismiss={() => {
setShowCallout(false);
submitFeedback({ generatedQuery, likeQuery, description: "", userPrompt: userInput });
}}
directionalHint={DirectionalHint.topCenter}
>
<Text>
Thank you. Need to give{" "}
<Link
onClick={() => {
setShowCallout(false);
useQueryCopilot.getState().openFeedbackModal(generatedQuery, true, userInput);
}}
>
more feedback?
</Link>
</Text>
</Callout>
)}
<IconButton
id="likeBtn"
style={{ marginLeft: 20 }}
iconProps={{ iconName: likeQuery === true ? "LikeSolid" : "Like" }}
onClick={() => {
setLikeQuery(true);
setShowCallout(true);
}}
/>
<IconButton
style={{ margin: "0 10px" }}
iconProps={{ iconName: likeQuery === false ? "DislikeSolid" : "Dislike" }}
onClick={() => {
setLikeQuery(false);
setShowCallout(false);
useQueryCopilot.getState().openFeedbackModal(generatedQuery, false, userInput);
}}
/>
<Separator vertical style={{ color: "#EDEBE9" }} />
<CommandBarButton iconProps={{ iconName: "Copy" }} style={{ margin: "0 10px", backgroundColor: "#FFF8F0" }}>
Copy code
</CommandBarButton>
<CommandBarButton iconProps={{ iconName: "Delete" }} style={{ backgroundColor: "#FFF8F0" }}>
Delete code
</CommandBarButton>
</Stack>
<Stack className="tabPaneContentContainer">
<SplitterLayout vertical={true} primaryIndex={0} primaryMinSize={100} secondaryMinSize={200}>
<EditorReact

View File

@@ -0,0 +1,36 @@
import { QueryCopilotSampleContainerSchema } from "Common/Constants";
import { handleError } from "Common/ErrorHandlingUtils";
interface FeedbackParams {
likeQuery: boolean;
generatedQuery: string;
userPrompt: string;
description?: string;
contact?: string;
}
export const submitFeedback = async (params: FeedbackParams): Promise<void> => {
try {
const { likeQuery, generatedQuery, userPrompt, description, contact } = params;
const payload = {
containerSchema: QueryCopilotSampleContainerSchema,
like: likeQuery ? "like" : "dislike",
generatedSql: generatedQuery,
userPrompt,
description: description || "",
contact: contact || "",
};
const response = await fetch("https://copilotorchestrater.azurewebsites.net/feedback", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify(payload),
});
// eslint-disable-next-line no-console
console.log(response);
} catch (error) {
handleError(error, "copilotSubmitFeedback");
}
};

View File

@@ -41,6 +41,7 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
verticalAlign="center"
>
<StyledTextFieldBase
disabled={false}
onChange={[Function]}
style={
Object {
@@ -57,6 +58,7 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
value="Write a query to return all records in this table"
/>
<CustomizedIconButton
disabled={false}
iconProps={
Object {
"iconName": "Send",
@@ -88,6 +90,91 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
Read preview terms
</StyledLinkBase>
</Text>
<Stack
horizontal={true}
style={
Object {
"backgroundColor": "#FFF8F0",
"padding": "2px 8px",
}
}
verticalAlign="center"
>
<Text
style={
Object {
"fontSize": 12,
"fontWeight": 600,
}
}
>
Provide feedback on the query generated
</Text>
<CustomizedIconButton
iconProps={
Object {
"iconName": "Like",
}
}
id="likeBtn"
onClick={[Function]}
style={
Object {
"marginLeft": 20,
}
}
/>
<CustomizedIconButton
iconProps={
Object {
"iconName": "Dislike",
}
}
onClick={[Function]}
style={
Object {
"margin": "0 10px",
}
}
/>
<Separator
style={
Object {
"color": "#EDEBE9",
}
}
vertical={true}
/>
<CustomizedCommandBarButton
iconProps={
Object {
"iconName": "Copy",
}
}
style={
Object {
"backgroundColor": "#FFF8F0",
"margin": "0 10px",
}
}
>
Copy code
</CustomizedCommandBarButton>
<CustomizedCommandBarButton
iconProps={
Object {
"iconName": "Delete",
}
}
style={
Object {
"backgroundColor": "#FFF8F0",
}
}
>
Delete code
</CustomizedCommandBarButton>
</Stack>
<Stack
className="tabPaneContentContainer"
>

View File

@@ -137,7 +137,7 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
description={
"Copilot is your AI buddy that helps you write Azure Cosmos DB queries like a pro. Try it using our sample data set now!"
}
onClick={() => useCarousel.getState().setShowCopilotCarousel(true)}
onClick={() => useTabs.getState().openAndActivateReactTab(ReactTabKind.QueryCopilot)}
/>
<SplashScreenButton
imgSrc={ConnectIcon}

View File

@@ -17,6 +17,7 @@ import "../externals/jquery.typeahead.min.css";
import "../externals/jquery.typeahead.min.js";
// Image Dependencies
import { QueryCopilotCarousel } from "Explorer/QueryCopilot/CopilotCarousel";
import { QueryCopilotFeedbackModal } from "Explorer/QueryCopilot/QueryCopilotFeedbackModal";
import "../images/CosmosDB_rgb_ui_lighttheme.ico";
import hdeConnectImage from "../images/HdeConnectCosmosDB.svg";
import "../images/favicon.ico";
@@ -125,6 +126,7 @@ const App: React.FunctionComponent = () => {
{<SQLQuickstartTutorial />}
{<MongoQuickstartTutorial />}
{<QueryCopilotCarousel isOpen={isCopilotCarouselOpen} explorer={explorer} />}
{<QueryCopilotFeedbackModal />}
</div>
);
};

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Lists the Cassandra keyspaces under an existing Azure Cosmos DB database account. */
export async function listCassandraKeyspaces(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Retrieves the metrics determined by the given filter for the given database account and collection. */
export async function listMetrics(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Retrieves the metrics determined by the given filter for the given collection, split by partition. */
export async function listMetrics(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Retrieves the metrics determined by the given filter for the given collection and region, split by partition. */
export async function listMetrics(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Retrieves the metrics determined by the given filter for the given database account, collection and region. */
export async function listMetrics(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Retrieves the metrics determined by the given filter for the given database account and database. */
export async function listMetrics(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Retrieves the metrics determined by the given filter for the given database account and region. */
export async function listMetrics(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Retrieves the properties of an existing Azure Cosmos DB database account. */
export async function get(
@@ -29,13 +29,7 @@ export async function update(
body: Types.DatabaseAccountUpdateParameters
): Promise<Types.DatabaseAccountGetResults> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}`;
return armRequest({
host: configContext.ARM_ENDPOINT,
path,
method: "PATCH",
apiVersion,
body,
});
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PATCH", apiVersion, body });
}
/* Creates or updates an Azure Cosmos DB database account. The "Update" method is preferred when performing updates on an account. */

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Lists the Gremlin databases under an existing Azure Cosmos DB database account. */
export async function listGremlinDatabases(

View File

@@ -0,0 +1,27 @@
/*
AUTOGENERATED FILE
Run "npm run generateARMClients" to regenerate
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/stable/2023-04-15/cosmos-db.json
*/
import { armRequest } from "../../request";
import * as Types from "./types";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* List Cosmos DB locations and their properties */
export async function list(subscriptionId: string): Promise<Types.LocationListResult | Types.CloudError> {
const path = `/subscriptions/${subscriptionId}/providers/Microsoft.DocumentDB/locations`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
}
/* Get the properties of an existing Cosmos DB location */
export async function get(
subscriptionId: string,
location: string
): Promise<Types.LocationGetResult | Types.CloudError> {
const path = `/subscriptions/${subscriptionId}/providers/Microsoft.DocumentDB/locations/${location}`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
}

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Lists the MongoDB databases under an existing Azure Cosmos DB database account. */
export async function listMongoDBDatabases(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Lists all of the available Cosmos DB Resource Provider operations. */
export async function list(): Promise<Types.OperationListResult> {

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Retrieves the metrics determined by the given filter for the given partition key range id. */
export async function listMetrics(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Retrieves the metrics determined by the given filter for the given partition key range id and region. */
export async function listMetrics(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* 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(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* 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(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* 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(

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Lists the SQL databases under an existing Azure Cosmos DB database account. */
export async function listSqlDatabases(
@@ -197,6 +197,42 @@ export async function migrateSqlContainerToManualThroughput(
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion });
}
/* Lists the ClientEncryptionKeys under an existing Azure Cosmos DB SQL database. */
export async function listClientEncryptionKeys(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
databaseName: string
): Promise<Types.ClientEncryptionKeysListResult> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/clientEncryptionKeys`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
}
/* Gets the ClientEncryptionKey under an existing Azure Cosmos DB SQL database. */
export async function getClientEncryptionKey(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
databaseName: string,
clientEncryptionKeyName: string
): Promise<Types.ClientEncryptionKeyGetResults> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/clientEncryptionKeys/${clientEncryptionKeyName}`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
}
/* Create or update a ClientEncryptionKey. This API is meant to be invoked via tools such as the Azure Powershell (instead of directly). */
export async function createUpdateClientEncryptionKey(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
databaseName: string,
clientEncryptionKeyName: string,
body: Types.ClientEncryptionKeyCreateUpdateParameters
): Promise<Types.ClientEncryptionKeyGetResults | void> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/clientEncryptionKeys/${clientEncryptionKeyName}`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
}
/* Lists the SQL storedProcedure under an existing Azure Cosmos DB database account. */
export async function listSqlStoredProcedures(
subscriptionId: string,
@@ -204,7 +240,7 @@ export async function listSqlStoredProcedures(
accountName: string,
databaseName: string,
containerName: string
): Promise<Types.SqlStoredProcedureListResult> {
): Promise<Types.SqlStoredProcedureListResult | Types.CloudError> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases/${databaseName}/containers/${containerName}/storedProcedures`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
}

View File

@@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request";
import * as Types from "./types";
const apiVersion = "2021-04-15";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2023-04-15";
/* Lists the Tables under an existing Azure Cosmos DB database account. */
export async function listTables(

View File

@@ -3,9 +3,15 @@
Run "npm run generateARMClients" to regenerate
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/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2021-04-15/cosmos-db.json
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/2023-04-15/cosmos-db.json
*/
/* The List operation response, that contains the client encryption keys and their properties. */
export interface ClientEncryptionKeysListResult {
/* List of client encryption keys and their properties. */
readonly value?: ClientEncryptionKeyGetResults[];
}
/* The List operation response, that contains the database accounts and their properties. */
export interface DatabaseAccountsListResult {
/* List of database account and their properties. */
@@ -161,6 +167,30 @@ export interface ARMProxyResource {
readonly type?: string;
}
/* Parameters to create and update ClientEncryptionKey. */
export interface ClientEncryptionKeyCreateUpdateParameters {
/* Properties to create and update ClientEncryptionKey. */
properties: ClientEncryptionKeyCreateUpdateProperties;
}
/* Properties to create and update ClientEncryptionKey. */
export interface ClientEncryptionKeyCreateUpdateProperties {
/* The standard JSON format of a ClientEncryptionKey */
resource: ClientEncryptionKeyResource;
}
/* Client Encryption Key. */
export type ClientEncryptionKeyGetResults = ARMProxyResource & {
/* The properties of a ClientEncryptionKey */
properties?: ClientEncryptionKeyGetProperties;
};
/* The properties of a ClientEncryptionKey resource */
export interface ClientEncryptionKeyGetProperties {
/* undocumented */
resource?: ClientEncryptionKeyResource & ExtendedResourceProperties;
}
/* An Azure Cosmos DB database account. */
export type DatabaseAccountGetResults = ARMResourceProperties & {
/* Indicates the type of database account. This can only be set at database account creation. */
@@ -171,6 +201,9 @@ export type DatabaseAccountGetResults = ARMResourceProperties & {
/* undocumented */
properties?: DatabaseAccountGetProperties;
/* The system meta data relating to this resource. */
readonly systemData?: unknown;
};
/* The system generated resource properties associated with SQL databases, SQL containers, Gremlin databases and Gremlin graphs. */
@@ -446,6 +479,17 @@ export interface DatabaseAccountGetProperties {
/* Flag to indicate whether to enable storage analytics. */
enableAnalyticalStorage?: boolean;
/* Analytical storage specific properties. */
analyticalStorageConfiguration?: AnalyticalStorageConfiguration;
/* A unique identifier assigned to the database account */
readonly instanceId?: string;
/* Enum to indicate the mode of account creation. */
createMode?: CreateMode;
/* Parameters to indicate the information about the restore. */
restoreParameters?: RestoreParameters;
/* The object representing the policy for taking backups on an account. */
backupPolicy?: BackupPolicy;
@@ -457,6 +501,19 @@ export interface DatabaseAccountGetProperties {
/* An array that contains the Resource Ids for Network Acl Bypass for the Cosmos DB account. */
networkAclBypassResourceIds?: unknown[];
/* Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. */
disableLocalAuth?: boolean;
/* The object that represents all properties related to capacity enforcement on an account. */
capacity?: Capacity;
/* The object that represents the metadata for the Account Keys of the Cosmos DB account. */
keysMetadata?: DatabaseAccountKeysMetadata;
/* Flag to indicate enabling/disabling of Partition Merge feature on the account */
enablePartitionMerge?: boolean;
/* Indicates the minimum allowed Tls version. The default is Tls 1.0, except for Cassandra and Mongo API's, which only work with Tls 1.2. */
minimalTlsVersion?: MinimalTlsVersion;
}
/* Properties to create and update Azure Cosmos DB database accounts. */
@@ -506,6 +563,12 @@ export interface DatabaseAccountCreateUpdateProperties {
/* Flag to indicate whether to enable storage analytics. */
enableAnalyticalStorage?: boolean;
/* Analytical storage specific properties. */
analyticalStorageConfiguration?: AnalyticalStorageConfiguration;
/* Enum to indicate the mode of account creation. */
createMode?: CreateMode;
/* The object representing the policy for taking backups on an account. */
backupPolicy?: BackupPolicy;
@@ -517,6 +580,22 @@ export interface DatabaseAccountCreateUpdateProperties {
/* An array that contains the Resource Ids for Network Acl Bypass for the Cosmos DB account. */
networkAclBypassResourceIds?: unknown[];
/* Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. */
disableLocalAuth?: boolean;
/* Parameters to indicate the information about the restore. */
restoreParameters?: RestoreParameters;
/* The object that represents all properties related to capacity enforcement on an account. */
capacity?: Capacity;
/* This property is ignored during the update/create operation, as the metadata is read-only. The object represents the metadata for the Account Keys of the Cosmos DB account. */
keysMetadata?: DatabaseAccountKeysMetadata;
/* Flag to indicate enabling/disabling of Partition Merge feature on the account */
enablePartitionMerge?: boolean;
/* Indicates the minimum allowed Tls version. The default is Tls 1.0, except for Cassandra and Mongo API's, which only work with Tls 1.2. */
minimalTlsVersion?: MinimalTlsVersion;
}
/* Parameters to create and update Cosmos DB database accounts. */
@@ -575,6 +654,9 @@ export interface DatabaseAccountUpdateProperties {
/* Flag to indicate whether to enable storage analytics. */
enableAnalyticalStorage?: boolean;
/* Analytical storage specific properties. */
analyticalStorageConfiguration?: AnalyticalStorageConfiguration;
/* The object representing the policy for taking backups on an account. */
backupPolicy?: BackupPolicy;
@@ -586,6 +668,19 @@ export interface DatabaseAccountUpdateProperties {
/* An array that contains the Resource Ids for Network Acl Bypass for the Cosmos DB account. */
networkAclBypassResourceIds?: unknown[];
/* Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication. */
disableLocalAuth?: boolean;
/* The object that represents all properties related to capacity enforcement on an account. */
capacity?: Capacity;
/* This property is ignored during the update operation, as the metadata is read-only. The object represents the metadata for the Account Keys of the Cosmos DB account. */
keysMetadata?: DatabaseAccountKeysMetadata;
/* Flag to indicate enabling/disabling of Partition Merge feature on the account */
enablePartitionMerge?: boolean;
/* Indicates the minimum allowed Tls version. The default is Tls 1.0, except for Cassandra and Mongo API's, which only work with Tls 1.2. */
minimalTlsVersion?: MinimalTlsVersion;
}
/* Parameters for patching Azure Cosmos DB database account properties. */
@@ -624,6 +719,20 @@ export interface DatabaseAccountConnectionString {
readonly connectionString?: string;
/* Description of the connection string */
readonly description?: string;
/* Kind of the connection string key */
readonly keyKind?: "Primary" | "Secondary" | "PrimaryReadonly" | "SecondaryReadonly";
/* Type of the connection string */
readonly type?:
| "Sql"
| "Table"
| "MongoDB"
| "Cassandra"
| "CassandraConnectorMetadata"
| "Gremlin"
| "SqlDedicatedGateway"
| "GremlinV2"
| "Undefined";
}
/* The connection strings for the given database account. */
@@ -844,6 +953,10 @@ export interface ThroughputSettingsResource {
readonly minimumThroughput?: string;
/* The throughput replace is pending */
readonly offerReplacePending?: string;
/* The offer throughput value to instantly scale up without triggering splits */
readonly instantMaximumThroughput?: string;
/* The maximum throughput value or the maximum maxThroughput value (for autoscale) that can be specified */
readonly softAllowedMaximumThroughput?: string;
}
/* Cosmos DB provisioned throughput settings object */
@@ -879,6 +992,30 @@ export interface OptionsResource {
autoscaleSettings?: AutoscaleSettings;
}
/* Cosmos DB client encryption key resource object. */
export interface ClientEncryptionKeyResource {
/* Name of the ClientEncryptionKey */
id?: string;
/* Encryption algorithm that will be used along with this client encryption key to encrypt/decrypt data. */
encryptionAlgorithm?: string;
/* Wrapped (encrypted) form of the key represented as a byte array. */
wrappedDataEncryptionKey?: string;
/* Metadata for the wrapping provider that can be used to unwrap the wrapped client encryption key. */
keyWrapMetadata?: KeyWrapMetadata;
}
/* Represents key wrap metadata that a key wrapping provider can use to wrap/unwrap a client encryption key. */
export interface KeyWrapMetadata {
/* The name of associated KeyEncryptionKey (aka CustomerManagedKey). */
name?: string;
/* ProviderName of KeyStoreProvider. */
type?: string;
/* Reference / link to the KeyEncryptionKey. */
value?: string;
/* Algorithm used in wrapping and unwrapping of the data encryption key. */
algorithm?: string;
}
/* Cosmos DB SQL database resource object */
export interface SqlDatabaseResource {
/* Name of the Cosmos DB SQL database */
@@ -903,6 +1040,9 @@ export interface SqlContainerResource {
/* The conflict resolution policy for the container. */
conflictResolutionPolicy?: ConflictResolutionPolicy;
/* The client encryption policy for the container. */
clientEncryptionPolicy?: ClientEncryptionPolicy;
/* Analytical TTL. */
analyticalStorageTtl?: number;
}
@@ -1014,6 +1154,27 @@ export interface ConflictResolutionPolicy {
conflictResolutionProcedure?: string;
}
/* Cosmos DB client encryption policy. */
export interface ClientEncryptionPolicy {
/* Paths of the item that need encryption along with path-specific settings. */
includedPaths: ClientEncryptionIncludedPath[];
/* Version of the client encryption policy definition. Supported versions are 1 and 2. Version 2 supports id and partition key path encryption. */
policyFormatVersion: number;
}
/* . */
export interface ClientEncryptionIncludedPath {
/* Path that needs to be encrypted. */
path: string;
/* The identifier of the Client Encryption Key to be used to encrypt the path. */
clientEncryptionKeyId: string;
/* The type of encryption to be performed. Eg - Deterministic, Randomized. */
encryptionType: string;
/* The encryption algorithm which will be used. Eg - AEAD_AES_256_CBC_HMAC_SHA256. */
encryptionAlgorithm: string;
}
/* Cosmos DB SQL storedProcedure resource object */
export interface SqlStoredProcedureResource {
/* Name of the Cosmos DB SQL storedProcedure */
@@ -1035,7 +1196,7 @@ export interface SqlTriggerResource {
/* Name of the Cosmos DB SQL trigger */
id: string;
/* Body of the Trigger */
body: string;
body?: string;
/* Type of the Trigger */
triggerType?: "Pre" | "Post";
@@ -1174,6 +1335,9 @@ export interface GremlinGraphResource {
/* The conflict resolution policy for the graph. */
conflictResolutionPolicy?: ConflictResolutionPolicy;
/* Analytical TTL. */
analyticalStorageTtl?: number;
}
/* CreateUpdateOptions are a list of key-value pairs that describe the resource. Supported keys are "If-Match", "If-None-Match", "Session-Token" and "Throughput" */
@@ -1196,6 +1360,12 @@ export interface Capability {
name?: string;
}
/* The object that represents all properties related to capacity enforcement on an account. */
export interface Capacity {
/* The total throughput limit imposed on the account. A totalThroughputLimit of 2000 imposes a strict limit of max throughput that can be provisioned on that account to be 2000. A totalThroughputLimit of -1 indicates no limits on provisioning of throughput. */
totalThroughputLimit?: number;
}
/* Tags are a list of key-value pairs that describe the resource. These tags can be used in viewing and grouping this resource (across resource groups). A maximum of 15 tags can be provided for a resource. Each tag must have a key no greater than 128 characters and value no greater than 256 characters. For example, the default experience for a template type is set with "defaultExperience": "Cassandra". Current "defaultExperience" values also include "Table", "Graph", "DocumentDB", and "MongoDB". */
export type Tags = { [key: string]: string };
@@ -1235,6 +1405,27 @@ export interface VirtualNetworkRule {
/* Indicates what services are allowed to bypass firewall checks. */
export type NetworkAclBypass = "None" | "AzureServices";
/* The metadata related to an access key for a given database account. */
export interface AccountKeyMetadata {
/* Generation time in UTC of the key in ISO-8601 format. If the value is missing from the object, it means that the last key regeneration was triggered before 2022-06-18. */
readonly generationTime?: string;
}
/* The metadata related to each access key for the given Cosmos DB database account. */
export interface DatabaseAccountKeysMetadata {
/* The metadata related to the Primary Read-Write Key for the given Cosmos DB database account. */
readonly primaryMasterKey?: AccountKeyMetadata;
/* The metadata related to the Secondary Read-Write Key for the given Cosmos DB database account. */
readonly secondaryMasterKey?: AccountKeyMetadata;
/* The metadata related to the Primary Read-Only Key for the given Cosmos DB database account. */
readonly primaryReadonlyMasterKey?: AccountKeyMetadata;
/* The metadata related to the Secondary Read-Only Key for the given Cosmos DB database account. */
readonly secondaryReadonlyMasterKey?: AccountKeyMetadata;
}
/* REST API operation */
export interface Operation {
/* Operation name: {provider}/{resource}/{operation} */
@@ -1430,23 +1621,97 @@ export type UnitType = "Count" | "Bytes" | "Seconds" | "Percent" | "CountPerSeco
export type ConnectorOffer = "Small";
/* Whether requests from Public Network are allowed */
export type PublicNetworkAccess = "Enabled" | "Disabled";
export type PublicNetworkAccess = "Enabled" | "Disabled" | "SecuredByPerimeter";
/* undocumented */
export interface ApiProperties {
/* Describes the ServerVersion of an a MongoDB account. */
serverVersion?: "3.2" | "3.6" | "4.0";
serverVersion?: "3.2" | "3.6" | "4.0" | "4.2";
}
/* Analytical storage specific properties. */
export interface AnalyticalStorageConfiguration {
/* undocumented */
schemaType?: AnalyticalStorageSchemaType;
}
/* Describes the types of schema for analytical storage. */
export type AnalyticalStorageSchemaType = "WellDefined" | "FullFidelity";
/* Enum to indicate the mode of account creation. */
export type CreateMode = "Default" | "Restore";
/* Parameters to indicate the information about the restore. */
export interface RestoreParameters {
/* Describes the mode of the restore. */
restoreMode?: "PointInTime";
/* The id of the restorable database account from which the restore has to be initiated. For example: /subscriptions/{subscriptionId}/providers/Microsoft.DocumentDB/locations/{location}/restorableDatabaseAccounts/{restorableDatabaseAccountName} */
restoreSource?: string;
/* Time to which the account has to be restored (ISO-8601 format). */
restoreTimestampInUtc?: string;
/* List of specific databases available for restore. */
databasesToRestore?: DatabaseRestoreResource[];
/* List of specific gremlin databases available for restore. */
gremlinDatabasesToRestore?: GremlinDatabaseRestoreResource[];
/* List of specific tables available for restore. */
tablesToRestore?: TableName[];
}
/* Specific Databases to restore. */
export interface DatabaseRestoreResource {
/* The name of the database available for restore. */
databaseName?: string;
/* The names of the collections available for restore. */
collectionNames?: CollectionName[];
}
/* Specific Gremlin Databases to restore. */
export interface GremlinDatabaseRestoreResource {
/* The name of the gremlin database available for restore. */
databaseName?: string;
/* The names of the graphs available for restore. */
graphNames?: GraphName[];
}
/* The name of the collection. */
export type CollectionName = string;
/* The name of the graph. */
export type GraphName = string;
/* The name of the table. */
export type TableName = string;
/* The object representing the policy for taking backups on an account. */
export interface BackupPolicy {
/* undocumented */
/* Describes the mode of backups. */
type: BackupPolicyType;
/* The object representing the state of the migration between the backup policies. */
migrationState?: BackupPolicyMigrationState;
}
/* Describes the mode of backups. */
export type BackupPolicyType = "Periodic" | "Continuous";
/* The object representing the state of the migration between the backup policies. */
export interface BackupPolicyMigrationState {
/* Describes the status of migration between backup policy types. */
status?: BackupPolicyMigrationStatus;
/* Describes the target backup policy type of the backup policy migration. */
targetType?: BackupPolicyType;
/* Time at which the backup policy migration started (ISO-8601 format). */
startTime?: string;
}
/* Describes the status of migration between backup policy types. */
export type BackupPolicyMigrationStatus = "Invalid" | "InProgress" | "Completed" | "Failed";
/* The object representing periodic mode backup policy. */
export type PeriodicModeBackupPolicy = BackupPolicy & {
/* Configuration values for periodic mode backup */
@@ -1454,7 +1719,10 @@ export type PeriodicModeBackupPolicy = BackupPolicy & {
};
/* The object representing continuous mode backup policy. */
export type ContinuousModeBackupPolicy = BackupPolicy;
export type ContinuousModeBackupPolicy = BackupPolicy & {
/* Configuration values for continuous mode backup */
continuousModeProperties?: ContinuousModeProperties;
};
/* Configuration values for periodic mode backup */
export interface PeriodicModeProperties {
@@ -1462,4 +1730,50 @@ export interface PeriodicModeProperties {
backupIntervalInMinutes?: number;
/* An integer representing the time (in hours) that each backup is retained */
backupRetentionIntervalInHours?: number;
/* Enum to indicate type of backup residency */
backupStorageRedundancy?: BackupStorageRedundancy;
}
/* Configuration values for periodic mode backup */
export interface ContinuousModeProperties {
/* Enum to indicate type of Continuous backup mode */
tier?: ContinuousTier;
}
/* The List operation response, that contains Cosmos DB locations and their properties. */
export interface LocationListResult {
/* List of Cosmos DB locations and their properties. */
readonly value?: LocationGetResult[];
}
/* Cosmos DB location get result */
export type LocationGetResult = ARMProxyResource & {
/* Cosmos DB location metadata */
properties?: LocationProperties;
};
/* Cosmos DB location metadata */
export interface LocationProperties {
/* Flag indicating whether the location supports availability zones or not. */
readonly supportsAvailabilityZone?: boolean;
/* Flag indicating whether the location is residency sensitive. */
readonly isResidencyRestricted?: boolean;
/* The properties of available backup storage redundancies. */
readonly backupStorageRedundancies?: BackupStorageRedundancy[];
/* Flag indicating whether the subscription have access in region for Non-Availability Zones. */
readonly isSubscriptionRegionAccessAllowedForRegular?: boolean;
/* Flag indicating whether the subscription have access in region for Availability Zones(Az). */
readonly isSubscriptionRegionAccessAllowedForAz?: boolean;
/* Enum to indicate current buildout status of the region. */
readonly status?: "Uninitialized" | "Initializing" | "InternallyReady" | "Online" | "Deleting";
}
/* Enum to indicate type of backup storage redundancy. */
export type BackupStorageRedundancy = "Geo" | "Local" | "Zone";
/* Enum to indicate type of Continuous backup tier. */
export type ContinuousTier = "Continuous7Days" | "Continuous30Days";
/* Indicates the minimum allowed Tls version. The default is Tls 1.0, except for Cassandra and Mongo API's, which only work with Tls 1.2. */
export type MinimalTlsVersion = "Tls" | "Tls11" | "Tls12";

View File

@@ -0,0 +1,25 @@
import create, { UseStore } from "zustand";
interface QueryCopilotState {
generatedQuery: string;
likeQuery: boolean;
userPrompt: string;
showFeedbackModal: boolean;
hideFeedbackModalForLikedQueries: boolean;
openFeedbackModal: (generatedQuery: string, likeQuery: boolean, userPrompt: string) => void;
closeFeedbackModal: () => void;
setHideFeedbackModalForLikedQueries: (hideFeedbackModalForLikedQueries: boolean) => void;
}
export const useQueryCopilot: UseStore<QueryCopilotState> = create((set) => ({
generatedQuery: "",
likeQuery: false,
userPrompt: "",
showFeedbackModal: false,
hideFeedbackModalForLikedQueries: false,
openFeedbackModal: (generatedQuery: string, likeQuery: boolean, userPrompt: string) =>
set({ generatedQuery, likeQuery, userPrompt, showFeedbackModal: true }),
closeFeedbackModal: () => set({ generatedQuery: "", likeQuery: false, userPrompt: "", showFeedbackModal: false }),
setHideFeedbackModalForLikedQueries: (hideFeedbackModalForLikedQueries: boolean) =>
set({ hideFeedbackModalForLikedQueries }),
}));

View File

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

View File

@@ -16,10 +16,15 @@ Results of this file should be checked into the repo.
*/
// CHANGE THESE VALUES TO GENERATE NEW CLIENTS
const version = "2021-04-15";
const resourceName = "cosmosNotebooks";
const schemaURL = `https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/${version}/notebook.json`;
const outputDir = path.join(__dirname, `../../src/Utils/arm/generatedClients/${resourceName}/${version}`);
const version = "2023-04-15";
/* The following are legal options for resourceName but you generally will only use cosmos-db:
"cosmos-db" | "managedCassandra" | "mongorbac" | "notebook" | "privateEndpointConnection" | "privateLinkResources" |
"rbac" | "restorable" | "services"
*/
const githubResourceName = "cosmos-db";
const deResourceName = "cosmos";
const schemaURL = `https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/${version}/${githubResourceName}.json`;
const outputDir = path.join(__dirname, `../../src/Utils/arm/generatedClients/${deResourceName}`);
// Array of strings to use for eventual output
const outputTypes: string[] = [""];
@@ -142,7 +147,7 @@ const propertyToType = (property: Property, prop: string, required: boolean) =>
`);
} else {
if (property.type === undefined) {
console.log(`UHANDLED TYPE: ${prop}. Falling back to unknown`);
console.log(`generator.ts - UNHANDLED TYPE: ${prop}. Falling back to unknown`);
property.type = "unknown";
}
outputTypes.push(`
@@ -209,7 +214,7 @@ async function main() {
export type ${definition} = ${type}
`);
} else {
console.log("UNHANDLED MODEL:", def, schema.definitions[def]);
console.log("generator.ts - UNHANDLED MODEL:", def, schema.definitions[def]);
}
}
}
@@ -233,9 +238,9 @@ async function main() {
// Write all grouped fetch functions to objects
for (const clientName in clients) {
const outputClient: string[] = [""];
outputClient.push(`import { armRequest } from "../../../request"\n`);
outputClient.push(`import { armRequest } from "../../request"\n`);
outputClient.push(`import * as Types from "./types"\n`);
outputClient.push(`import { configContext } from "../../../../../ConfigContext";\n`);
outputClient.push(`import { configContext } from "../../../../ConfigContext";\n`);
outputClient.push(`const apiVersion = "${version}"\n\n`);
for (const path of clients[clientName].paths) {
for (const method in schema.paths[path]) {