Compare commits
1 Commits
add-dp-rba
...
users/lang
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa865f99c8 |
@@ -145,5 +145,4 @@ src/Explorer/Notebook/temp/inputs/connected-editors/codemirror.tsx
|
||||
src/Explorer/Tree/ResourceTreeAdapter.tsx
|
||||
__mocks__/monaco-editor.ts
|
||||
src/Explorer/Tree/ResourceTree.tsx
|
||||
src/Utils/EndpointUtils.ts
|
||||
src/Utils/PriorityBasedExecutionUtils.ts
|
||||
@@ -53,9 +53,4 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: "detect",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
80
.github/workflows/ci.yml
vendored
@@ -14,11 +14,11 @@ jobs:
|
||||
name: "Log Code Metrics"
|
||||
if: github.ref == 'refs/heads/master'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 14.x
|
||||
- run: npm ci
|
||||
- run: node utils/codeMetrics.js
|
||||
env:
|
||||
@@ -27,11 +27,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Compile TypeScript"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 14.x
|
||||
- run: npm ci
|
||||
- run: npm run compile
|
||||
- run: npm run compile:strict
|
||||
@@ -39,44 +39,44 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Check Format"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 14.x
|
||||
- run: npm ci
|
||||
- run: npm run format:check
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Lint"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 14.x
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
unittest:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Unit Tests"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 14.x
|
||||
- run: npm ci
|
||||
- run: npm run test
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Build"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 14.x
|
||||
- run: npm ci
|
||||
- run: npm run build:contracts
|
||||
- name: Restore Build Cache
|
||||
@@ -85,11 +85,9 @@ jobs:
|
||||
path: .cache
|
||||
key: ${{ runner.os }}-build-cache
|
||||
- run: npm run pack:prod
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=4096"
|
||||
- run: cp -r ./Contracts ./dist/contracts
|
||||
- run: cp -r ./configs ./dist/configs
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
@@ -107,11 +105,11 @@ jobs:
|
||||
if: false
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 14.x
|
||||
- uses: southpolesteve/cosmos-emulator-github-action@v1
|
||||
- name: End to End Tests
|
||||
run: |
|
||||
@@ -124,7 +122,7 @@ jobs:
|
||||
DATA_EXPLORER_ENDPOINT: "https://localhost:1234/explorer.html?platform=Emulator"
|
||||
PLATFORM: "Emulator"
|
||||
NODE_TLS_REJECT_UNAUTHORIZED: 0
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: screenshots
|
||||
@@ -149,11 +147,11 @@ jobs:
|
||||
- ./test/sql/resourceToken.spec.ts
|
||||
- ./test/tables/container.spec.ts
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js 18.x
|
||||
uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 14.x
|
||||
- run: npm ci
|
||||
- run: npm start &
|
||||
- run: npm run wait-for-server
|
||||
@@ -162,7 +160,7 @@ jobs:
|
||||
# Run tests up to three times
|
||||
for i in $(seq 1 3); do npx jest -c ./jest.config.playwright.js ${{ matrix['test-file'] }} && s=0 && break || s=$? && sleep 1; done; (exit $s)
|
||||
shell: bash
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: screenshots
|
||||
@@ -180,14 +178,14 @@ jobs:
|
||||
with:
|
||||
nuget-api-key: ${{ secrets.NUGET_API_KEY }}
|
||||
- name: Download Dist Folder
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
- run: cp ./configs/prod.json config.json
|
||||
- run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "jawelton@microsoft.com" -Password "$AZURE_DEVOPS_PAT"
|
||||
- run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}"
|
||||
- run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v2
|
||||
name: packages
|
||||
with:
|
||||
path: "*.nupkg"
|
||||
@@ -204,7 +202,7 @@ jobs:
|
||||
with:
|
||||
nuget-api-key: ${{ secrets.NUGET_API_KEY }}
|
||||
- name: Download Dist Folder
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
- run: cp ./configs/mpac.json config.json
|
||||
@@ -212,7 +210,7 @@ jobs:
|
||||
- run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "jawelton@microsoft.com" -Password "$AZURE_DEVOPS_PAT"
|
||||
- run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}"
|
||||
- run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v2
|
||||
name: packages
|
||||
with:
|
||||
path: "*.nupkg"
|
||||
|
||||
4
.github/workflows/cleanup.yml
vendored
@@ -20,9 +20,9 @@ jobs:
|
||||
NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET: ${{ secrets.NOTEBOOKS_TEST_RUNNER_CLIENT_SECRET }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 14.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 14.x
|
||||
- run: npm ci
|
||||
- run: node utils/cleanupDBs.js
|
||||
|
||||
7
.vscode/settings.json
vendored
@@ -20,9 +20,8 @@
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.organizeImports": "explicit"
|
||||
"source.fixAll.eslint": true,
|
||||
"source.organizeImports": true
|
||||
},
|
||||
"typescript.preferences.importModuleSpecifier": "non-relative",
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"typescript.preferences.importModuleSpecifier": "non-relative"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"JUNO_ENDPOINT": "https://tools.cosmos.azure.com",
|
||||
"isTerminalEnabled": true,
|
||||
"isPhoenixEnabled": true
|
||||
}
|
||||
"JUNO_ENDPOINT": "https://tools-staging.cosmos.azure.com",
|
||||
"isTerminalEnabled" : true,
|
||||
"isPhoenixEnabled" : true
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.3626 11.9771C13.1573 11.9837 13.019 12.0288 12.9215 12.0836C12.817 12.1424 12.7301 12.229 12.6508 12.3542C12.4802 12.6239 12.3837 12.9957 12.252 13.5033L12.2347 13.5699C12.1079 14.0581 11.9424 14.6764 11.5775 15.1594C11.1788 15.687 10.5903 16 9.74835 16H4.63681C3.55423 16 2.75741 15.2435 2.18373 14.3271C1.60629 13.4047 1.17786 12.2045 0.845481 11.0542L0.845003 11.0525C0.464365 9.73512 -0.017355 8.06787 0.000479698 6.72244C0.00951195 6.04103 0.145994 5.34953 0.569528 4.825C1.00712 4.28305 1.66518 4.02294 2.50365 4.02294H2.63739C2.84267 4.01631 2.98102 3.97123 3.07848 3.9164C3.18305 3.85757 3.26995 3.77102 3.34916 3.64584C3.51985 3.37613 3.61631 3.00432 3.74801 2.49671L3.76529 2.43012C3.89213 1.94191 4.05757 1.32365 4.42251 0.840633C4.82119 0.312966 5.40972 0 6.25165 0H11.3632C12.4458 0 13.2426 0.756543 13.8163 1.67295C14.3937 2.59534 14.8221 3.79546 15.1545 4.94582L15.155 4.94748C15.5356 6.26488 16.0174 7.93213 15.9995 9.27756C15.9905 9.95897 15.854 10.6505 15.4305 11.175C14.9929 11.717 14.3348 11.9771 13.4963 11.9771H13.3626ZM14.1354 5.28381C13.8114 4.16251 13.4194 3.09096 12.9303 2.3096C12.4374 1.52225 11.9215 1.14296 11.3632 1.14296H7.95613C8.10274 1.42082 8.22537 1.731 8.33548 2.05199C8.48008 2.47355 8.61427 2.94842 8.75233 3.43699L8.78302 3.54557C9.32758 5.47082 10.008 7.94794 10.4498 9.5646C10.6507 10.2998 11.2693 10.8098 11.9798 10.8333H13.4156C13.4253 10.8333 13.4351 10.8335 13.4447 10.8341H13.4963C14.1298 10.8341 14.4484 10.6443 14.6237 10.4272C14.813 10.1928 14.9255 9.8162 14.9328 9.26133C14.9477 8.13479 14.5323 6.65749 14.1354 5.28381ZM3.06972 13.6904C3.56261 14.4777 4.0785 14.857 4.63681 14.857H8.04387C7.89726 14.5792 7.77463 14.269 7.66452 13.948C7.51992 13.5265 7.38573 13.0516 7.24767 12.563L7.21698 12.4544C6.67242 10.5292 5.99197 8.05206 5.55019 6.4354C5.34929 5.70024 4.73069 5.19015 4.02018 5.16674H2.58445C2.57465 5.16674 2.56492 5.16646 2.55526 5.1659H2.50365C1.87025 5.1659 1.5516 5.35572 1.37634 5.57277C1.18703 5.80723 1.07454 6.1838 1.06719 6.73867C1.05225 7.86521 1.46769 9.34251 1.86459 10.7162C2.18857 11.8375 2.58057 12.909 3.06972 13.6904ZM9.10298 10.8333H9.87304C9.67506 10.5554 9.5217 10.236 9.42598 9.88575C9.233 9.17956 8.99466 8.30985 8.74215 7.39421L8.47331 6.42622C8.26579 5.67902 7.62465 5.16674 6.89702 5.16674H6.12695C6.32494 5.44463 6.4783 5.76395 6.57402 6.11425C6.767 6.82044 7.00534 7.69015 7.25785 8.60579L7.52669 9.57378C7.73421 10.321 8.37535 10.8333 9.10298 10.8333ZM6.89702 4.02378C7.23212 4.02378 7.55609 4.08968 7.85646 4.21152C7.82459 4.0984 7.7931 3.98682 7.76205 3.87706L7.73417 3.77844C7.59304 3.27914 7.46754 2.83514 7.33414 2.44626C7.19129 2.02979 7.05211 1.71602 6.90214 1.4942C6.77014 1.29897 6.56087 1.14296 6.25165 1.14296C5.69009 1.14296 5.42306 1.33297 5.2517 1.55976C5.04661 1.83121 4.92755 2.21889 4.79304 2.73662C4.78284 2.77588 4.77249 2.81622 4.76191 2.85744C4.66966 3.21703 4.55997 3.64464 4.37733 4.02378H6.89702ZM9.10298 11.9762C8.76788 11.9762 8.44391 11.9103 8.14354 11.7885C8.1754 11.9016 8.2069 12.0132 8.23795 12.1229L8.26583 12.2216C8.40696 12.7208 8.53246 13.1649 8.66585 13.5537C8.80871 13.9702 8.94789 14.284 9.09786 14.5058C9.22986 14.701 9.43913 14.857 9.74835 14.857C10.3099 14.857 10.5769 14.667 10.7483 14.4402C10.9534 14.1688 11.0725 13.7811 11.207 13.2634C11.2172 13.2241 11.2275 13.1838 11.2381 13.1426C11.3303 12.783 11.44 12.3554 11.6227 11.9762H9.10298Z" fill="#0078D4"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
@@ -1,3 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.31299 1.26164C7.69849 0.897163 8.30151 0.897163 8.68701 1.26164L13.5305 5.84098C13.8302 6.12431 14 6.51853 14 6.93094V12.5002C14 13.3286 13.3284 14.0002 12.5 14.0002H10.5C9.67157 14.0002 9 13.3286 9 12.5002V10.0002C9 9.72407 8.77614 9.50021 8.5 9.50021H7.5C7.22386 9.50021 7 9.72407 7 10.0002V12.5002C7 13.3286 6.32843 14.0002 5.5 14.0002H3.5C2.67157 14.0002 2 13.3286 2 12.5002V6.93094C2 6.51853 2.1698 6.12431 2.46948 5.84098L7.31299 1.26164ZM8 1.98828L3.15649 6.56762C3.0566 6.66207 3 6.79347 3 6.93094V12.5002C3 12.7763 3.22386 13.0002 3.5 13.0002H5.5C5.77614 13.0002 6 12.7763 6 12.5002V10.0002C6 9.17179 6.67157 8.50022 7.5 8.50022H8.5C9.32843 8.50022 10 9.17179 10 10.0002V12.5002C10 12.7763 10.2239 13.0002 10.5 13.0002H12.5C12.7761 13.0002 13 12.7763 13 12.5002V6.93094C13 6.79347 12.9434 6.66207 12.8435 6.56762L8 1.98828Z" fill="#0078D4" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 968 B |
@@ -1,40 +1,34 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="34px" height="34px" viewBox="0 0 34 34" version="1.1">
|
||||
<svg width="32" height="34" viewBox="0 0 32 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13 0.739258L16 1.04436V9.68622L11.2 10.8013L9.60002 12.9967V16.4479C9.60002 18.7669 10.8545 20.9045 12.879 22.0353L17.4036 24.5626L9.6 28.69L6.35592 29.1523L3.27902 27.4337C1.25445 26.3028 0 24.1652 0 21.8462V11.7591C0 9.43952 1.25512 7.30147 3.28055 6.17085L12.3174 1.12639L12.3121 1.13012L13 0.739258Z" fill="url(#paint0_radial_857_143948)"/>
|
||||
<path d="M13 0.739258L16 1.04436V9.68622L11.2 10.8013L9.60002 12.9967V16.4479C9.60002 18.7669 10.8545 20.9045 12.879 22.0353L17.4036 24.5626L9.6 28.69L6.35592 29.1523L3.27902 27.4337C1.25445 26.3028 0 24.1652 0 21.8462V11.7591C0 9.43952 1.25512 7.30147 3.28055 6.17085L12.3174 1.12639L12.3121 1.13012L13 0.739258Z" fill="url(#paint1_linear_857_143948)"/>
|
||||
<path d="M22.399 12.001L30.399 16.801L31.999 18.401V21.8452C31.999 24.1642 30.7446 26.3018 28.72 27.4327L19.12 32.7949C17.1804 33.8784 14.8177 33.8784 12.878 32.7949L3.27804 27.4327C3.09146 27.3284 2.91141 27.2157 2.73828 27.095L3.278 27.3965C5.21762 28.4799 7.58035 28.4799 9.51996 27.3965L19.12 22.0342C21.1445 20.9033 22.399 18.7657 22.399 16.4467V12.001Z" fill="url(#paint2_radial_857_143948)"/>
|
||||
<path d="M22.399 12.001L30.399 16.801L31.999 18.401V21.8452C31.999 24.1642 30.7446 26.3018 28.72 27.4327L19.12 32.7949C17.1804 33.8784 14.8177 33.8784 12.878 32.7949L3.27804 27.4327C3.09146 27.3284 2.91141 27.2157 2.73828 27.095L3.278 27.3965C5.21762 28.4799 7.58035 28.4799 9.51996 27.3965L19.12 22.0342C21.1445 20.9033 22.399 18.7657 22.399 16.4467V12.001Z" fill="url(#paint3_linear_857_143948)"/>
|
||||
<path d="M28.7191 6.17053L19.119 0.811705C17.1802 -0.270568 14.819 -0.270568 12.8802 0.811704L12.3151 1.1271C10.6239 2.31737 9.59961 4.26472 9.59961 6.36025V13.0461L12.8802 11.2149C14.819 10.1326 17.1802 10.1326 19.119 11.2149L28.7191 16.5737C30.6984 17.6786 31.9421 19.7456 31.9977 22.0039C31.999 21.9514 31.9996 21.8987 31.9996 21.8459V11.7588C31.9996 9.4392 30.7445 7.30115 28.7191 6.17053Z" fill="url(#paint4_radial_857_143948)"/>
|
||||
<path d="M28.7191 6.17053L19.119 0.811705C17.1802 -0.270568 14.819 -0.270568 12.8802 0.811704L12.3151 1.1271C10.6239 2.31737 9.59961 4.26472 9.59961 6.36025V13.0461L12.8802 11.2149C14.819 10.1326 17.1802 10.1326 19.119 11.2149L28.7191 16.5737C30.6984 17.6786 31.9421 19.7456 31.9977 22.0039C31.999 21.9514 31.9996 21.8987 31.9996 21.8459V11.7588C31.9996 9.4392 30.7445 7.30115 28.7191 6.17053Z" fill="url(#paint5_linear_857_143948)"/>
|
||||
<defs>
|
||||
<radialGradient id="radial0" gradientUnits="userSpaceOnUse" cx="0" cy="0" fx="0" fy="0" r="1" gradientTransform="matrix(-7.787324,-9.624098,9.028449,-7.305356,26.915817,14.703725)">
|
||||
<stop offset="0.0955758" style="stop-color:rgb(0%,47.058824%,83.137255%);stop-opacity:1;"/>
|
||||
<stop offset="0.715277" style="stop-color:rgb(4.705882%,43.921569%,60.784314%);stop-opacity:1;"/>
|
||||
<stop offset="1" style="stop-color:rgb(3.921569%,31.372549%,47.45098%);stop-opacity:1;"/>
|
||||
<radialGradient id="paint0_radial_857_143948" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(13.5054 9.8837) rotate(112.544) scale(23.4519 19.3067)">
|
||||
<stop offset="0.206732" stop-color="#4995D0"/>
|
||||
<stop offset="0.875628" stop-color="#0078D4"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="radial1" gradientUnits="userSpaceOnUse" cx="0" cy="0" fx="0" fy="0" r="1" gradientTransform="matrix(7.955722,8.152531,-8.011265,7.817866,7.897393,23.013892)">
|
||||
<stop offset="0" style="stop-color:rgb(0%,56.862745%,92.156863%);stop-opacity:1;"/>
|
||||
<stop offset="0.523516" style="stop-color:rgb(15.294118%,39.215686%,90.588235%);stop-opacity:1;"/>
|
||||
<stop offset="0.923392" style="stop-color:rgb(2.352941%,21.176471%,76.470588%);stop-opacity:1;"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="linear0" gradientUnits="userSpaceOnUse" x1="5.16831" y1="2" x2="7.75605" y2="17.2359" gradientTransform="matrix(1.416667,0,0,1.416667,0,0)">
|
||||
<stop offset="0.289817" style="stop-color:rgb(0%,64.705882%,85.098039%);stop-opacity:1;"/>
|
||||
<stop offset="0.662336" style="stop-color:rgb(12.941176%,79.215686%,69.803922%);stop-opacity:1;"/>
|
||||
<stop offset="0.950002" style="stop-color:rgb(41.568627%,86.27451%,56.470588%);stop-opacity:1;"/>
|
||||
<linearGradient id="paint1_linear_857_143948" x1="11.0625" y1="26.6174" x2="9.78695" y2="24.2436" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.9999" stop-color="#0078D4"/>
|
||||
<stop offset="1" stop-color="#0078D4" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear1" gradientUnits="userSpaceOnUse" x1="7.25046" y1="2" x2="7.87502" y2="16.4401" gradientTransform="matrix(1.416667,0,0,1.416667,0,0)">
|
||||
<stop offset="0" style="stop-color:rgb(6.27451%,78.823529%,92.54902%);stop-opacity:1;"/>
|
||||
<stop offset="0.166667" style="stop-color:rgb(0.392157%,68.235294%,89.411765%);stop-opacity:0;"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="radial2" gradientUnits="userSpaceOnUse" cx="0" cy="0" fx="0" fy="0" r="1" gradientTransform="matrix(-9.930588,25.254205,-30.30117,-11.915182,29.269325,8.70791)">
|
||||
<stop offset="0.154405" style="stop-color:rgb(15.294118%,44.313725%,84.705882%);stop-opacity:1;"/>
|
||||
<stop offset="0.678875" style="stop-color:rgb(7.843137%,69.411765%,100%);stop-opacity:1;"/>
|
||||
<stop offset="0.931138" style="stop-color:rgb(8.627451%,74.901961%,87.45098%);stop-opacity:1;"/>
|
||||
<radialGradient id="paint2_radial_857_143948" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(6.899 24.5214) rotate(-3.9995) scale(24.6197 15.4594)">
|
||||
<stop offset="0.140029" stop-color="#80C8FF"/>
|
||||
<stop offset="0.952721" stop-color="#0078D4"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="linear2" gradientUnits="userSpaceOnUse" x1="21.2403" y1="7.01008" x2="20.306" y2="12.5802" gradientTransform="matrix(1.416667,0,0,1.416667,0,0)">
|
||||
<stop offset="0.0581535" style="stop-color:rgb(7.843137%,69.411765%,100%);stop-opacity:1;"/>
|
||||
<stop offset="0.708063" style="stop-color:rgb(16.078431%,46.27451%,85.882353%);stop-opacity:0;"/>
|
||||
<linearGradient id="paint3_linear_857_143948" x1="26.8932" y1="15.5508" x2="25.5491" y2="17.8921" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.9999" stop-color="#3F8AC3"/>
|
||||
<stop offset="1" stop-color="#8C66BA" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="paint4_radial_857_143948" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(26.632 16.3878) rotate(-138.33) scale(22.8015 13.0047)">
|
||||
<stop stop-color="#7BC6FF"/>
|
||||
<stop offset="0.839255" stop-color="#0078D4"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="paint5_linear_857_143948" x1="9.59961" y1="8.71337" x2="12.2131" y2="8.71337" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.9999" stop-color="#0078D4"/>
|
||||
<stop offset="1" stop-color="#436DCD" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="surface1">
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:url(#radial0);" d="M 24.1875 5.1875 C 23.777344 3.792969 22.496094 2.832031 21.039062 2.832031 L 20.078125 2.832031 C 18.496094 2.832031 17.140625 3.960938 16.855469 5.519531 L 15.175781 14.625 L 15.628906 13.066406 C 16.039062 11.664062 17.320312 10.703125 18.777344 10.703125 L 24.335938 10.703125 L 26.667969 11.613281 L 28.917969 10.703125 L 28.261719 10.703125 C 26.804688 10.703125 25.523438 9.746094 25.113281 8.347656 Z M 24.1875 5.1875 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:url(#radial1);" d="M 10.152344 28.796875 C 10.558594 30.199219 11.839844 31.167969 13.300781 31.167969 L 15.359375 31.167969 C 17.128906 31.167969 18.578125 29.765625 18.636719 27.996094 L 18.941406 19.011719 L 18.371094 20.945312 C 17.960938 22.339844 16.679688 23.296875 15.226562 23.296875 L 9.613281 23.296875 L 7.613281 22.210938 L 5.449219 23.296875 L 6.09375 23.296875 C 7.554688 23.296875 8.839844 24.261719 9.246094 25.664062 Z M 10.152344 28.796875 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear0);" d="M 20.898438 2.832031 L 9.535156 2.832031 C 6.289062 2.832031 4.339844 7.121094 3.042969 11.410156 C 1.503906 16.492188 -0.507812 23.289062 5.316406 23.289062 L 10.222656 23.289062 C 11.6875 23.289062 12.972656 22.320312 13.375 20.910156 C 14.230469 17.929688 15.722656 12.722656 16.898438 8.761719 C 17.496094 6.75 17.992188 5.019531 18.753906 3.941406 C 19.183594 3.339844 19.894531 2.832031 20.898438 2.832031 Z M 20.898438 2.832031 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear1);" d="M 20.898438 2.832031 L 9.535156 2.832031 C 6.289062 2.832031 4.339844 7.121094 3.042969 11.410156 C 1.503906 16.492188 -0.507812 23.289062 5.316406 23.289062 L 10.222656 23.289062 C 11.6875 23.289062 12.972656 22.320312 13.375 20.910156 C 14.230469 17.929688 15.722656 12.722656 16.898438 8.761719 C 17.496094 6.75 17.992188 5.019531 18.753906 3.941406 C 19.183594 3.339844 19.894531 2.832031 20.898438 2.832031 Z M 20.898438 2.832031 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:url(#radial2);" d="M 13.101562 31.167969 L 24.464844 31.167969 C 27.710938 31.167969 29.660156 26.878906 30.957031 22.589844 C 32.496094 17.507812 34.507812 10.710938 28.6875 10.710938 L 23.78125 10.710938 C 22.3125 10.710938 21.027344 11.679688 20.625 13.089844 C 19.769531 16.074219 18.277344 21.277344 17.101562 25.238281 C 16.503906 27.253906 16.007812 28.980469 15.246094 30.058594 C 14.816406 30.660156 14.105469 31.167969 13.101562 31.167969 Z M 13.101562 31.167969 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear2);" d="M 13.101562 31.167969 L 24.464844 31.167969 C 27.710938 31.167969 29.660156 26.878906 30.957031 22.589844 C 32.496094 17.507812 34.507812 10.710938 28.6875 10.710938 L 23.78125 10.710938 C 22.3125 10.710938 21.027344 11.679688 20.625 13.089844 C 19.769531 16.074219 18.277344 21.277344 17.101562 25.238281 C 16.503906 27.253906 16.007812 28.980469 15.246094 30.058594 C 14.816406 30.660156 14.105469 31.167969 13.101562 31.167969 Z M 13.101562 31.167969 "/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 4.0 KiB |
@@ -1,20 +0,0 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.11108 12.8623H38.8889V33.9245C38.8889 34.2593 38.7559 34.5803 38.5192 34.8171C38.2825 35.0538 37.9614 35.1867 37.6266 35.1867H2.37331C2.03854 35.1867 1.71749 35.0538 1.48078 34.8171C1.24407 34.5803 1.11108 34.2593 1.11108 33.9245V12.8623Z" fill="url(#paint0_linear_307_12833)"/>
|
||||
<path d="M2.37997 4.81349H37.62C37.7857 4.81349 37.9499 4.84614 38.103 4.90958C38.2561 4.97301 38.3953 5.06598 38.5125 5.18319C38.6297 5.3004 38.7227 5.43955 38.7861 5.59269C38.8495 5.74582 38.8822 5.90996 38.8822 6.07572V12.8624H1.11108V6.07572C1.11108 5.9094 1.14395 5.74472 1.2078 5.59114C1.27165 5.43756 1.36522 5.29812 1.48313 5.18083C1.60105 5.06353 1.74098 4.97069 1.89489 4.90766C2.0488 4.84462 2.21366 4.81262 2.37997 4.81349V4.81349Z" fill="#0078D4"/>
|
||||
<path opacity="0.9" d="M12.6021 15.8242H5.74876C5.40144 15.8242 5.11987 16.1058 5.11987 16.4531V19.3064C5.11987 19.6538 5.40144 19.9353 5.74876 19.9353H12.6021C12.9494 19.9353 13.231 19.6538 13.231 19.3064V16.4531C13.231 16.1058 12.9494 15.8242 12.6021 15.8242Z" fill="white"/>
|
||||
<path opacity="0.9" d="M23.4821 15.7666H16.6288C16.2814 15.7666 15.9999 16.0482 15.9999 16.3955V19.2488C15.9999 19.5961 16.2814 19.8777 16.6288 19.8777H23.4821C23.8294 19.8777 24.111 19.5961 24.111 19.2488V16.3955C24.111 16.0482 23.8294 15.7666 23.4821 15.7666Z" fill="white"/>
|
||||
<path opacity="0.9" d="M34.3621 15.7666H27.5088C27.1614 15.7666 26.8799 16.0482 26.8799 16.3955V19.2488C26.8799 19.5961 27.1614 19.8777 27.5088 19.8777H34.3621C34.7094 19.8777 34.991 19.5961 34.991 19.2488V16.3955C34.991 16.0482 34.7094 15.7666 34.3621 15.7666Z" fill="white"/>
|
||||
<path opacity="0.9" d="M12.7221 21.7051H5.86876C5.52143 21.7051 5.23987 21.9866 5.23987 22.334V25.1873C5.23987 25.5346 5.52143 25.8162 5.86876 25.8162H12.7221C13.0694 25.8162 13.351 25.5346 13.351 25.1873V22.334C13.351 21.9866 13.0694 21.7051 12.7221 21.7051Z" fill="white"/>
|
||||
<path d="M23.6021 21.6465H16.7488C16.4014 21.6465 16.1199 21.928 16.1199 22.2754V25.1287C16.1199 25.476 16.4014 25.7576 16.7488 25.7576H23.6021C23.9494 25.7576 24.231 25.476 24.231 25.1287V22.2754C24.231 21.928 23.9494 21.6465 23.6021 21.6465Z" fill="#ECF4FD"/>
|
||||
<path d="M34.4821 21.6465H27.6288C27.2814 21.6465 26.9999 21.928 26.9999 22.2754V25.1287C26.9999 25.476 27.2814 25.7576 27.6288 25.7576H34.4821C34.8294 25.7576 35.111 25.476 35.111 25.1287V22.2754C35.111 21.928 34.8294 21.6465 34.4821 21.6465Z" fill="#ECF4FD"/>
|
||||
<path d="M12.7221 27.6426H5.86876C5.52143 27.6426 5.23987 27.9241 5.23987 28.2715V31.1248C5.23987 31.4721 5.52143 31.7537 5.86876 31.7537H12.7221C13.0694 31.7537 13.351 31.4721 13.351 31.1248V28.2715C13.351 27.9241 13.0694 27.6426 12.7221 27.6426Z" fill="#ECF4FD"/>
|
||||
<path d="M23.6021 27.585H16.7488C16.4014 27.585 16.1199 27.8665 16.1199 28.2139V31.0672C16.1199 31.4145 16.4014 31.6961 16.7488 31.6961H23.6021C23.9494 31.6961 24.231 31.4145 24.231 31.0672V28.2139C24.231 27.8665 23.9494 27.585 23.6021 27.585Z" fill="#ECF4FD"/>
|
||||
<path d="M34.4821 27.585H27.6288C27.2814 27.585 26.9999 27.8665 26.9999 28.2139V31.0672C26.9999 31.4145 27.2814 31.6961 27.6288 31.6961H34.4821C34.8294 31.6961 35.111 31.4145 35.111 31.0672V28.2139C35.111 27.8665 34.8294 27.585 34.4821 27.585Z" fill="#ECF4FD"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_307_12833" x1="20" y1="35.1867" x2="20" y2="12.8623" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0078D4"/>
|
||||
<stop offset="0.502" stop-color="#4093E6"/>
|
||||
<stop offset="0.775" stop-color="#5EA0EF"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
3
images/X-errorMessage.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 0C8.73438 0 9.44271 0.0963542 10.125 0.289062C10.8073 0.476562 11.4427 0.744792 12.0312 1.09375C12.625 1.44271 13.1641 1.86198 13.6484 2.35156C14.138 2.83594 14.5573 3.375 14.9062 3.96875C15.2552 4.55729 15.5234 5.19271 15.7109 5.875C15.9036 6.55729 16 7.26562 16 8C16 8.73438 15.9036 9.44271 15.7109 10.125C15.5234 10.8073 15.2552 11.4453 14.9062 12.0391C14.5573 12.6276 14.138 13.1667 13.6484 13.6562C13.1641 14.1406 12.625 14.5573 12.0312 14.9062C11.4427 15.2552 10.8073 15.526 10.125 15.7188C9.44271 15.9062 8.73438 16 8 16C7.26562 16 6.55729 15.9062 5.875 15.7188C5.19271 15.526 4.55469 15.2552 3.96094 14.9062C3.3724 14.5573 2.83333 14.1406 2.34375 13.6562C1.85938 13.1667 1.44271 12.6276 1.09375 12.0391C0.744792 11.4453 0.473958 10.8073 0.28125 10.125C0.09375 9.44271 0 8.73438 0 8C0 7.26562 0.09375 6.55729 0.28125 5.875C0.473958 5.19271 0.744792 4.55729 1.09375 3.96875C1.44271 3.375 1.85938 2.83594 2.34375 2.35156C2.83333 1.86198 3.3724 1.44271 3.96094 1.09375C4.55469 0.744792 5.19271 0.476562 5.875 0.289062C6.55729 0.0963542 7.26562 0 8 0ZM8 15C8.64583 15 9.26562 14.9167 9.85938 14.75C10.4583 14.5833 11.0156 14.349 11.5312 14.0469C12.0521 13.7396 12.5234 13.375 12.9453 12.9531C13.3724 12.526 13.737 12.0547 14.0391 11.5391C14.3464 11.0182 14.5833 10.4609 14.75 9.86719C14.9167 9.26823 15 8.64583 15 8C15 7.35417 14.9167 6.73438 14.75 6.14062C14.5833 5.54167 14.3464 4.98438 14.0391 4.46875C13.737 3.94792 13.3724 3.47656 12.9453 3.05469C12.5234 2.6276 12.0521 2.26302 11.5312 1.96094C11.0156 1.65365 10.4583 1.41667 9.85938 1.25C9.26562 1.08333 8.64583 1 8 1C7.35417 1 6.73177 1.08333 6.13281 1.25C5.53906 1.41667 4.98177 1.65365 4.46094 1.96094C3.94531 2.26302 3.47396 2.6276 3.04688 3.05469C2.625 3.47656 2.26042 3.94792 1.95312 4.46875C1.65104 4.98438 1.41667 5.54167 1.25 6.14062C1.08333 6.73438 1 7.35417 1 8C1 8.64583 1.08333 9.26823 1.25 9.86719C1.41667 10.4609 1.65104 11.0182 1.95312 11.5391C2.26042 12.0547 2.625 12.526 3.04688 12.9531C3.47396 13.375 3.94531 13.7396 4.46094 14.0469C4.98177 14.349 5.53906 14.5833 6.13281 14.75C6.73177 14.9167 7.35417 15 8 15ZM11.4609 5.24219L8.71094 8L11.4609 10.7578L10.7578 11.4609L8 8.71094L5.24219 11.4609L4.53906 10.7578L7.28906 8L4.53906 5.24219L5.24219 4.53906L8 7.28906L10.7578 4.53906L11.4609 5.24219Z" fill="#E00B1C"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 160 B |
|
Before Width: | Height: | Size: 148 B |
|
Before Width: | Height: | Size: 201 B |
|
Before Width: | Height: | Size: 158 B |
|
Before Width: | Height: | Size: 146 B |
|
Before Width: | Height: | Size: 13 KiB |
@@ -10,7 +10,6 @@
|
||||
@DataExplorerFont: wf_segoe-ui_normal, "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif;
|
||||
@SemiboldFont: "Segoe UI Semibold", "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif;
|
||||
@GrayScale: "grayscale()";
|
||||
@NoColor: "brightness(0) saturate(100%)";
|
||||
|
||||
@xSmallFontSize: 4px;
|
||||
@smallFontSize: 8px;
|
||||
@@ -147,44 +146,15 @@
|
||||
|
||||
// CommandBar
|
||||
@CommandBarButtonHeight: 40px;
|
||||
@FabricCommandBarButtonHeight: 34px;
|
||||
|
||||
/**********************************************************************************
|
||||
Portal Consts
|
||||
/**********************************************************************************/
|
||||
|
||||
@PortalAccentMediumHigh: #0058ad;
|
||||
@PortalAccentMedium: #004e87;
|
||||
@PortalAccentLight: #eef7ff;
|
||||
@PortalAccentAccentExtra: #ddf0ff;
|
||||
|
||||
/**********************************************************************************
|
||||
Fabric Consts
|
||||
/**********************************************************************************/
|
||||
|
||||
@FabricFont: "Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;
|
||||
@FabricToolbarIconColor: "brightness(0) saturate(100%) invert(50%) sepia(17%) saturate(1459%) hue-rotate(81deg) brightness(99%) contrast(94%)";
|
||||
|
||||
@FabricBoxBorderRadius: 8px;
|
||||
@FabricBoxBorderShadow: rgba(0, 0, 0, 0.133) 0px 1.6px 3.6px 0px, rgba(0, 0, 0, 0.11) 0px 0.3px 0.9px 0px;
|
||||
@FabricBoxMargin: 4px 3px 4px 3px;
|
||||
|
||||
@FabricAccentMediumHigh: #0c695a;
|
||||
@FabricAccentMedium: #117865;
|
||||
@FabricAccentLight: #f5f5f5;
|
||||
@FabricAccentExtra: #ebebeb;
|
||||
|
||||
@FabricButtonBorderRadius: 4px;
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
Common Flex Property
|
||||
/**********************************************************************************/
|
||||
|
||||
.flex-display(@display: flex) {
|
||||
display:~"-webkit-@{display}";
|
||||
display:~"-ms-@{display}box"; // IE10 uses -ms-flexbox
|
||||
display:~"-ms-@{display}"; // IE11
|
||||
display: ~"-webkit-@{display}";
|
||||
display: ~"-ms-@{display}box"; // IE10 uses -ms-flexbox
|
||||
display: ~"-ms-@{display}"; // IE11
|
||||
display: @display;
|
||||
}
|
||||
|
||||
@@ -198,15 +168,13 @@
|
||||
High contrast mode active
|
||||
**************************************************************************************/
|
||||
|
||||
@media all and (-ms-high-contrast: none),
|
||||
(-ms-high-contrast: active) {
|
||||
|
||||
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
|
||||
.selectedRadio,
|
||||
.selectedRadio:hover,
|
||||
.selectedRadio:active,
|
||||
.selectedRadio.dirty,
|
||||
.tab [type="radio"]:checked~label,
|
||||
.tab [type="radio"]:checked~label:hover {
|
||||
.tab [type="radio"]:checked ~ label,
|
||||
.tab [type="radio"]:checked ~ label:hover {
|
||||
-ms-high-contrast-adjust: none;
|
||||
-webkit-text-fill-color: HighlightText;
|
||||
color: HighlightText;
|
||||
@@ -215,7 +183,6 @@
|
||||
}
|
||||
|
||||
.queryMetricsSummaryTuple {
|
||||
|
||||
th,
|
||||
td {
|
||||
&:nth-child(2) {
|
||||
@@ -335,4 +302,4 @@
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: @InfoPointerColor transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,13 +124,12 @@ table.dataTable thead td:active {
|
||||
|
||||
table.dataTable thead th:focus,
|
||||
table.dataTable thead td:focus {
|
||||
outline: 1px dashed #605E5C;
|
||||
outline-offset: -2px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #007ACC;
|
||||
/*[{datatable-header-cell-focus-background}]*/
|
||||
}
|
||||
table.dataTable tbody tr:focus{
|
||||
outline: 1px dashed #605E5C;
|
||||
}
|
||||
|
||||
table.dataTable thead th:hover,
|
||||
table.dataTable thead td:hover {
|
||||
border: 1px solid #007ACC;
|
||||
|
||||
@@ -1179,16 +1179,16 @@ menuQuickStart {
|
||||
}
|
||||
}
|
||||
|
||||
#tbodycontent tr.gridRowSelected {
|
||||
.gridRowSelected {
|
||||
.active();
|
||||
}
|
||||
|
||||
#tbodycontent tr.gridRowSelected:hover {
|
||||
.gridRowSelected:hover {
|
||||
cursor: default;
|
||||
.hover();
|
||||
}
|
||||
|
||||
#tbodycontent tr.gridRowHighlighted {
|
||||
.gridRowHighlighted {
|
||||
border-style: dotted;
|
||||
border-width: 2px;
|
||||
}
|
||||
@@ -2296,17 +2296,6 @@ a:link {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.monaco-editor .quick-input-list-label {
|
||||
/* Restore some of Monaco's default styles that are clobbered by our global styles */
|
||||
padding: 0;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.monaco-editor .quick-input-list .highlight {
|
||||
/* Padding in highlighted text within the quick input list breaks the flow of the text */
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
td a {
|
||||
color: #393939;
|
||||
}
|
||||
@@ -2587,10 +2576,9 @@ a:link {
|
||||
.querydropdown.placeholderVisible {
|
||||
font-style: italic;
|
||||
}
|
||||
.querydropdown.placeholderVisible::placeholder {
|
||||
/* Chrome, Firefox, Opera, Safari 10.1+ */
|
||||
.querydropdown.placeholderVisible::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
|
||||
color: #767474;
|
||||
opacity: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.querydropdown:hover {
|
||||
@@ -2658,11 +2646,6 @@ a:link {
|
||||
width: @ActiveTabWidth;
|
||||
}
|
||||
|
||||
.nav-tabs > li.active > .tabNavContentContainer > .tab_Content > .tabNavText {
|
||||
font-weight: bolder;
|
||||
border-bottom: 2px solid rgba(0, 120, 212, 1);
|
||||
}
|
||||
|
||||
.nav-tabs > li.active:focus > .tabNavContentContainer {
|
||||
.focus();
|
||||
}
|
||||
@@ -2908,21 +2891,9 @@ a:link {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.settingsSectionInlineCheckbox {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.settingsSectionLabel {
|
||||
margin-bottom: @DefaultSpace;
|
||||
margin-right: 5px;
|
||||
|
||||
.panelInfoIcon {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.pageOptionsPart {
|
||||
@@ -3120,3 +3091,4 @@ a:link {
|
||||
background: white;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
@import "./Common/Constants";
|
||||
|
||||
html {
|
||||
font-family: @FabricFont;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: @FabricFont;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @FabricAccentMedium;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus {
|
||||
color: @FabricAccentMediumHigh;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#divExplorer {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.resourceTreeAndTabs {
|
||||
border-radius: 0px;
|
||||
box-shadow: @FabricBoxBorderShadow;
|
||||
margin: @FabricBoxMargin;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.tabsManagerContainer {
|
||||
background-color: #ffffff
|
||||
}
|
||||
|
||||
.nav-tabs-margin {
|
||||
padding-top: 8px;
|
||||
background-color: #ffffff
|
||||
}
|
||||
|
||||
.commandBarContainer {
|
||||
background-color: #ffffff;
|
||||
border-radius: @FabricBoxBorderRadius @FabricBoxBorderRadius 0px 0px;
|
||||
box-shadow: @FabricBoxBorderShadow;
|
||||
margin: @FabricBoxMargin;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
padding-top: 2px;
|
||||
padding: 0px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.dividerContainer {
|
||||
padding: @SmallSpace 0px @SmallSpace 0px;
|
||||
height: @FabricCommandBarButtonHeight;
|
||||
.flex-display();
|
||||
|
||||
span {
|
||||
border-left: @ButtonBorderWidth solid @BaseMedium;
|
||||
margin: 0 10px 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.nav-tabs>li>.tabNavContentContainer>.tab_Content:hover {
|
||||
border-bottom: 2px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.nav-tabs>li.active>.tabNavContentContainer>.tab_Content,
|
||||
.nav-tabs>li.active>.tabNavContentContainer>.tab_Content:hover {
|
||||
border-bottom: 2px solid @FabricAccentMedium;
|
||||
}
|
||||
|
||||
.nav-tabs>li.active>.tabNavContentContainer>.tab_Content>.tabNavText {
|
||||
border-bottom: 0px none transparent;
|
||||
}
|
||||
|
||||
.tabNavContentContainer {
|
||||
padding: @SmallSpace 0px @SmallSpace 0px;
|
||||
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.tab_Content {
|
||||
border-right: 0px none transparent;
|
||||
margin: 0px @SmallSpace 0px @SmallSpace;
|
||||
width: calc(@TabsWidth - (@SmallSpace * 2));
|
||||
padding-bottom: @SmallSpace;
|
||||
|
||||
.statusIconContainer {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.tabIconSection {
|
||||
.cancelButton {
|
||||
padding: 0px 0px 0px @SmallSpace;
|
||||
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.resourceTree {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.accordion {
|
||||
.accordionItemContainer {
|
||||
.accordionItemHeader {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.treeComponent {
|
||||
.nodeItem {
|
||||
&:focus {
|
||||
outline: 2px @FabricAccentMedium;
|
||||
}
|
||||
|
||||
.treeNodeHeader {
|
||||
padding: 5px 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: @FabricAccentLight;
|
||||
|
||||
.treeMenuEllipsis {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.showingMenu {
|
||||
background-color: #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.selected {
|
||||
&>.treeNodeHeader {
|
||||
background-color: @FabricAccentExtra;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.dataExplorerErrorConsoleContainer {
|
||||
border-radius: 0px 0px @FabricBoxBorderRadius @FabricBoxBorderRadius;
|
||||
box-shadow: @FabricBoxBorderShadow;
|
||||
margin: @FabricBoxMargin;
|
||||
margin-top: 0px;
|
||||
width: auto;
|
||||
align-self: auto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.filterbtnstyle {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
border: solid 1px #d1d1d1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.filterbtnstyle:hover {
|
||||
background: @FabricAccentLight;
|
||||
color: #000;
|
||||
border: solid 1px #d1d1d1;
|
||||
}
|
||||
|
||||
.filterbtnstyle:active {
|
||||
background: @FabricAccentLight;
|
||||
color: #000;
|
||||
border: solid 1px #d1d1d1;
|
||||
}
|
||||
|
||||
.filterbtnstyle:focus {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
border: solid 1px #d1d1d1;
|
||||
}
|
||||
|
||||
|
||||
.gridRowSelected .tabdocumentsGridElement:hover {
|
||||
background-color: @FabricAccentLight !important;
|
||||
}
|
||||
|
||||
|
||||
.refreshcol {
|
||||
filter: brightness(0) saturate(100%);
|
||||
}
|
||||
|
||||
.refreshcol1 {
|
||||
filter: brightness(0) saturate(100%);
|
||||
}
|
||||
|
||||
.fileImportImg img {
|
||||
filter: brightness(0) saturate(100%);
|
||||
}
|
||||
52366
package-lock.json
generated
94
package.json
@@ -5,19 +5,19 @@
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@azure/arm-cosmosdb": "9.1.0",
|
||||
"@azure/cosmos": "4.0.1-beta.2",
|
||||
"@azure/cosmos": "3.16.2",
|
||||
"@azure/cosmos-language-service": "0.0.5",
|
||||
"@azure/identity": "1.2.1",
|
||||
"@azure/ms-rest-nodeauth": "3.0.7",
|
||||
"@azure/msal-browser": "2.14.2",
|
||||
"@babel/plugin-proposal-class-properties": "7.12.1",
|
||||
"@babel/plugin-proposal-decorators": "7.12.12",
|
||||
"@fluentui/react": "8.112.1",
|
||||
"@fluentui/react-components": "9.34.0",
|
||||
"@fluentui/react": "8.14.3",
|
||||
"@fluentui/react-components": "9.30.1",
|
||||
"@jupyterlab/services": "6.0.2",
|
||||
"@jupyterlab/terminal": "3.0.3",
|
||||
"@microsoft/applicationinsights-web": "2.6.1",
|
||||
"@nteract/commutable": "7.5.1",
|
||||
"@nteract/commutable": "7.4.2",
|
||||
"@nteract/connected-components": "6.8.2",
|
||||
"@nteract/core": "15.1.0",
|
||||
"@nteract/data-explorer": "8.0.3",
|
||||
@@ -49,20 +49,20 @@
|
||||
"applicationinsights": "1.8.0",
|
||||
"bootstrap": "3.4.1",
|
||||
"canvas": "file:./canvas",
|
||||
"clean-webpack-plugin": "4.0.0",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"clipboard-copy": "4.0.1",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"copy-webpack-plugin": "9.0.1",
|
||||
"crossroads": "0.12.2",
|
||||
"css-element-queries": "1.1.1",
|
||||
"d3": "6.1.1",
|
||||
"datatables.net-colreorder-dt": "1.7.0",
|
||||
"datatables.net-dt": "1.13.8",
|
||||
"datatables.net-colreorder-dt": "1.5.1",
|
||||
"datatables.net-dt": "1.10.19",
|
||||
"date-fns": "1.29.0",
|
||||
"dayjs": "1.8.19",
|
||||
"dom-to-image": "2.6.0",
|
||||
"dotenv": "8.2.0",
|
||||
"eslint-plugin-jest": "27.4.2",
|
||||
"eslint-plugin-react": "7.33.2",
|
||||
"eslint-plugin-jest": "23.13.2",
|
||||
"eslint-plugin-react": "7.20.0",
|
||||
"hasher": "1.2.0",
|
||||
"html2canvas": "1.0.0-rc.5",
|
||||
"i18next": "19.8.4",
|
||||
@@ -71,15 +71,14 @@
|
||||
"iframe-resizer-react": "1.1.0",
|
||||
"immutable": "4.0.0-rc.12",
|
||||
"is-ci": "2.0.0",
|
||||
"jquery": "3.7.1",
|
||||
"jquery-typeahead": "2.11.1",
|
||||
"jquery-ui-dist": "1.13.2",
|
||||
"jquery": "3.5.1",
|
||||
"jquery-typeahead": "2.10.6",
|
||||
"jquery-ui-dist": "1.12.1",
|
||||
"knockout": "3.5.1",
|
||||
"mkdirp": "1.0.4",
|
||||
"monaco-editor": "0.44.0",
|
||||
"monaco-editor": "0.18.1",
|
||||
"ms": "2.1.3",
|
||||
"p-retry": "4.6.2",
|
||||
"patch-package": "8.0.0",
|
||||
"p-retry": "4.2.0",
|
||||
"plotly.js-cartesian-dist-min": "1.52.3",
|
||||
"post-robot": "10.0.42",
|
||||
"q": "1.5.1",
|
||||
@@ -87,20 +86,21 @@
|
||||
"react-animate-height": "2.0.8",
|
||||
"react-dnd": "14.0.2",
|
||||
"react-dnd-html5-backend": "14.0.0",
|
||||
"react-dom": "16.14.0",
|
||||
"react-dom": "16.13.1",
|
||||
"react-hotkeys": "2.0.0",
|
||||
"react-i18next": "11.8.5",
|
||||
"react-notification-system": "0.2.17",
|
||||
"react-redux": "7.1.3",
|
||||
"react-splitter-layout": "4.0.0",
|
||||
"react-string-format": "1.0.1",
|
||||
"react-youtube": "9.0.1",
|
||||
"redux": "4.0.4",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rx-jupyter": "5.5.12",
|
||||
"rxjs": "6.6.3",
|
||||
"sanitize-html": "2.3.3",
|
||||
"styled-components": "5.0.1",
|
||||
"styled-components": "4.3.2",
|
||||
"swr": "0.4.0",
|
||||
"terser-webpack-plugin": "5.3.9",
|
||||
"terser-webpack-plugin": "5.1.4",
|
||||
"underscore": "1.9.1",
|
||||
"utility-types": "3.10.0",
|
||||
"zustand": "3.5.0"
|
||||
@@ -115,14 +115,11 @@
|
||||
"@types/codemirror": "0.0.56",
|
||||
"@types/crossroads": "0.0.30",
|
||||
"@types/d3": "5.9.2",
|
||||
"@types/datatables.net": "1.10.28",
|
||||
"@types/datatables.net-colreorder": "1.4.5",
|
||||
"@types/dom-to-image": "2.6.2",
|
||||
"@types/enzyme": "3.10.7",
|
||||
"@types/enzyme-adapter-react-16": "1.0.6",
|
||||
"@types/hasher": "0.0.31",
|
||||
"@types/jest": "26.0.20",
|
||||
"@types/jquery": "3.5.29",
|
||||
"@types/node": "12.11.1",
|
||||
"@types/post-robot": "10.0.1",
|
||||
"@types/q": "1.5.1",
|
||||
@@ -136,62 +133,63 @@
|
||||
"@types/styled-components": "5.1.1",
|
||||
"@types/underscore": "1.7.36",
|
||||
"@types/youtube-player": "5.5.6",
|
||||
"@typescript-eslint/eslint-plugin": "6.7.4",
|
||||
"@typescript-eslint/parser": "6.7.4",
|
||||
"@webpack-cli/serve": "2.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "4.22.0",
|
||||
"@typescript-eslint/parser": "4.22.0",
|
||||
"@webpack-cli/serve": "1.5.2",
|
||||
"babel-jest": "24.9.0",
|
||||
"babel-loader": "8.1.0",
|
||||
"buffer": "5.1.0",
|
||||
"case-sensitive-paths-webpack-plugin": "2.4.0",
|
||||
"case-sensitive-paths-webpack-plugin": "2.3.0",
|
||||
"create-file-webpack": "1.0.2",
|
||||
"css-loader": "6.8.1",
|
||||
"css-loader": "1.0.0",
|
||||
"enzyme": "3.11.0",
|
||||
"enzyme-adapter-react-16": "1.15.5",
|
||||
"enzyme-to-json": "3.6.1",
|
||||
"eslint": "8.50.0",
|
||||
"eslint": "7.8.1",
|
||||
"eslint-cli": "1.1.1",
|
||||
"eslint-plugin-no-null": "1.0.2",
|
||||
"eslint-plugin-prefer-arrow": "1.2.3",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"eslint-plugin-prefer-arrow": "1.2.2",
|
||||
"eslint-plugin-react-hooks": "4.2.0",
|
||||
"expect-playwright": "0.3.3",
|
||||
"fast-glob": "3.2.5",
|
||||
"file-loader": "2.0.0",
|
||||
"fs-extra": "7.0.0",
|
||||
"html-inline-css-webpack-plugin": "1.11.2",
|
||||
"html-inline-css-webpack-plugin": "1.11.0",
|
||||
"html-loader": "0.5.5",
|
||||
"html-loader-jest": "0.2.1",
|
||||
"html-webpack-plugin": "5.5.3",
|
||||
"html-webpack-plugin": "5.3.2",
|
||||
"jest": "26.6.3",
|
||||
"jest-canvas-mock": "2.3.1",
|
||||
"jest-playwright-preset": "1.5.1",
|
||||
"jest-react-hooks-shallow": "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": "7.1.0",
|
||||
"monaco-editor-webpack-plugin": "1.7.0",
|
||||
"node-fetch": "2.6.1",
|
||||
"playwright": "1.13.0",
|
||||
"prettier": "3.0.3",
|
||||
"prettier": "2.2.1",
|
||||
"process": "0.11.10",
|
||||
"querystring-es3": "0.2.1",
|
||||
"raw-loader": "0.5.1",
|
||||
"react-dev-utils": "11.0.4",
|
||||
"rimraf": "3.0.0",
|
||||
"sinon": "3.2.1",
|
||||
"style-loader": "0.23.0",
|
||||
"ts-loader": "9.2.4",
|
||||
"typedoc": "0.21.5",
|
||||
"typescript": "4.3.5",
|
||||
"url-loader": "4.1.1",
|
||||
"tslint": "5.11.0",
|
||||
"tslint-microsoft-contrib": "6.0.0",
|
||||
"typedoc": "0.20.36",
|
||||
"typescript": "4.3.4",
|
||||
"url-loader": "1.1.1",
|
||||
"wait-on": "4.0.2",
|
||||
"webpack": "5.88.2",
|
||||
"webpack-bundle-analyzer": "4.9.1",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-dev-server": "4.15.1"
|
||||
"webpack": "5.47.0",
|
||||
"webpack-bundle-analyzer": "4.4.2",
|
||||
"webpack-cli": "4.7.2",
|
||||
"webpack-dev-server": "3.11.2"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "patch-package",
|
||||
"start": "webpack serve --mode development",
|
||||
"dev": "echo \"WARNING: npm run dev has been deprecated\" && npm run build",
|
||||
"build:dataExplorer:ci": "npm run build:ci",
|
||||
@@ -201,7 +199,6 @@
|
||||
"pack:fast": "webpack --mode development --progress",
|
||||
"copyToConsumers": "node copyToConsumers",
|
||||
"test": "rimraf coverage && jest",
|
||||
"test:debug": "jest --runInBand",
|
||||
"test:e2e": "jest -c ./jest.config.playwright.js --detectOpenHandles",
|
||||
"watch": "npm run start",
|
||||
"wait-for-server": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/",
|
||||
@@ -212,7 +209,7 @@
|
||||
"compile:strict": "tsc -p ./tsconfig.strict.json",
|
||||
"format": "prettier --write \"{src,test}/**/*.{ts,tsx,html}\" \"*.{js,html}\"",
|
||||
"format:check": "prettier --check \"{src,test}/**/*.{ts,tsx,html}\" \"*.{js,html}\"",
|
||||
"lint": "eslint \"**/*.{ts,tsx}\"",
|
||||
"lint": "tslint --project tsconfig.json && eslint \"**/*.{ts,tsx}\"",
|
||||
"build:contracts": "npm run compile:contracts",
|
||||
"strict:find": "node ./strict-null-checks/find.js",
|
||||
"strict:add": "node ./strict-null-checks/auto-add.js",
|
||||
@@ -235,7 +232,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/Azure/cosmos-explorer",
|
||||
"prettier": {
|
||||
"printWidth": 120,
|
||||
"endOfLine": "auto"
|
||||
"printWidth": 120
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
diff --git a/node_modules/datatables.net-colreorder/types/types.d.ts b/node_modules/datatables.net-colreorder/types/types.d.ts
|
||||
index e5dc283..1930c2b 100644
|
||||
--- a/node_modules/datatables.net-colreorder/types/types.d.ts
|
||||
+++ b/node_modules/datatables.net-colreorder/types/types.d.ts
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
/// <reference types="jquery" />
|
||||
|
||||
-import DataTables, {Api} from 'datatables.net';
|
||||
+import DataTables, { Api } from 'datatables.net';
|
||||
|
||||
export default DataTables;
|
||||
|
||||
@@ -40,6 +40,8 @@ declare module 'datatables.net' {
|
||||
/**
|
||||
* Create a new ColReorder instance for the target DataTable
|
||||
*/
|
||||
+ // Ignore this error: error TS7013: Construct signature, which lacks return-type annotation, implicitly has an 'any' return type.
|
||||
+ // @ts-ignore
|
||||
new (dt: Api<any>, settings: boolean | ConfigColReorder);
|
||||
|
||||
/**
|
||||
@@ -10,7 +10,7 @@ export class BindingHandlersRegisterer {
|
||||
wrappedValueAccessor: () => any,
|
||||
allBindings?: ko.AllBindings,
|
||||
viewModel?: any,
|
||||
bindingContext?: ko.BindingContext,
|
||||
bindingContext?: ko.BindingContext
|
||||
) {
|
||||
const value = ko.unwrap(wrappedValueAccessor());
|
||||
bindingContext?.$data.isTemplateReady(value);
|
||||
|
||||
@@ -31,7 +31,7 @@ export class Registerer {
|
||||
|
||||
// If any of the ko observable change inside parameters, trigger a new render.
|
||||
ko.computed(() => ko.toJSON(adapter.parameters)).subscribe(() =>
|
||||
ReactDOM.render(adapter.renderComponent(), element),
|
||||
ReactDOM.render(adapter.renderComponent(), element)
|
||||
);
|
||||
|
||||
// Initial rendering at mount point
|
||||
|
||||
@@ -66,7 +66,7 @@ const onInit = async () => {
|
||||
);
|
||||
|
||||
ReactDOM.render(outputs, document.getElementById("cellOutput"));
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
postRobot.on(
|
||||
@@ -89,14 +89,14 @@ const onInit = async () => {
|
||||
topNode,
|
||||
snapshotRequest.aspectRatio,
|
||||
undefined,
|
||||
snapshotRequest.downloadFilename,
|
||||
snapshotRequest.downloadFilename
|
||||
);
|
||||
|
||||
return {
|
||||
imageSrc: result.imageSrc,
|
||||
requestId: snapshotRequest.requestId,
|
||||
};
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ const getMediaInfo = (props: TransformMediaProps) => {
|
||||
const mediaType = displayOrder.find(
|
||||
(key) =>
|
||||
Object.prototype.hasOwnProperty.call(output.data, key) &&
|
||||
(Object.prototype.hasOwnProperty.call(transformsById, key) || transformsById.get(key)),
|
||||
(Object.prototype.hasOwnProperty.call(transformsById, key) || transformsById.get(key))
|
||||
);
|
||||
|
||||
if (mediaType) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
@@ -124,36 +124,7 @@ export enum MongoBackendEndpointType {
|
||||
remote,
|
||||
}
|
||||
|
||||
export class BackendApi {
|
||||
public static readonly GenerateToken: string = "GenerateToken";
|
||||
public static readonly PortalSettings: string = "PortalSettings";
|
||||
}
|
||||
|
||||
export class PortalBackendEndpoints {
|
||||
public static readonly Development: string = "https://localhost:7235";
|
||||
public static readonly Mpac: string = "https://cdb-ms-mpac-pbe.cosmos.azure.com";
|
||||
public static readonly Prod: string = "https://cdb-ms-prod-pbe.cosmos.azure.com";
|
||||
public static readonly Fairfax: string = "https://cdb-ff-prod-pbe.cosmos.azure.us";
|
||||
public static readonly Mooncake: string = "https://cdb-mc-prod-pbe.cosmos.azure.cn";
|
||||
}
|
||||
|
||||
export class MongoProxyEndpoints {
|
||||
public static readonly Development: string = "https://localhost:7238";
|
||||
public static readonly Mpac: string = "https://cdb-ms-mpac-mp.cosmos.azure.com";
|
||||
public static readonly Prod: string = "https://cdb-ms-prod-mp.cosmos.azure.com";
|
||||
public static readonly Fairfax: string = "https://cdb-ff-prod-mp.cosmos.azure.us";
|
||||
public static readonly Mooncake: string = "https://cdb-mc-prod-mp.cosmos.azure.cn";
|
||||
}
|
||||
|
||||
export class CassandraProxyEndpoints {
|
||||
public static readonly Development: string = "https://localhost:7240";
|
||||
public static readonly Mpac: string = "https://cdb-ms-mpac-cp.cosmos.azure.com";
|
||||
public static readonly Prod: string = "https://cdb-ms-prod-cp.cosmos.azure.com";
|
||||
public static readonly Fairfax: string = "https://cdb-ff-prod-cp.cosmos.azure.us";
|
||||
public static readonly Mooncake: string = "https://cdb-mc-prod-cp.cosmos.azure.cn";
|
||||
}
|
||||
|
||||
//TODO: Remove this when new backend is migrated over
|
||||
// TODO: 435619 Add default endpoints per cloud and use regional only when available
|
||||
export class CassandraBackend {
|
||||
public static readonly createOrDeleteApi: string = "api/cassandra/createordelete";
|
||||
public static readonly guestCreateOrDeleteApi: string = "api/guest/cassandra/createordelete";
|
||||
@@ -165,32 +136,15 @@ export class CassandraBackend {
|
||||
public static readonly guestSchemaApi: string = "api/guest/cassandra/schema";
|
||||
}
|
||||
|
||||
export class CassandraProxyAPIs {
|
||||
public static readonly createOrDeleteApi: string = "api/cassandra/createordelete";
|
||||
public static readonly connectionStringCreateOrDeleteApi: string = "api/connectionstring/cassandra/createordelete";
|
||||
public static readonly queryApi: string = "api/cassandra";
|
||||
public static readonly connectionStringQueryApi: string = "api/connectionstring/cassandra";
|
||||
public static readonly keysApi: string = "api/cassandra/keys";
|
||||
public static readonly connectionStringKeysApi: string = "api/connectionstring/cassandra/keys";
|
||||
public static readonly schemaApi: string = "api/cassandra/schema";
|
||||
public static readonly connectionStringSchemaApi: string = "api/connectionstring/cassandra/schema";
|
||||
}
|
||||
|
||||
export class Queries {
|
||||
public static CustomPageOption: string = "custom";
|
||||
public static UnlimitedPageOption: string = "unlimited";
|
||||
public static setAutomaticRBACOption: string = "Automatic";
|
||||
public static setTrueRBACOption: string = "True";
|
||||
public static setFalseRBACOption: string = "False";
|
||||
public static itemsPerPage: number = 100;
|
||||
public static unlimitedItemsPerPage: number = 100; // TODO: Figure out appropriate value so it works for accounts with a large number of partitions
|
||||
public static containersPerPage: number = 50;
|
||||
public static QueryEditorMinHeightRatio: number = 0.1;
|
||||
public static QueryEditorMaxHeightRatio: number = 0.4;
|
||||
public static readonly DefaultMaxDegreeOfParallelism = 6;
|
||||
public static readonly DefaultRetryAttempts = 9;
|
||||
public static readonly DefaultRetryIntervalInMs = 0;
|
||||
public static readonly DefaultMaxWaitTimeInSeconds = 30;
|
||||
}
|
||||
|
||||
export class SavedQueries {
|
||||
@@ -217,7 +171,6 @@ export class Areas {
|
||||
public static Tab: string = "Tab";
|
||||
public static ShareDialog: string = "Share Access Dialog";
|
||||
public static Notebook: string = "Notebook";
|
||||
public static Copilot: string = "Copilot";
|
||||
}
|
||||
|
||||
export class HttpHeaders {
|
||||
@@ -254,10 +207,6 @@ export class HttpHeaders {
|
||||
public static migrateOfferToAutopilot: string = "x-ms-cosmos-migrate-offer-to-autopilot";
|
||||
}
|
||||
|
||||
export class ContentType {
|
||||
public static applicationJson: string = "application/json";
|
||||
}
|
||||
|
||||
export class ApiType {
|
||||
// Mapped to hexadecimal values in the backend
|
||||
public static readonly MongoDB: number = 1;
|
||||
@@ -322,7 +271,7 @@ export class HashRoutePrefixes {
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
sprocId: string,
|
||||
stripFirstSlash: boolean = true,
|
||||
stripFirstSlash: boolean = true
|
||||
): string {
|
||||
const transformedDatabasePrefix: string = this.sprocs.replace("{db_id}", databaseId);
|
||||
|
||||
@@ -416,6 +365,9 @@ export const EmulatorMasterKey =
|
||||
//[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Well known public masterKey for emulator")]
|
||||
"C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
|
||||
|
||||
// A variable @MyVariable defined in Constants.less is accessible as StyleConstants.MyVariable
|
||||
export const StyleConstants = require("less-vars-loader!../../less/Common/Constants.less");
|
||||
|
||||
export class Notebook {
|
||||
public static readonly defaultBasePath = "./notebooks";
|
||||
public static readonly heartbeatDelayMs = 60000;
|
||||
|
||||
@@ -66,7 +66,7 @@ describe("getTokenFromAuthService", () => {
|
||||
getTokenFromAuthService("GET", "dbs", "foo");
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://main.documentdb.ext.azure.com/api/guest/runtimeproxy/authorizationTokens",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -77,7 +77,7 @@ describe("getTokenFromAuthService", () => {
|
||||
getTokenFromAuthService("GET", "dbs", "foo");
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://localhost:1234/api/guest/runtimeproxy/authorizationTokens",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -125,7 +125,7 @@ describe("requestPlugin", () => {
|
||||
const headers = {};
|
||||
const endpoint = "https://docs.azure.com";
|
||||
const path = "/dbs/foo";
|
||||
requestPlugin({ endpoint, headers, path } as any, undefined, next as any);
|
||||
requestPlugin({ endpoint, headers, path } as any, next as any);
|
||||
expect(next.mock.calls[0][0]).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -137,7 +137,7 @@ describe("requestPlugin", () => {
|
||||
const headers = {};
|
||||
const endpoint = "";
|
||||
const path = "/dbs/foo";
|
||||
requestPlugin({ endpoint, headers, path } as any, undefined, next as any);
|
||||
requestPlugin({ endpoint, headers, path } as any, next as any);
|
||||
expect(next.mock.calls[0][0]).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
import * as Cosmos from "@azure/cosmos";
|
||||
import { getAuthorizationTokenUsingResourceTokens } from "Common/getAuthorizationTokenUsingResourceTokens";
|
||||
import { AuthorizationToken } from "Contracts/MessageTypes";
|
||||
import { checkDatabaseResourceTokensValidity } from "Platform/Fabric/FabricUtil";
|
||||
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||
import { AuthType } from "../AuthType";
|
||||
import { PriorityLevel } from "../Common/Constants";
|
||||
import { Platform, configContext } from "../ConfigContext";
|
||||
import { configContext, Platform } from "../ConfigContext";
|
||||
import { userContext } from "../UserContext";
|
||||
import { logConsoleError } from "../Utils/NotificationConsoleUtils";
|
||||
import * as PriorityBasedExecutionUtils from "../Utils/PriorityBasedExecutionUtils";
|
||||
import { EmulatorMasterKey, HttpHeaders } from "./Constants";
|
||||
import { getErrorMessage } from "./ErrorHandlingUtils";
|
||||
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||
import { PriorityLevel } from "../Common/Constants";
|
||||
import * as PriorityBasedExecutionUtils from "../Utils/PriorityBasedExecutionUtils";
|
||||
|
||||
const _global = typeof self === "undefined" ? window : self;
|
||||
|
||||
@@ -29,47 +25,6 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
||||
return decodeURIComponent(headers.authorization);
|
||||
}
|
||||
|
||||
if (configContext.platform === Platform.Fabric) {
|
||||
switch (requestInfo.resourceType) {
|
||||
case Cosmos.ResourceType.conflicts:
|
||||
case Cosmos.ResourceType.container:
|
||||
case Cosmos.ResourceType.sproc:
|
||||
case Cosmos.ResourceType.udf:
|
||||
case Cosmos.ResourceType.trigger:
|
||||
case Cosmos.ResourceType.item:
|
||||
case Cosmos.ResourceType.pkranges:
|
||||
// User resource tokens
|
||||
// TODO userContext.fabricContext.databaseConnectionInfo can be undefined
|
||||
headers[HttpHeaders.msDate] = new Date().toUTCString();
|
||||
const resourceTokens = userContext.fabricContext.databaseConnectionInfo.resourceTokens;
|
||||
checkDatabaseResourceTokensValidity(userContext.fabricContext.databaseConnectionInfo.resourceTokensTimestamp);
|
||||
return getAuthorizationTokenUsingResourceTokens(resourceTokens, requestInfo.path, requestInfo.resourceId);
|
||||
|
||||
case Cosmos.ResourceType.none:
|
||||
case Cosmos.ResourceType.database:
|
||||
case Cosmos.ResourceType.offer:
|
||||
case Cosmos.ResourceType.user:
|
||||
case Cosmos.ResourceType.permission:
|
||||
// For now, these operations aren't used, so fetching the authorization token is commented out.
|
||||
// This provider must return a real token to pass validation by the client, so we return the cached resource token
|
||||
// (which is a valid token, but won't work for these operations).
|
||||
const resourceTokens2 = userContext.fabricContext.databaseConnectionInfo.resourceTokens;
|
||||
return getAuthorizationTokenUsingResourceTokens(resourceTokens2, requestInfo.path, requestInfo.resourceId);
|
||||
|
||||
/* ************** TODO: Uncomment this code if we need to support these operations **************
|
||||
// User master tokens
|
||||
const authorizationToken = await sendCachedDataMessage<AuthorizationToken>(
|
||||
MessageTypes.GetAuthorizationToken,
|
||||
[requestInfo],
|
||||
userContext.fabricContext.connectionId,
|
||||
);
|
||||
console.log("Response from Fabric: ", authorizationToken);
|
||||
headers[HttpHeaders.msDate] = authorizationToken.XDate;
|
||||
return decodeURIComponent(authorizationToken.PrimaryReadWriteToken);
|
||||
***********************************************************************************************/
|
||||
}
|
||||
}
|
||||
|
||||
if (userContext.masterKey) {
|
||||
// TODO This SDK method mutates the headers object. Find a better one or fix the SDK.
|
||||
await Cosmos.setAuthorizationTokenHeaderUsingMasterKey(verb, resourceId, resourceType, headers, EmulatorMasterKey);
|
||||
@@ -85,7 +40,7 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
||||
return decodeURIComponent(result.PrimaryReadWriteToken);
|
||||
};
|
||||
|
||||
export const requestPlugin: Cosmos.Plugin<any> = async (requestContext, diagnosticNode, next) => {
|
||||
export const requestPlugin: Cosmos.Plugin<any> = async (requestContext, next) => {
|
||||
requestContext.endpoint = new URL(configContext.PROXY_PATH, window.location.href).href;
|
||||
requestContext.headers["x-ms-proxy-target"] = endpoint();
|
||||
return next(requestContext);
|
||||
@@ -100,11 +55,7 @@ export const endpoint = () => {
|
||||
return userContext.endpoint || userContext?.databaseAccount?.properties?.documentEndpoint;
|
||||
};
|
||||
|
||||
export async function getTokenFromAuthService(
|
||||
verb: string,
|
||||
resourceType: string,
|
||||
resourceId?: string,
|
||||
): Promise<AuthorizationToken> {
|
||||
export async function getTokenFromAuthService(verb: string, resourceType: string, resourceId?: string): Promise<any> {
|
||||
try {
|
||||
const host = configContext.BACKEND_ENDPOINT;
|
||||
const response = await _global.fetch(host + "/api/guest/runtimeproxy/authorizationTokens", {
|
||||
@@ -143,38 +94,22 @@ export function client(): Cosmos.CosmosClient {
|
||||
_defaultHeaders["x-ms-cosmos-sdk-supportedcapabilities"] =
|
||||
SDKSupportedCapabilities.None | SDKSupportedCapabilities.PartitionMerge;
|
||||
|
||||
if (
|
||||
userContext.authType === AuthType.ConnectionString ||
|
||||
userContext.authType === AuthType.EncryptedToken ||
|
||||
userContext.authType === AuthType.ResourceToken
|
||||
) {
|
||||
// Default to low priority. Needed for non-AAD-auth scenarios
|
||||
// where we cannot use RP API, and thus, cannot detect whether priority
|
||||
// based execution is enabled.
|
||||
// The header will be ignored if priority based execution is disabled on the account.
|
||||
_defaultHeaders["x-ms-cosmos-priority-level"] = PriorityLevel.Default;
|
||||
}
|
||||
|
||||
const options: Cosmos.CosmosClientOptions = {
|
||||
endpoint: endpoint() || "https://cosmos.azure.com", // CosmosClient gets upset if we pass a bad URL. This should never actually get called
|
||||
key: userContext.masterKey,
|
||||
tokenProvider,
|
||||
connectionPolicy: {
|
||||
enableEndpointDiscovery: false,
|
||||
},
|
||||
userAgentSuffix: "Azure Portal",
|
||||
defaultHeaders: _defaultHeaders,
|
||||
connectionPolicy: {
|
||||
retryOptions: {
|
||||
maxRetryAttemptCount: LocalStorageUtility.getEntryNumber(StorageKey.RetryAttempts),
|
||||
fixedRetryIntervalInMilliseconds: LocalStorageUtility.getEntryNumber(StorageKey.RetryInterval),
|
||||
maxWaitTimeInSeconds: LocalStorageUtility.getEntryNumber(StorageKey.MaxWaitTimeInSeconds),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (configContext.PROXY_PATH !== undefined) {
|
||||
(options as any).plugins = [{ on: "request", plugin: requestPlugin }];
|
||||
}
|
||||
|
||||
if (PriorityBasedExecutionUtils.isFeatureEnabled()) {
|
||||
if (userContext.features.enablePriorityBasedThrottling && userContext.apiType === "SQL") {
|
||||
const plugins = (options as any).plugins || [];
|
||||
plugins.push({ on: "request", plugin: PriorityBasedExecutionUtils.requestPlugin });
|
||||
(options as any).plugins = plugins;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DatePicker, TextField } from "@fluentui/react";
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { attributeValueLabel } from "../Explorer/Panes/Tables/Validators/EntityTableHelper";
|
||||
|
||||
export interface TableEntityProps {
|
||||
entityValueLabel?: string;
|
||||
@@ -59,7 +58,6 @@ export const EntityValue: FunctionComponent<TableEntityProps> = ({
|
||||
placeholder={entityValuePlaceholder}
|
||||
value={typeof entityValue === "string" ? entityValue : ""}
|
||||
onChange={onEntityValueChange}
|
||||
ariaLabel={attributeValueLabel}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -51,11 +51,6 @@ const replaceKnownError = (errorMessage: string): string => {
|
||||
return "Database throughput is not supported for internal subscriptions.";
|
||||
} else if (errorMessage?.indexOf("Partition key paths must contain only valid") >= 0) {
|
||||
return "Partition key paths must contain only valid characters and not contain a trailing slash or wildcard character.";
|
||||
} else if (
|
||||
errorMessage?.indexOf("The user aborted a request") >= 0 ||
|
||||
errorMessage?.indexOf("The operation was aborted") >= 0
|
||||
) {
|
||||
return "User aborted query.";
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { QueryOperationOptions } from "@azure/cosmos";
|
||||
import { QueryResults } from "../Contracts/ViewModels";
|
||||
|
||||
interface QueryResponse {
|
||||
@@ -11,17 +10,13 @@ interface QueryResponse {
|
||||
}
|
||||
|
||||
export interface MinimalQueryIterator {
|
||||
fetchNext: (queryOperationOptions?: QueryOperationOptions) => Promise<QueryResponse>;
|
||||
fetchNext: () => Promise<QueryResponse>;
|
||||
}
|
||||
|
||||
// Pick<QueryIterator<any>, "fetchNext">;
|
||||
|
||||
export function nextPage(
|
||||
documentsIterator: MinimalQueryIterator,
|
||||
firstItemIndex: number,
|
||||
queryOperationOptions?: QueryOperationOptions,
|
||||
): Promise<QueryResults> {
|
||||
return documentsIterator.fetchNext(queryOperationOptions).then((response) => {
|
||||
export function nextPage(documentsIterator: MinimalQueryIterator, firstItemIndex: number): Promise<QueryResults> {
|
||||
return documentsIterator.fetchNext().then((response) => {
|
||||
const documents = response.resources;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const headers = (response as any).headers || {}; // TODO this is a private key. Remove any
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
jest.mock("./MessageHandler");
|
||||
import { LogEntryLevel } from "../Contracts/Diagnostics";
|
||||
import * as Logger from "./Logger";
|
||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
import { sendMessage } from "./MessageHandler";
|
||||
|
||||
describe("Logger", () => {
|
||||
@@ -9,16 +11,16 @@ describe("Logger", () => {
|
||||
|
||||
it("should log info messages", () => {
|
||||
Logger.logInfo("Test info", "DocDB");
|
||||
expect(sendMessage).toHaveBeenCalled();
|
||||
expect(sendMessage).toBeCalled();
|
||||
});
|
||||
|
||||
it("should log error messages", () => {
|
||||
Logger.logError("Test error", "DocDB");
|
||||
expect(sendMessage).toHaveBeenCalled();
|
||||
expect(sendMessage).toBeCalled();
|
||||
});
|
||||
|
||||
it("should log warnings", () => {
|
||||
Logger.logWarning("Test warning", "DocDB");
|
||||
expect(sendMessage).toHaveBeenCalled();
|
||||
expect(sendMessage).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ function _generateLogEntry(
|
||||
level: Diagnostics.LogEntryLevel,
|
||||
message: string,
|
||||
area: string,
|
||||
code?: number | string,
|
||||
code?: number | string
|
||||
): Diagnostics.LogEntry {
|
||||
return {
|
||||
timestamp: new Date().getUTCSeconds(),
|
||||
|
||||
@@ -22,29 +22,20 @@ export function handleCachedDataMessage(message: any): void {
|
||||
if (messageContent.error != null) {
|
||||
cachedDataPromise.deferred.reject(messageContent.error);
|
||||
} else {
|
||||
cachedDataPromise.deferred.resolve(messageContent.data);
|
||||
cachedDataPromise.deferred.resolve(JSON.parse(messageContent.data));
|
||||
}
|
||||
runGarbageCollector();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param messageType
|
||||
* @param params
|
||||
* @param scope Use this string to identify request Useful to distinguish response from different senders
|
||||
* @param timeoutInMs
|
||||
* @returns
|
||||
*/
|
||||
export function sendCachedDataMessage<TResponseDataModel>(
|
||||
messageType: MessageTypes,
|
||||
params: Object[],
|
||||
scope?: string,
|
||||
timeoutInMs?: number,
|
||||
timeoutInMs?: number
|
||||
): Q.Promise<TResponseDataModel> {
|
||||
let cachedDataPromise: CachedDataPromise<TResponseDataModel> = {
|
||||
deferred: Q.defer<TResponseDataModel>(),
|
||||
startTime: new Date(),
|
||||
id: _.uniqueId(scope),
|
||||
id: _.uniqueId(),
|
||||
};
|
||||
RequestMap[cachedDataPromise.id] = cachedDataPromise;
|
||||
sendMessage({ type: messageType, params: params, id: cachedDataPromise.id });
|
||||
@@ -52,14 +43,10 @@ export function sendCachedDataMessage<TResponseDataModel>(
|
||||
//TODO: Use telemetry to measure optimal time to resolve/reject promises
|
||||
return cachedDataPromise.deferred.promise.timeout(
|
||||
timeoutInMs || Constants.ClientDefaults.requestTimeoutMs,
|
||||
"Timed out while waiting for response from portal",
|
||||
"Timed out while waiting for response from portal"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param data Overwrite the data property of the message
|
||||
*/
|
||||
export function sendMessage(data: any): void {
|
||||
_sendMessage({
|
||||
signature: "pcIframe",
|
||||
|
||||
@@ -38,7 +38,7 @@ const collection = {
|
||||
},
|
||||
} as Collection;
|
||||
|
||||
const documentId = {
|
||||
const documentId = ({
|
||||
partitionKeyHeader: () => "[]",
|
||||
self: "db/testDB/db/testCollection/docs/testId",
|
||||
partitionKeyProperties,
|
||||
@@ -47,7 +47,7 @@ const documentId = {
|
||||
kind: "Hash",
|
||||
version: 1,
|
||||
},
|
||||
} as unknown as DocumentId;
|
||||
} as unknown) as DocumentId;
|
||||
|
||||
const databaseAccount = {
|
||||
id: "foo",
|
||||
@@ -83,7 +83,7 @@ describe("MongoProxyClient", () => {
|
||||
queryDocuments(databaseId, collection, true, "{}");
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://main.documentdb.ext.azure.com/api/mongo/explorer/resourcelist?db=testDB&coll=testCollection&resourceUrl=bardbs%2FtestDB%2Fcolls%2FtestCollection%2Fdocs%2F&rid=testCollectionrid&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -92,7 +92,7 @@ describe("MongoProxyClient", () => {
|
||||
queryDocuments(databaseId, collection, true, "{}");
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://localhost:1234/api/mongo/explorer/resourcelist?db=testDB&coll=testCollection&resourceUrl=bardbs%2FtestDB%2Fcolls%2FtestCollection%2Fdocs%2F&rid=testCollectionrid&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -115,7 +115,7 @@ describe("MongoProxyClient", () => {
|
||||
readDocument(databaseId, collection, documentId);
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://main.documentdb.ext.azure.com/api/mongo/explorer?db=testDB&coll=testCollection&resourceUrl=bardb%2FtestDB%2Fdb%2FtestCollection%2FtestId&rid=testId&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -124,7 +124,7 @@ describe("MongoProxyClient", () => {
|
||||
readDocument(databaseId, collection, documentId);
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://localhost:1234/api/mongo/explorer?db=testDB&coll=testCollection&resourceUrl=bardb%2FtestDB%2Fdb%2FtestCollection%2FtestId&rid=testId&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -147,7 +147,7 @@ describe("MongoProxyClient", () => {
|
||||
readDocument(databaseId, collection, documentId);
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://main.documentdb.ext.azure.com/api/mongo/explorer?db=testDB&coll=testCollection&resourceUrl=bardb%2FtestDB%2Fdb%2FtestCollection%2FtestId&rid=testId&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -156,7 +156,7 @@ describe("MongoProxyClient", () => {
|
||||
readDocument(databaseId, collection, documentId);
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://localhost:1234/api/mongo/explorer?db=testDB&coll=testCollection&resourceUrl=bardb%2FtestDB%2Fdb%2FtestCollection%2FtestId&rid=testId&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -179,7 +179,7 @@ describe("MongoProxyClient", () => {
|
||||
updateDocument(databaseId, collection, documentId, "{}");
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://main.documentdb.ext.azure.com/api/mongo/explorer?db=testDB&coll=testCollection&resourceUrl=bardb%2FtestDB%2Fdb%2FtestCollection%2Fdocs%2FtestId&rid=testId&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -188,7 +188,7 @@ describe("MongoProxyClient", () => {
|
||||
updateDocument(databaseId, collection, documentId, "{}");
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://localhost:1234/api/mongo/explorer?db=testDB&coll=testCollection&resourceUrl=bardb%2FtestDB%2Fdb%2FtestCollection%2Fdocs%2FtestId&rid=testId&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -211,7 +211,7 @@ describe("MongoProxyClient", () => {
|
||||
deleteDocument(databaseId, collection, documentId);
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://main.documentdb.ext.azure.com/api/mongo/explorer?db=testDB&coll=testCollection&resourceUrl=bardb%2FtestDB%2Fdb%2FtestCollection%2Fdocs%2FtestId&rid=testId&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -220,7 +220,7 @@ describe("MongoProxyClient", () => {
|
||||
deleteDocument(databaseId, collection, documentId);
|
||||
expect(window.fetch).toHaveBeenCalledWith(
|
||||
"https://localhost:1234/api/mongo/explorer?db=testDB&coll=testCollection&resourceUrl=bardb%2FtestDB%2Fdb%2FtestCollection%2Fdocs%2FtestId&rid=testId&rtype=docs&sid=&rg=&dba=foo&pk=pk",
|
||||
expect.any(Object),
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { Constants as CosmosSDKConstants } from "@azure/cosmos";
|
||||
import {
|
||||
allowedMongoProxyEndpoints,
|
||||
allowedMongoProxyEndpoints_ToBeDeprecated,
|
||||
validateEndpoint,
|
||||
} from "Utils/EndpointUtils";
|
||||
import queryString from "querystring";
|
||||
import { allowedMongoProxyEndpoints, validateEndpoint } from "Utils/EndpointValidation";
|
||||
import { AuthType } from "../AuthType";
|
||||
import { configContext } from "../ConfigContext";
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
@@ -14,7 +10,7 @@ import DocumentId from "../Explorer/Tree/DocumentId";
|
||||
import { hasFlag } from "../Platform/Hosted/extractFeatures";
|
||||
import { userContext } from "../UserContext";
|
||||
import { logConsoleError } from "../Utils/NotificationConsoleUtils";
|
||||
import { ApiType, ContentType, HttpHeaders, HttpStatusCodes, MongoProxyEndpoints } from "./Constants";
|
||||
import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants";
|
||||
import { MinimalQueryIterator } from "./IteratorUtilities";
|
||||
import { sendMessage } from "./MessageHandler";
|
||||
|
||||
@@ -65,74 +61,7 @@ export function queryDocuments(
|
||||
collection: Collection,
|
||||
isResourceList: boolean,
|
||||
query: string,
|
||||
continuationToken?: string,
|
||||
): Promise<QueryResponse> {
|
||||
if (!useMongoProxyEndpoint("resourcelist") || !useMongoProxyEndpoint("queryDocuments")) {
|
||||
return queryDocuments_ToBeDeprecated(databaseId, collection, isResourceList, query, continuationToken);
|
||||
}
|
||||
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
const params = {
|
||||
databaseID: databaseId,
|
||||
collectionID: collection.id(),
|
||||
resourceUrl: `${resourceEndpoint}dbs/${databaseId}/colls/${collection.id()}/docs/`,
|
||||
resourceID: collection.rid,
|
||||
resourceType: "docs",
|
||||
subscriptionID: userContext.subscriptionId,
|
||||
resourceGroup: userContext.resourceGroup,
|
||||
databaseAccountName: databaseAccount.name,
|
||||
partitionKey:
|
||||
collection && collection.partitionKey && !collection.partitionKey.systemKey
|
||||
? collection.partitionKeyProperties?.[0]
|
||||
: "",
|
||||
query,
|
||||
};
|
||||
|
||||
const endpoint = getFeatureEndpointOrDefault("resourcelist") || "";
|
||||
|
||||
const headers = {
|
||||
...defaultHeaders,
|
||||
...authHeaders(),
|
||||
[CosmosSDKConstants.HttpHeaders.IsQuery]: "true",
|
||||
[CosmosSDKConstants.HttpHeaders.PopulateQueryMetrics]: "true",
|
||||
[CosmosSDKConstants.HttpHeaders.EnableScanInQuery]: "true",
|
||||
[CosmosSDKConstants.HttpHeaders.EnableCrossPartitionQuery]: "true",
|
||||
[CosmosSDKConstants.HttpHeaders.ParallelizeCrossPartitionQuery]: "true",
|
||||
[HttpHeaders.contentType]: "application/query+json",
|
||||
};
|
||||
|
||||
if (continuationToken) {
|
||||
headers[CosmosSDKConstants.HttpHeaders.Continuation] = continuationToken;
|
||||
}
|
||||
|
||||
const path = isResourceList ? "/resourcelist" : "/queryDocuments";
|
||||
|
||||
return window
|
||||
.fetch(`${endpoint}${path}`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
headers,
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (response.ok) {
|
||||
return {
|
||||
continuationToken: response.headers.get(CosmosSDKConstants.HttpHeaders.Continuation),
|
||||
documents: (await response.json()).Documents as DataModels.DocumentId[],
|
||||
headers: response.headers,
|
||||
};
|
||||
}
|
||||
await errorHandling(response, "querying documents", params);
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
function queryDocuments_ToBeDeprecated(
|
||||
databaseId: string,
|
||||
collection: Collection,
|
||||
isResourceList: boolean,
|
||||
query: string,
|
||||
continuationToken?: string,
|
||||
continuationToken?: string
|
||||
): Promise<QueryResponse> {
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
@@ -192,55 +121,7 @@ function queryDocuments_ToBeDeprecated(
|
||||
export function readDocument(
|
||||
databaseId: string,
|
||||
collection: Collection,
|
||||
documentId: DocumentId,
|
||||
): Promise<DataModels.DocumentId> {
|
||||
if (!useMongoProxyEndpoint("readDocument")) {
|
||||
return readDocument_ToBeDeprecated(databaseId, collection, documentId);
|
||||
}
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
const idComponents = documentId.self.split("/");
|
||||
const path = idComponents.slice(0, 4).join("/");
|
||||
const rid = encodeURIComponent(idComponents[5]);
|
||||
const params = {
|
||||
databaseID: databaseId,
|
||||
collectionID: collection.id(),
|
||||
resourceUrl: `${resourceEndpoint}${path}/${rid}`,
|
||||
resourceID: rid,
|
||||
resourceType: "docs",
|
||||
subscriptionID: userContext.subscriptionId,
|
||||
resourceGroup: userContext.resourceGroup,
|
||||
databaseAccountName: databaseAccount.name,
|
||||
partitionKey:
|
||||
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
||||
? documentId.partitionKeyProperties?.[0]
|
||||
: "",
|
||||
};
|
||||
|
||||
const endpoint = getFeatureEndpointOrDefault("readDocument");
|
||||
|
||||
return window
|
||||
.fetch(endpoint, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...authHeaders(),
|
||||
[HttpHeaders.contentType]: ContentType.applicationJson,
|
||||
},
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return await errorHandling(response, "reading document", params);
|
||||
});
|
||||
}
|
||||
|
||||
export function readDocument_ToBeDeprecated(
|
||||
databaseId: string,
|
||||
collection: Collection,
|
||||
documentId: DocumentId,
|
||||
documentId: DocumentId
|
||||
): Promise<DataModels.DocumentId> {
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
@@ -271,7 +152,7 @@ export function readDocument_ToBeDeprecated(
|
||||
...defaultHeaders,
|
||||
...authHeaders(),
|
||||
[CosmosSDKConstants.HttpHeaders.PartitionKey]: encodeURIComponent(
|
||||
JSON.stringify(documentId.partitionKeyHeader()),
|
||||
JSON.stringify(documentId.partitionKeyHeader())
|
||||
),
|
||||
},
|
||||
})
|
||||
@@ -287,52 +168,7 @@ export function createDocument(
|
||||
databaseId: string,
|
||||
collection: Collection,
|
||||
partitionKeyProperty: string,
|
||||
documentContent: unknown,
|
||||
): Promise<DataModels.DocumentId> {
|
||||
if (!useMongoProxyEndpoint("createDocument")) {
|
||||
return createDocument_ToBeDeprecated(databaseId, collection, partitionKeyProperty, documentContent);
|
||||
}
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
const params = {
|
||||
databaseID: databaseId,
|
||||
collectionID: collection.id(),
|
||||
resourceUrl: `${resourceEndpoint}dbs/${databaseId}/colls/${collection.id()}/docs/`,
|
||||
resourceID: collection.rid,
|
||||
resourceType: "docs",
|
||||
subscriptionID: userContext.subscriptionId,
|
||||
resourceGroup: userContext.resourceGroup,
|
||||
databaseAccountName: databaseAccount.name,
|
||||
partitionKey:
|
||||
collection && collection.partitionKey && !collection.partitionKey.systemKey ? partitionKeyProperty : "",
|
||||
documentContent: JSON.stringify(documentContent),
|
||||
};
|
||||
|
||||
const endpoint = getFeatureEndpointOrDefault("createDocument");
|
||||
|
||||
return window
|
||||
.fetch(`${endpoint}/createDocument`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(params),
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...authHeaders(),
|
||||
[HttpHeaders.contentType]: ContentType.applicationJson,
|
||||
},
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return await errorHandling(response, "creating document", params);
|
||||
});
|
||||
}
|
||||
|
||||
export function createDocument_ToBeDeprecated(
|
||||
databaseId: string,
|
||||
collection: Collection,
|
||||
partitionKeyProperty: string,
|
||||
documentContent: unknown,
|
||||
documentContent: unknown
|
||||
): Promise<DataModels.DocumentId> {
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
@@ -371,57 +207,7 @@ export function updateDocument(
|
||||
databaseId: string,
|
||||
collection: Collection,
|
||||
documentId: DocumentId,
|
||||
documentContent: string,
|
||||
): Promise<DataModels.DocumentId> {
|
||||
if (!useMongoProxyEndpoint("updateDocument")) {
|
||||
return updateDocument_ToBeDeprecated(databaseId, collection, documentId, documentContent);
|
||||
}
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
const idComponents = documentId.self.split("/");
|
||||
const path = idComponents.slice(0, 5).join("/");
|
||||
const rid = encodeURIComponent(idComponents[5]);
|
||||
const params = {
|
||||
databaseID: databaseId,
|
||||
collectionID: collection.id(),
|
||||
resourceUrl: `${resourceEndpoint}${path}/${rid}`,
|
||||
resourceID: rid,
|
||||
resourceType: "docs",
|
||||
subscriptionID: userContext.subscriptionId,
|
||||
resourceGroup: userContext.resourceGroup,
|
||||
databaseAccountName: databaseAccount.name,
|
||||
partitionKey:
|
||||
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
||||
? documentId.partitionKeyProperties?.[0]
|
||||
: "",
|
||||
documentContent,
|
||||
};
|
||||
const endpoint = getFeatureEndpointOrDefault("updateDocument");
|
||||
|
||||
return window
|
||||
.fetch(endpoint, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(params),
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...authHeaders(),
|
||||
[HttpHeaders.contentType]: ContentType.applicationJson,
|
||||
[CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()),
|
||||
},
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return await errorHandling(response, "updating document", params);
|
||||
});
|
||||
}
|
||||
|
||||
export function updateDocument_ToBeDeprecated(
|
||||
databaseId: string,
|
||||
collection: Collection,
|
||||
documentId: DocumentId,
|
||||
documentContent: string,
|
||||
documentContent: string
|
||||
): Promise<DataModels.DocumentId> {
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
@@ -451,7 +237,7 @@ export function updateDocument_ToBeDeprecated(
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...authHeaders(),
|
||||
[HttpHeaders.contentType]: ContentType.applicationJson,
|
||||
[HttpHeaders.contentType]: "application/json",
|
||||
[CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()),
|
||||
},
|
||||
})
|
||||
@@ -464,53 +250,6 @@ export function updateDocument_ToBeDeprecated(
|
||||
}
|
||||
|
||||
export function deleteDocument(databaseId: string, collection: Collection, documentId: DocumentId): Promise<void> {
|
||||
if (!useMongoProxyEndpoint("deleteDocument")) {
|
||||
return deleteDocument_ToBeDeprecated(databaseId, collection, documentId);
|
||||
}
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
const idComponents = documentId.self.split("/");
|
||||
const path = idComponents.slice(0, 5).join("/");
|
||||
const rid = encodeURIComponent(idComponents[5]);
|
||||
const params = {
|
||||
databaseID: databaseId,
|
||||
collectionID: collection.id(),
|
||||
resourceUrl: `${resourceEndpoint}${path}/${rid}`,
|
||||
resourceID: rid,
|
||||
resourceType: "docs",
|
||||
subscriptionID: userContext.subscriptionId,
|
||||
resourceGroup: userContext.resourceGroup,
|
||||
databaseAccountName: databaseAccount.name,
|
||||
partitionKey:
|
||||
documentId && documentId.partitionKey && !documentId.partitionKey.systemKey
|
||||
? documentId.partitionKeyProperties?.[0]
|
||||
: "",
|
||||
};
|
||||
const endpoint = getFeatureEndpointOrDefault("deleteDocument");
|
||||
|
||||
return window
|
||||
.fetch(endpoint, {
|
||||
method: "DELETE",
|
||||
body: JSON.stringify(params),
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...authHeaders(),
|
||||
[HttpHeaders.contentType]: ContentType.applicationJson,
|
||||
},
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (response.ok) {
|
||||
return undefined;
|
||||
}
|
||||
return await errorHandling(response, "deleting document", params);
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteDocument_ToBeDeprecated(
|
||||
databaseId: string,
|
||||
collection: Collection,
|
||||
documentId: DocumentId,
|
||||
): Promise<void> {
|
||||
const { databaseAccount } = userContext;
|
||||
const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint;
|
||||
const idComponents = documentId.self.split("/");
|
||||
@@ -538,7 +277,7 @@ export function deleteDocument_ToBeDeprecated(
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...authHeaders(),
|
||||
[HttpHeaders.contentType]: ContentType.applicationJson,
|
||||
[HttpHeaders.contentType]: "application/json",
|
||||
[CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()),
|
||||
},
|
||||
})
|
||||
@@ -551,53 +290,7 @@ export function deleteDocument_ToBeDeprecated(
|
||||
}
|
||||
|
||||
export function createMongoCollectionWithProxy(
|
||||
params: DataModels.CreateCollectionParams,
|
||||
): Promise<DataModels.Collection> {
|
||||
if (!useMongoProxyEndpoint("createCollectionWithProxy")) {
|
||||
return createMongoCollectionWithProxy_ToBeDeprecated(params);
|
||||
}
|
||||
const { databaseAccount } = userContext;
|
||||
const shardKey: string = params.partitionKey?.paths[0];
|
||||
|
||||
const createCollectionParams = {
|
||||
databaseID: params.databaseId,
|
||||
collectionID: params.collectionId,
|
||||
resourceUrl: databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint,
|
||||
resourceID: "",
|
||||
resourceType: "colls",
|
||||
subscriptionID: userContext.subscriptionId,
|
||||
resourceGroup: userContext.resourceGroup,
|
||||
databaseAccountName: databaseAccount.name,
|
||||
partitionKey: shardKey,
|
||||
isAutoscale: !!params.autoPilotMaxThroughput,
|
||||
hasSharedThroughput: params.databaseLevelThroughput,
|
||||
offerThroughput: params.autoPilotMaxThroughput || params.offerThroughput,
|
||||
createDatabase: params.createNewDatabase,
|
||||
isSharded: !!shardKey,
|
||||
};
|
||||
|
||||
const endpoint = getFeatureEndpointOrDefault("createCollectionWithProxy");
|
||||
|
||||
return window
|
||||
.fetch(`${endpoint}/createCollection`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(createCollectionParams),
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...authHeaders(),
|
||||
[HttpHeaders.contentType]: ContentType.applicationJson,
|
||||
},
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
}
|
||||
return await errorHandling(response, "creating collection", createCollectionParams);
|
||||
});
|
||||
}
|
||||
|
||||
export function createMongoCollectionWithProxy_ToBeDeprecated(
|
||||
params: DataModels.CreateCollectionParams,
|
||||
params: DataModels.CreateCollectionParams
|
||||
): Promise<DataModels.Collection> {
|
||||
const { databaseAccount } = userContext;
|
||||
const shardKey: string = params.partitionKey?.paths[0];
|
||||
@@ -623,7 +316,7 @@ export function createMongoCollectionWithProxy_ToBeDeprecated(
|
||||
return window
|
||||
.fetch(
|
||||
`${endpoint}/createCollection?${queryString.stringify(
|
||||
mongoParams as unknown as queryString.ParsedUrlQueryInput,
|
||||
(mongoParams as unknown) as queryString.ParsedUrlQueryInput
|
||||
)}`,
|
||||
{
|
||||
method: "POST",
|
||||
@@ -632,7 +325,7 @@ export function createMongoCollectionWithProxy_ToBeDeprecated(
|
||||
...authHeaders(),
|
||||
[HttpHeaders.contentType]: "application/json",
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
.then(async (response) => {
|
||||
if (response.ok) {
|
||||
@@ -641,20 +334,13 @@ export function createMongoCollectionWithProxy_ToBeDeprecated(
|
||||
return await errorHandling(response, "creating collection", mongoParams);
|
||||
});
|
||||
}
|
||||
|
||||
export function getFeatureEndpointOrDefault(feature: string): string {
|
||||
let endpoint;
|
||||
if (useMongoProxyEndpoint(feature)) {
|
||||
endpoint = configContext.MONGO_PROXY_ENDPOINT;
|
||||
} else {
|
||||
endpoint =
|
||||
hasFlag(userContext.features.mongoProxyAPIs, feature) &&
|
||||
validateEndpoint(userContext.features.mongoProxyEndpoint, [
|
||||
...allowedMongoProxyEndpoints,
|
||||
...allowedMongoProxyEndpoints_ToBeDeprecated,
|
||||
])
|
||||
? userContext.features.mongoProxyEndpoint
|
||||
: configContext.MONGO_BACKEND_ENDPOINT || configContext.BACKEND_ENDPOINT;
|
||||
}
|
||||
const endpoint =
|
||||
hasFlag(userContext.features.mongoProxyAPIs, feature) &&
|
||||
validateEndpoint(userContext.features.mongoProxyEndpoint, allowedMongoProxyEndpoints)
|
||||
? userContext.features.mongoProxyEndpoint
|
||||
: configContext.MONGO_BACKEND_ENDPOINT || configContext.BACKEND_ENDPOINT;
|
||||
|
||||
return getEndpoint(endpoint);
|
||||
}
|
||||
@@ -663,11 +349,7 @@ export function getEndpoint(endpoint: string): string {
|
||||
let url = endpoint + "/api/mongo/explorer";
|
||||
|
||||
if (userContext.authType === AuthType.EncryptedToken) {
|
||||
if (endpoint === configContext.MONGO_PROXY_ENDPOINT) {
|
||||
url = url.replace("api/mongo", "api/connectionstring/mongo");
|
||||
} else {
|
||||
url = url.replace("api/mongo", "api/guest/mongo");
|
||||
}
|
||||
url = url.replace("api/mongo", "api/guest/mongo");
|
||||
}
|
||||
return url;
|
||||
}
|
||||
@@ -688,24 +370,3 @@ async function errorHandling(response: Response, action: string, params: unknown
|
||||
export function getARMCreateCollectionEndpoint(params: DataModels.MongoParameters): string {
|
||||
return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/mongodbDatabases/${params.db}/collections/${params.coll}`;
|
||||
}
|
||||
|
||||
function useMongoProxyEndpoint(api: string): boolean {
|
||||
const activeMongoProxyEndpoints: string[] = [
|
||||
MongoProxyEndpoints.Development,
|
||||
MongoProxyEndpoints.Mpac,
|
||||
MongoProxyEndpoints.Prod,
|
||||
];
|
||||
let canAccessMongoProxy: boolean = userContext.databaseAccount.properties.publicNetworkAccess === "Enabled";
|
||||
if (
|
||||
configContext.MONGO_PROXY_ENDPOINT !== MongoProxyEndpoints.Development &&
|
||||
userContext.databaseAccount.properties.ipRules?.length > 0
|
||||
) {
|
||||
canAccessMongoProxy = canAccessMongoProxy && configContext.MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED;
|
||||
}
|
||||
|
||||
return (
|
||||
canAccessMongoProxy &&
|
||||
configContext.NEW_MONGO_APIS?.includes(api) &&
|
||||
activeMongoProxyEndpoints.includes(configContext.MONGO_PROXY_ENDPOINT)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { isServerlessAccount } from "Utils/CapabilityUtils";
|
||||
import * as _ from "underscore";
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
import * as ViewModels from "../Contracts/ViewModels";
|
||||
@@ -9,11 +8,11 @@ import { useDatabases } from "../Explorer/useDatabases";
|
||||
import { userContext } from "../UserContext";
|
||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||
import { BackendDefaults, HttpStatusCodes, SavedQueries } from "./Constants";
|
||||
import { handleError } from "./ErrorHandlingUtils";
|
||||
import { createCollection } from "./dataAccess/createCollection";
|
||||
import { createDocument } from "./dataAccess/createDocument";
|
||||
import { deleteDocument } from "./dataAccess/deleteDocument";
|
||||
import { queryDocuments } from "./dataAccess/queryDocuments";
|
||||
import { handleError } from "./ErrorHandlingUtils";
|
||||
|
||||
export class QueriesClient {
|
||||
private static readonly PartitionKey: DataModels.PartitionKey = {
|
||||
@@ -33,36 +32,25 @@ export class QueriesClient {
|
||||
}
|
||||
|
||||
const clearMessage = NotificationConsoleUtils.logConsoleProgress("Setting up account for saving queries");
|
||||
|
||||
if (isServerlessAccount()) {
|
||||
return createCollection({
|
||||
collectionId: SavedQueries.CollectionName,
|
||||
createNewDatabase: true,
|
||||
databaseId: SavedQueries.DatabaseName,
|
||||
partitionKey: QueriesClient.PartitionKey,
|
||||
databaseLevelThroughput: false,
|
||||
});
|
||||
} else {
|
||||
return createCollection({
|
||||
collectionId: SavedQueries.CollectionName,
|
||||
createNewDatabase: true,
|
||||
databaseId: SavedQueries.DatabaseName,
|
||||
partitionKey: QueriesClient.PartitionKey,
|
||||
offerThroughput: SavedQueries.OfferThroughput,
|
||||
databaseLevelThroughput: false,
|
||||
})
|
||||
.then(
|
||||
(collection: DataModels.Collection) => {
|
||||
NotificationConsoleUtils.logConsoleInfo("Successfully set up account for saving queries");
|
||||
return Promise.resolve(collection);
|
||||
},
|
||||
(error: any) => {
|
||||
handleError(error, "setupQueriesCollection", "Failed to set up account for saving queries");
|
||||
return Promise.reject(error);
|
||||
},
|
||||
)
|
||||
.finally(() => clearMessage());
|
||||
}
|
||||
return createCollection({
|
||||
collectionId: SavedQueries.CollectionName,
|
||||
createNewDatabase: true,
|
||||
databaseId: SavedQueries.DatabaseName,
|
||||
partitionKey: QueriesClient.PartitionKey,
|
||||
offerThroughput: SavedQueries.OfferThroughput,
|
||||
databaseLevelThroughput: false,
|
||||
})
|
||||
.then(
|
||||
(collection: DataModels.Collection) => {
|
||||
NotificationConsoleUtils.logConsoleInfo("Successfully set up account for saving queries");
|
||||
return Promise.resolve(collection);
|
||||
},
|
||||
(error: any) => {
|
||||
handleError(error, "setupQueriesCollection", "Failed to set up account for saving queries");
|
||||
return Promise.reject(error);
|
||||
}
|
||||
)
|
||||
.finally(() => clearMessage());
|
||||
}
|
||||
|
||||
public async saveQuery(query: DataModels.Query): Promise<void> {
|
||||
@@ -95,7 +83,7 @@ export class QueriesClient {
|
||||
}
|
||||
handleError(error, "saveQuery", `Failed to save query ${query.queryName}`);
|
||||
return Promise.reject(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
.finally(() => clearMessage());
|
||||
}
|
||||
@@ -114,7 +102,7 @@ export class QueriesClient {
|
||||
SavedQueries.DatabaseName,
|
||||
SavedQueries.CollectionName,
|
||||
this.fetchQueriesQuery(),
|
||||
options,
|
||||
options
|
||||
).fetchAll();
|
||||
|
||||
let queries: DataModels.Query[] = _.map(results.resources, (document: DataModels.Query) => {
|
||||
@@ -164,7 +152,7 @@ export class QueriesClient {
|
||||
partitionKeyProperties: ["id"],
|
||||
} as DocumentsTab,
|
||||
query,
|
||||
[query.queryName],
|
||||
[query.queryName]
|
||||
); // TODO: Remove DocumentId's dependency on DocumentsTab
|
||||
const options: any = { partitionKey: query.resourceId };
|
||||
return deleteDocument(queriesCollection, documentId)
|
||||
@@ -176,7 +164,7 @@ export class QueriesClient {
|
||||
(error: any) => {
|
||||
handleError(error, "deleteQuery", `Failed to delete query ${query.queryName}`);
|
||||
return Promise.reject(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
.finally(() => clearMessage());
|
||||
}
|
||||
@@ -190,14 +178,14 @@ export class QueriesClient {
|
||||
private findQueriesCollection(): ViewModels.Collection {
|
||||
const queriesDatabase: ViewModels.Database = _.find(
|
||||
useDatabases.getState().databases,
|
||||
(database: ViewModels.Database) => database.id() === SavedQueries.DatabaseName,
|
||||
(database: ViewModels.Database) => database.id() === SavedQueries.DatabaseName
|
||||
);
|
||||
if (!queriesDatabase) {
|
||||
return undefined;
|
||||
}
|
||||
return _.find(
|
||||
queriesDatabase.collections(),
|
||||
(collection: ViewModels.Collection) => collection.id() === SavedQueries.CollectionName,
|
||||
(collection: ViewModels.Collection) => collection.id() === SavedQueries.CollectionName
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { ResourceTree } from "Explorer/Tree/ResourceTree";
|
||||
import React, { FunctionComponent, MutableRefObject, useEffect, useRef } from "react";
|
||||
import arrowLeftImg from "../../images/imgarrowlefticon.svg";
|
||||
import refreshImg from "../../images/refresh-cosmos.svg";
|
||||
import { AuthType } from "../AuthType";
|
||||
import Explorer from "../Explorer/Explorer";
|
||||
import { ResourceTokenTree } from "../Explorer/Tree/ResourceTokenTree";
|
||||
import { ResourceTree2 } from "../Explorer/Tree2/ResourceTree";
|
||||
import { ResourceTree } from "../Explorer/Tree/ResourceTree";
|
||||
import { userContext } from "../UserContext";
|
||||
import { getApiShortDisplayName } from "../Utils/APITypeUtils";
|
||||
import { Platform, configContext } from "./../ConfigContext";
|
||||
import { NormalizedEventKey } from "./Constants";
|
||||
|
||||
export interface ResourceTreeContainerProps {
|
||||
@@ -78,8 +76,6 @@ export const ResourceTreeContainer: FunctionComponent<ResourceTreeContainerProps
|
||||
<ResourceTokenTree />
|
||||
) : userContext.features.enableKoResourceTree ? (
|
||||
<div style={{ overflowY: "auto" }} data-bind="react:resourceTree" />
|
||||
) : configContext.platform === Platform.Fabric ? (
|
||||
<ResourceTree2 container={container} />
|
||||
) : (
|
||||
<ResourceTree container={container} />
|
||||
)}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Platform, configContext } from "../ConfigContext";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
export const StyleConstants = require("less-vars-loader!../../less/Common/Constants.less");
|
||||
|
||||
export function updateStyles(): void {
|
||||
if (configContext.platform === Platform.Fabric) {
|
||||
StyleConstants.AccentMediumHigh = StyleConstants.FabricAccentMediumHigh;
|
||||
StyleConstants.AccentMedium = StyleConstants.FabricAccentMedium;
|
||||
StyleConstants.AccentLight = StyleConstants.FabricAccentLight;
|
||||
StyleConstants.AccentAccentExtra = StyleConstants.FabricAccentMediumHigh;
|
||||
} else {
|
||||
StyleConstants.AccentMediumHigh = StyleConstants.PortalAccentMediumHigh;
|
||||
StyleConstants.AccentMedium = StyleConstants.PortalAccentMedium;
|
||||
StyleConstants.AccentLight = StyleConstants.PortalAccentLight;
|
||||
StyleConstants.AccentAccentExtra = StyleConstants.PortalAccentMediumHigh;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
import React, { FunctionComponent } from "react";
|
||||
import DeleteIcon from "../../images/delete.svg";
|
||||
import EditIcon from "../../images/Edit_entity.svg";
|
||||
import { attributeNameLabel, dataTypeLabel } from "../Explorer/Panes/Tables/Validators/EntityTableHelper";
|
||||
import { CassandraType, TableType } from "../Explorer/Tables/Constants";
|
||||
import { userContext } from "../UserContext";
|
||||
import { EntityValue } from "./EntityValue";
|
||||
@@ -113,7 +112,6 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
|
||||
value={entityProperty}
|
||||
onChange={onEntityPropertyChange}
|
||||
required
|
||||
ariaLabel={attributeNameLabel}
|
||||
/>
|
||||
<Dropdown
|
||||
label={entityTypeLabel && entityTypeLabel}
|
||||
@@ -122,7 +120,6 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
|
||||
options={options}
|
||||
disabled={isPropertyTypeDisable}
|
||||
styles={dropdownStyles}
|
||||
ariaLabel={dataTypeLabel}
|
||||
/>
|
||||
<EntityValue
|
||||
entityValueLabel={entityValueLabel}
|
||||
@@ -146,7 +143,6 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
|
||||
onClick={onEditEntity}
|
||||
tabIndex={0}
|
||||
onKeyPress={handleKeyPress}
|
||||
role="button"
|
||||
/>
|
||||
</div>
|
||||
</TooltipHost>
|
||||
@@ -161,7 +157,6 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
|
||||
onClick={onDeleteEntity}
|
||||
tabIndex={0}
|
||||
onKeyPress={handleKeyPressdelete}
|
||||
role="button"
|
||||
/>
|
||||
</TooltipHost>
|
||||
)}
|
||||
|
||||
@@ -6,10 +6,10 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
|
||||
export const bulkCreateDocument = async (
|
||||
collection: CollectionBase,
|
||||
documents: JSONObject[],
|
||||
documents: JSONObject[]
|
||||
): Promise<OperationResponse[]> => {
|
||||
const clearMessage = logConsoleProgress(
|
||||
`Executing ${documents.length} bulk operations for container ${collection.id()}`,
|
||||
`Executing ${documents.length} bulk operations for container ${collection.id()}`
|
||||
);
|
||||
|
||||
try {
|
||||
@@ -18,7 +18,7 @@ export const bulkCreateDocument = async (
|
||||
.container(collection.id())
|
||||
.items.bulk(
|
||||
documents.map((doc) => ({ operationType: "Create", resourceBody: doc })),
|
||||
{ continueOnError: true },
|
||||
{ continueOnError: true }
|
||||
);
|
||||
|
||||
const successCount = response.filter((r) => r.statusCode === 201).length;
|
||||
@@ -27,7 +27,7 @@ export const bulkCreateDocument = async (
|
||||
logConsoleInfo(
|
||||
`${
|
||||
documents.length
|
||||
} operations completed for container ${collection.id()}. ${successCount} operations succeeded. ${throttledCount} operations throttled`,
|
||||
} operations completed for container ${collection.id()}. ${successCount} operations succeeded. ${throttledCount} operations throttled`
|
||||
);
|
||||
return response;
|
||||
} catch (error) {
|
||||
|
||||
@@ -20,7 +20,7 @@ import { createDatabase } from "./createDatabase";
|
||||
|
||||
export const createCollection = async (params: DataModels.CreateCollectionParams): Promise<DataModels.Collection> => {
|
||||
const clearMessage = logConsoleProgress(
|
||||
`Creating a new container ${params.collectionId} for database ${params.databaseId}`,
|
||||
`Creating a new container ${params.collectionId} for database ${params.databaseId}`
|
||||
);
|
||||
try {
|
||||
let collection: DataModels.Collection;
|
||||
@@ -57,7 +57,7 @@ const createCollectionWithARM = async (params: DataModels.CreateCollectionParams
|
||||
if (!isValid) {
|
||||
const collectionName = getCollectionName().toLocaleLowerCase();
|
||||
throw new Error(
|
||||
`Create ${collectionName} failed: ${collectionName} with id ${params.collectionId} already exists`,
|
||||
`Create ${collectionName} failed: ${collectionName} with id ${params.collectionId} already exists`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ const createSqlContainer = async (params: DataModels.CreateCollectionParams): Pr
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
rpPayload,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Collection);
|
||||
};
|
||||
@@ -145,7 +145,7 @@ const createMongoCollection = async (params: DataModels.CreateCollectionParams):
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
rpPayload,
|
||||
rpPayload
|
||||
);
|
||||
|
||||
if (params.createMongoWildcardIndex) {
|
||||
@@ -179,7 +179,7 @@ const createCassandraTable = async (params: DataModels.CreateCollectionParams):
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
rpPayload,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Collection);
|
||||
};
|
||||
@@ -213,7 +213,7 @@ const createGraph = async (params: DataModels.CreateCollectionParams): Promise<D
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
rpPayload,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Collection);
|
||||
};
|
||||
@@ -236,7 +236,7 @@ const createTable = async (params: DataModels.CreateCollectionParams): Promise<D
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.collectionId,
|
||||
rpPayload,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Collection);
|
||||
};
|
||||
@@ -287,7 +287,7 @@ const createCollectionWithSDK = async (params: DataModels.CreateCollectionParams
|
||||
const databaseResponse: DatabaseResponse = await client().databases.createIfNotExists(createDatabaseBody);
|
||||
const collectionResponse: ContainerResponse = await databaseResponse?.database.containers.create(
|
||||
createCollectionBody,
|
||||
collectionOptions,
|
||||
collectionOptions
|
||||
);
|
||||
return collectionResponse?.resource as DataModels.Collection;
|
||||
};
|
||||
|
||||
@@ -77,7 +77,7 @@ async function createSqlDatabase(params: DataModels.CreateDatabaseParams): Promi
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
rpPayload,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Database);
|
||||
}
|
||||
@@ -97,7 +97,7 @@ async function createMongoDatabase(params: DataModels.CreateDatabaseParams): Pro
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
rpPayload,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Database);
|
||||
}
|
||||
@@ -117,7 +117,7 @@ async function createCassandraKeyspace(params: DataModels.CreateDatabaseParams):
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
rpPayload,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Database);
|
||||
}
|
||||
@@ -137,7 +137,7 @@ async function createGremlineDatabase(params: DataModels.CreateDatabaseParams):
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
params.databaseId,
|
||||
rpPayload,
|
||||
rpPayload
|
||||
);
|
||||
return createResponse && (createResponse.properties.resource as DataModels.Database);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
export async function createStoredProcedure(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
storedProcedure: StoredProcedureDefinition,
|
||||
storedProcedure: StoredProcedureDefinition
|
||||
): Promise<StoredProcedureDefinition & Resource> {
|
||||
const clearMessage = logConsoleProgress(`Creating stored procedure ${storedProcedure.id}`);
|
||||
try {
|
||||
@@ -32,11 +32,11 @@ export async function createStoredProcedure(
|
||||
userContext.databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
storedProcedure.id,
|
||||
storedProcedure.id
|
||||
);
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(
|
||||
`Create stored procedure failed: stored procedure with id ${storedProcedure.id} already exists`,
|
||||
`Create stored procedure failed: stored procedure with id ${storedProcedure.id} already exists`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -58,7 +58,7 @@ export async function createStoredProcedure(
|
||||
databaseId,
|
||||
collectionId,
|
||||
storedProcedure.id,
|
||||
createSprocParams,
|
||||
createSprocParams
|
||||
);
|
||||
return rpResponse && (rpResponse.properties?.resource as StoredProcedureDefinition & Resource);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
export async function createTrigger(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
trigger: SqlTriggerResource,
|
||||
trigger: SqlTriggerResource
|
||||
): Promise<TriggerDefinition | SqlTriggerResource> {
|
||||
const clearMessage = logConsoleProgress(`Creating trigger ${trigger.id}`);
|
||||
try {
|
||||
@@ -26,7 +26,7 @@ export async function createTrigger(
|
||||
userContext.databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
trigger.id,
|
||||
trigger.id
|
||||
);
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(`Create trigger failed: ${trigger.id} already exists`);
|
||||
@@ -50,7 +50,7 @@ export async function createTrigger(
|
||||
databaseId,
|
||||
collectionId,
|
||||
trigger.id,
|
||||
createTriggerParams,
|
||||
createTriggerParams
|
||||
);
|
||||
return rpResponse && rpResponse.properties?.resource;
|
||||
}
|
||||
@@ -58,7 +58,7 @@ export async function createTrigger(
|
||||
const response = await client()
|
||||
.database(databaseId)
|
||||
.container(collectionId)
|
||||
.scripts.triggers.create(trigger as unknown as TriggerDefinition); // TODO: TypeScript does not like the SQL SDK trigger type
|
||||
.scripts.triggers.create((trigger as unknown) as TriggerDefinition); // TODO: TypeScript does not like the SQL SDK trigger type
|
||||
return response.resource;
|
||||
} catch (error) {
|
||||
handleError(error, "CreateTrigger", `Error while creating trigger ${trigger.id}`);
|
||||
|
||||
@@ -16,7 +16,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
export async function createUserDefinedFunction(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
userDefinedFunction: UserDefinedFunctionDefinition,
|
||||
userDefinedFunction: UserDefinedFunctionDefinition
|
||||
): Promise<UserDefinedFunctionDefinition & Resource> {
|
||||
const clearMessage = logConsoleProgress(`Creating user defined function ${userDefinedFunction.id}`);
|
||||
try {
|
||||
@@ -32,11 +32,11 @@ export async function createUserDefinedFunction(
|
||||
userContext.databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
userDefinedFunction.id,
|
||||
userDefinedFunction.id
|
||||
);
|
||||
if (getResponse?.properties?.resource) {
|
||||
throw new Error(
|
||||
`Create user defined function failed: user defined function with id ${userDefinedFunction.id} already exists`,
|
||||
`Create user defined function failed: user defined function with id ${userDefinedFunction.id} already exists`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -58,7 +58,7 @@ export async function createUserDefinedFunction(
|
||||
databaseId,
|
||||
collectionId,
|
||||
userDefinedFunction.id,
|
||||
createUDFParams,
|
||||
createUDFParams
|
||||
);
|
||||
return rpResponse && (rpResponse.properties?.resource as UserDefinedFunctionDefinition & Resource);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ export async function createUserDefinedFunction(
|
||||
handleError(
|
||||
error,
|
||||
"CreateUserupdateUserDefinedFunction",
|
||||
`Error while creating user defined function ${userDefinedFunction.id}`,
|
||||
`Error while creating user defined function ${userDefinedFunction.id}`
|
||||
);
|
||||
throw error;
|
||||
} finally {
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
import { ApiType, userContext } from "UserContext";
|
||||
import * as NotificationConsoleUtils from "Utils/NotificationConsoleUtils";
|
||||
import {
|
||||
cancel,
|
||||
create,
|
||||
get,
|
||||
listByDatabaseAccount,
|
||||
} from "Utils/arm/generatedClients/dataTransferService/dataTransferJobs";
|
||||
import {
|
||||
CosmosCassandraDataTransferDataSourceSink,
|
||||
CosmosMongoDataTransferDataSourceSink,
|
||||
CosmosSqlDataTransferDataSourceSink,
|
||||
CreateJobRequest,
|
||||
DataTransferJobFeedResults,
|
||||
DataTransferJobGetResults,
|
||||
} from "Utils/arm/generatedClients/dataTransferService/types";
|
||||
import { addToPolling, removeFromPolling, updateDataTransferJob, useDataTransferJobs } from "hooks/useDataTransferJobs";
|
||||
import promiseRetry, { AbortError, FailedAttemptError } from "p-retry";
|
||||
|
||||
export interface DataTransferParams {
|
||||
jobName: string;
|
||||
apiType: ApiType;
|
||||
subscriptionId: string;
|
||||
resourceGroupName: string;
|
||||
accountName: string;
|
||||
sourceDatabaseName: string;
|
||||
sourceCollectionName: string;
|
||||
targetDatabaseName: string;
|
||||
targetCollectionName: string;
|
||||
}
|
||||
|
||||
export const getDataTransferJobs = async (
|
||||
subscriptionId: string,
|
||||
resourceGroup: string,
|
||||
accountName: string,
|
||||
): Promise<DataTransferJobGetResults[]> => {
|
||||
let dataTransferJobs: DataTransferJobGetResults[] = [];
|
||||
let dataTransferFeeds: DataTransferJobFeedResults = await listByDatabaseAccount(
|
||||
subscriptionId,
|
||||
resourceGroup,
|
||||
accountName,
|
||||
);
|
||||
dataTransferJobs = [...dataTransferJobs, ...(dataTransferFeeds?.value || [])];
|
||||
while (dataTransferFeeds?.nextLink) {
|
||||
const nextResponse = await window.fetch(dataTransferFeeds.nextLink, {
|
||||
headers: {
|
||||
Authorization: userContext.authorizationToken,
|
||||
},
|
||||
});
|
||||
if (nextResponse.ok) {
|
||||
dataTransferFeeds = await nextResponse.json();
|
||||
dataTransferJobs = [...dataTransferJobs, ...(dataTransferFeeds?.value || [])];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dataTransferJobs;
|
||||
};
|
||||
|
||||
export const initiateDataTransfer = async (params: DataTransferParams): Promise<DataTransferJobGetResults> => {
|
||||
const {
|
||||
jobName,
|
||||
apiType,
|
||||
subscriptionId,
|
||||
resourceGroupName,
|
||||
accountName,
|
||||
sourceDatabaseName,
|
||||
sourceCollectionName,
|
||||
targetDatabaseName,
|
||||
targetCollectionName,
|
||||
} = params;
|
||||
const sourcePayload = createPayload(apiType, sourceDatabaseName, sourceCollectionName);
|
||||
const targetPayload = createPayload(apiType, targetDatabaseName, targetCollectionName);
|
||||
const body: CreateJobRequest = {
|
||||
properties: {
|
||||
source: sourcePayload,
|
||||
destination: targetPayload,
|
||||
},
|
||||
};
|
||||
return create(subscriptionId, resourceGroupName, accountName, jobName, body);
|
||||
};
|
||||
|
||||
export const pollDataTransferJob = async (
|
||||
jobName: string,
|
||||
subscriptionId: string,
|
||||
resourceGroupName: string,
|
||||
accountName: string,
|
||||
): Promise<unknown> => {
|
||||
const currentPollingJobs = useDataTransferJobs.getState().pollingDataTransferJobs;
|
||||
if (currentPollingJobs.has(jobName)) {
|
||||
return;
|
||||
}
|
||||
let clearMessage = NotificationConsoleUtils.logConsoleProgress(`Data transfer job ${jobName} in progress`);
|
||||
return await promiseRetry(
|
||||
() => pollDataTransferJobOperation(jobName, subscriptionId, resourceGroupName, accountName, clearMessage),
|
||||
{
|
||||
retries: 500,
|
||||
maxTimeout: 5000,
|
||||
onFailedAttempt: (error: FailedAttemptError) => {
|
||||
clearMessage();
|
||||
clearMessage = NotificationConsoleUtils.logConsoleProgress(error.message);
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const pollDataTransferJobOperation = async (
|
||||
jobName: string,
|
||||
subscriptionId: string,
|
||||
resourceGroupName: string,
|
||||
accountName: string,
|
||||
clearMessage?: () => void,
|
||||
): Promise<DataTransferJobGetResults> => {
|
||||
if (!userContext.authorizationToken) {
|
||||
throw new Error("No authority token provided");
|
||||
}
|
||||
|
||||
addToPolling(jobName);
|
||||
|
||||
const body: DataTransferJobGetResults = await get(subscriptionId, resourceGroupName, accountName, jobName);
|
||||
const status = body?.properties?.status;
|
||||
|
||||
updateDataTransferJob(body);
|
||||
|
||||
if (status === "Cancelled") {
|
||||
removeFromPolling(jobName);
|
||||
clearMessage && clearMessage();
|
||||
const cancelMessage = `Data transfer job ${jobName} cancelled`;
|
||||
NotificationConsoleUtils.logConsoleError(cancelMessage);
|
||||
throw new AbortError(cancelMessage);
|
||||
}
|
||||
if (status === "Failed" || status === "Faulted") {
|
||||
removeFromPolling(jobName);
|
||||
const errorMessage = body?.properties?.error
|
||||
? JSON.stringify(body?.properties?.error)
|
||||
: "Operation could not be completed";
|
||||
const error = new Error(errorMessage);
|
||||
clearMessage && clearMessage();
|
||||
NotificationConsoleUtils.logConsoleError(`Data transfer job ${jobName} failed: ${errorMessage}`);
|
||||
throw new AbortError(error);
|
||||
}
|
||||
if (status === "Completed") {
|
||||
removeFromPolling(jobName);
|
||||
clearMessage && clearMessage();
|
||||
NotificationConsoleUtils.logConsoleInfo(`Data transfer job ${jobName} completed`);
|
||||
return body;
|
||||
}
|
||||
const processedCount = body.properties.processedCount;
|
||||
const totalCount = body.properties.totalCount;
|
||||
const retryMessage = `Data transfer job ${jobName} in progress, total count: ${totalCount}, processed count: ${processedCount}`;
|
||||
throw new Error(retryMessage);
|
||||
};
|
||||
|
||||
export const cancelDataTransferJob = async (
|
||||
subscriptionId: string,
|
||||
resourceGroupName: string,
|
||||
accountName: string,
|
||||
jobName: string,
|
||||
): Promise<void> => {
|
||||
const cancelResult: DataTransferJobGetResults = await cancel(subscriptionId, resourceGroupName, accountName, jobName);
|
||||
updateDataTransferJob(cancelResult);
|
||||
removeFromPolling(cancelResult?.properties?.jobName);
|
||||
};
|
||||
|
||||
const createPayload = (
|
||||
apiType: ApiType,
|
||||
databaseName: string,
|
||||
containerName: string,
|
||||
):
|
||||
| CosmosSqlDataTransferDataSourceSink
|
||||
| CosmosMongoDataTransferDataSourceSink
|
||||
| CosmosCassandraDataTransferDataSourceSink => {
|
||||
switch (apiType) {
|
||||
case "SQL":
|
||||
return {
|
||||
component: "CosmosDBSql",
|
||||
databaseName: databaseName,
|
||||
containerName: containerName,
|
||||
} as CosmosSqlDataTransferDataSourceSink;
|
||||
case "Mongo":
|
||||
return {
|
||||
component: "CosmosDBMongo",
|
||||
databaseName: databaseName,
|
||||
collectionName: containerName,
|
||||
} as CosmosMongoDataTransferDataSourceSink;
|
||||
case "Cassandra":
|
||||
return {
|
||||
component: "CosmosDBCassandra",
|
||||
keyspaceName: databaseName,
|
||||
tableName: containerName,
|
||||
};
|
||||
default:
|
||||
throw new Error(`Unsupported API type for data transfer: ${apiType}`);
|
||||
}
|
||||
};
|
||||
@@ -8,7 +8,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
export async function deleteStoredProcedure(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
storedProcedureId: string,
|
||||
storedProcedureId: string
|
||||
): Promise<void> {
|
||||
const clearMessage = logConsoleProgress(`Deleting stored procedure ${storedProcedureId}`);
|
||||
try {
|
||||
@@ -23,7 +23,7 @@ export async function deleteStoredProcedure(
|
||||
userContext.databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
storedProcedureId,
|
||||
storedProcedureId
|
||||
);
|
||||
} else {
|
||||
await client().database(databaseId).container(collectionId).scripts.storedProcedure(storedProcedureId).delete();
|
||||
|
||||
@@ -19,7 +19,7 @@ export async function deleteTrigger(databaseId: string, collectionId: string, tr
|
||||
userContext.databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
triggerId,
|
||||
triggerId
|
||||
);
|
||||
} else {
|
||||
await client().database(databaseId).container(collectionId).scripts.trigger(triggerId).delete();
|
||||
|
||||
@@ -19,7 +19,7 @@ export async function deleteUserDefinedFunction(databaseId: string, collectionId
|
||||
userContext.databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
id,
|
||||
id
|
||||
);
|
||||
} else {
|
||||
await client().database(databaseId).container(collectionId).scripts.userDefinedFunction(id).delete();
|
||||
|
||||
@@ -14,7 +14,7 @@ export const executeStoredProcedure = async (
|
||||
collection: Collection,
|
||||
storedProcedure: StoredProcedure,
|
||||
partitionKeyValue: string,
|
||||
params: string[],
|
||||
params: string[]
|
||||
): Promise<ExecuteSprocResult> => {
|
||||
const clearMessage = logConsoleProgress(`Executing stored procedure ${storedProcedure.id()}`);
|
||||
const timeout = setTimeout(() => {
|
||||
@@ -29,7 +29,7 @@ export const executeStoredProcedure = async (
|
||||
.execute(partitionKeyValue, params, { enableScriptLogging: true });
|
||||
clearTimeout(timeout);
|
||||
logConsoleInfo(
|
||||
`Finished executing stored procedure ${storedProcedure.id()} for container ${storedProcedure.collection.id()}`,
|
||||
`Finished executing stored procedure ${storedProcedure.id()} for container ${storedProcedure.collection.id()}`
|
||||
);
|
||||
return {
|
||||
result: response.resource,
|
||||
@@ -39,7 +39,7 @@ export const executeStoredProcedure = async (
|
||||
handleError(
|
||||
error,
|
||||
"ExecuteStoredProcedure",
|
||||
`Failed to execute stored procedure ${storedProcedure.id()} for container ${storedProcedure.collection.id()}`,
|
||||
`Failed to execute stored procedure ${storedProcedure.id()} for container ${storedProcedure.collection.id()}`
|
||||
);
|
||||
throw error;
|
||||
} finally {
|
||||
|
||||
@@ -15,7 +15,7 @@ export async function getIndexTransformationProgress(databaseId: string, collect
|
||||
const response = await client().database(databaseId).container(collectionId).read({ populateQuotaInfo: true });
|
||||
|
||||
indexTransformationPercentage = parseInt(
|
||||
response.headers[Constants.HttpHeaders.collectionIndexTransformationProgress] as string,
|
||||
response.headers[Constants.HttpHeaders.collectionIndexTransformationProgress] as string
|
||||
);
|
||||
} catch (error) {
|
||||
handleError(error, "ReadMongoDBCollection", `Error while reading container ${collectionId}`);
|
||||
|
||||
@@ -5,7 +5,7 @@ export const queryConflicts = (
|
||||
databaseId: string,
|
||||
containerId: string,
|
||||
query: string,
|
||||
options: FeedOptions,
|
||||
options: FeedOptions
|
||||
): QueryIterator<ConflictDefinition & Resource> => {
|
||||
return client().database(databaseId).container(containerId).conflicts.query(query, options);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { LocalStorageUtility, StorageKey } from "../../Shared/StorageUtility";
|
||||
import { getCommonQueryOptions } from "./queryDocuments";
|
||||
import { LocalStorageUtility, StorageKey } from "../../Shared/StorageUtility";
|
||||
|
||||
describe("getCommonQueryOptions", () => {
|
||||
it("builds the correct default options objects", () => {
|
||||
|
||||
@@ -7,7 +7,7 @@ export const queryDocuments = (
|
||||
databaseId: string,
|
||||
containerId: string,
|
||||
query: string,
|
||||
options: FeedOptions,
|
||||
options: FeedOptions
|
||||
): QueryIterator<ItemDefinition & Resource> => {
|
||||
options = getCommonQueryOptions(options);
|
||||
return client().database(databaseId).container(containerId).items.query(query, options);
|
||||
@@ -26,5 +26,6 @@ export const getCommonQueryOptions = (options: FeedOptions): FeedOptions => {
|
||||
(storedItemPerPageSetting !== undefined && storedItemPerPageSetting) ||
|
||||
Queries.itemsPerPage;
|
||||
options.maxDegreeOfParallelism = LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism);
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { QueryOperationOptions } from "@azure/cosmos";
|
||||
import { QueryResults } from "../../Contracts/ViewModels";
|
||||
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { getEntityName } from "../DocumentUtility";
|
||||
@@ -8,14 +7,13 @@ import { MinimalQueryIterator, nextPage } from "../IteratorUtilities";
|
||||
export const queryDocumentsPage = async (
|
||||
resourceName: string,
|
||||
documentsIterator: MinimalQueryIterator,
|
||||
firstItemIndex: number,
|
||||
queryOperationOptions?: QueryOperationOptions,
|
||||
firstItemIndex: number
|
||||
): Promise<QueryResults> => {
|
||||
const entityName = getEntityName();
|
||||
const clearMessage = logConsoleProgress(`Querying ${entityName} for container ${resourceName}`);
|
||||
|
||||
try {
|
||||
const result: QueryResults = await nextPage(documentsIterator, firstItemIndex, queryOperationOptions);
|
||||
const result: QueryResults = await nextPage(documentsIterator, firstItemIndex);
|
||||
const itemCount = (result.documents && result.documents.length) || 0;
|
||||
logConsoleInfo(`Successfully fetched ${itemCount} ${entityName} for container ${resourceName}`);
|
||||
return result;
|
||||
|
||||
@@ -28,7 +28,7 @@ export async function readSampleCollection(): Promise<DataModels.Collection> {
|
||||
export async function readCollectionInternal(
|
||||
cosmosClient: CosmosClient,
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
collectionId: string
|
||||
): Promise<DataModels.Collection> {
|
||||
let collection: DataModels.Collection;
|
||||
const clearMessage = logConsoleProgress(`Querying container ${collectionId}`);
|
||||
|
||||
@@ -44,7 +44,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
|
||||
resourceGroup,
|
||||
accountName,
|
||||
databaseId,
|
||||
collectionId,
|
||||
collectionId
|
||||
);
|
||||
break;
|
||||
case "Mongo":
|
||||
@@ -53,7 +53,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
|
||||
resourceGroup,
|
||||
accountName,
|
||||
databaseId,
|
||||
collectionId,
|
||||
collectionId
|
||||
);
|
||||
break;
|
||||
case "Cassandra":
|
||||
@@ -62,7 +62,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
|
||||
resourceGroup,
|
||||
accountName,
|
||||
databaseId,
|
||||
collectionId,
|
||||
collectionId
|
||||
);
|
||||
break;
|
||||
case "Gremlin":
|
||||
@@ -71,7 +71,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
|
||||
resourceGroup,
|
||||
accountName,
|
||||
databaseId,
|
||||
collectionId,
|
||||
collectionId
|
||||
);
|
||||
break;
|
||||
case "Tables":
|
||||
|
||||
@@ -1,57 +1,18 @@
|
||||
import { ContainerResponse } from "@azure/cosmos";
|
||||
import { Queries } from "Common/Constants";
|
||||
import { Platform, configContext } from "ConfigContext";
|
||||
import { AuthType } from "../../AuthType";
|
||||
import * as DataModels from "../../Contracts/DataModels";
|
||||
import { userContext } from "../../UserContext";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { listCassandraTables } from "../../Utils/arm/generatedClients/cosmos/cassandraResources";
|
||||
import { listGremlinGraphs } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
|
||||
import { listMongoDBCollections } from "../../Utils/arm/generatedClients/cosmos/mongoDBResources";
|
||||
import { listSqlContainers } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
|
||||
import { listTables } from "../../Utils/arm/generatedClients/cosmos/tableResources";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { client } from "../CosmosClient";
|
||||
import { handleError } from "../ErrorHandlingUtils";
|
||||
|
||||
export async function readCollections(databaseId: string): Promise<DataModels.Collection[]> {
|
||||
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
|
||||
|
||||
if (
|
||||
configContext.platform === Platform.Fabric &&
|
||||
userContext.fabricContext &&
|
||||
userContext.fabricContext.databaseConnectionInfo.databaseId === databaseId
|
||||
) {
|
||||
const collections: DataModels.Collection[] = [];
|
||||
const promises: Promise<ContainerResponse>[] = [];
|
||||
|
||||
for (const collectionResourceId in userContext.fabricContext.databaseConnectionInfo.resourceTokens) {
|
||||
// Dictionary key looks like this: dbs/SampleDB/colls/Container
|
||||
const resourceIdObj = collectionResourceId.split("/");
|
||||
const tokenDatabaseId = resourceIdObj[1];
|
||||
const tokenCollectionId = resourceIdObj[3];
|
||||
|
||||
if (tokenDatabaseId === databaseId) {
|
||||
promises.push(client().database(databaseId).container(tokenCollectionId).read());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const responses = await Promise.all(promises);
|
||||
responses.forEach((response) => {
|
||||
collections.push(response.resource as DataModels.Collection);
|
||||
});
|
||||
|
||||
// Sort collections by id before returning
|
||||
collections.sort((a, b) => a.id.localeCompare(b.id));
|
||||
return collections;
|
||||
} catch (error) {
|
||||
handleError(error, "ReadCollections", `Error while querying containers for database ${databaseId}`);
|
||||
throw error;
|
||||
} finally {
|
||||
clearMessage();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (
|
||||
userContext.authType === AuthType.AAD &&
|
||||
@@ -73,7 +34,7 @@ export async function readCollections(databaseId: string): Promise<DataModels.Co
|
||||
|
||||
export async function readCollectionsWithPagination(
|
||||
databaseId: string,
|
||||
continuationToken?: string,
|
||||
continuationToken?: string
|
||||
): Promise<DataModels.CollectionsWithPagination> {
|
||||
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
|
||||
try {
|
||||
@@ -84,7 +45,7 @@ export async function readCollectionsWithPagination(
|
||||
{
|
||||
continuationToken,
|
||||
maxItemCount: Queries.containersPerPage,
|
||||
},
|
||||
}
|
||||
)
|
||||
.fetchNext();
|
||||
const collectionsWithPagination: DataModels.CollectionsWithPagination = {
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
import { Platform, configContext } from "ConfigContext";
|
||||
import { AuthType } from "../../AuthType";
|
||||
import { Offer, ReadDatabaseOfferParams } from "../../Contracts/DataModels";
|
||||
import { userContext } from "../../UserContext";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { getCassandraKeyspaceThroughput } from "../../Utils/arm/generatedClients/cosmos/cassandraResources";
|
||||
import { getGremlinDatabaseThroughput } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
|
||||
import { getMongoDBDatabaseThroughput } from "../../Utils/arm/generatedClients/cosmos/mongoDBResources";
|
||||
import { getSqlDatabaseThroughput } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { handleError } from "../ErrorHandlingUtils";
|
||||
import { readOfferWithSDK } from "./readOfferWithSDK";
|
||||
|
||||
export const readDatabaseOffer = async (params: ReadDatabaseOfferParams): Promise<Offer> => {
|
||||
if (configContext.platform === Platform.Fabric) {
|
||||
// TODO This works, but is very slow, because it requests the token, so we skip for now
|
||||
console.error("Skiping readDatabaseOffer for Fabric");
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const clearMessage = logConsoleProgress(`Querying offer for database ${params.databaseId}`);
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,53 +1,17 @@
|
||||
import { Platform, configContext } from "ConfigContext";
|
||||
import { AuthType } from "../../AuthType";
|
||||
import * as DataModels from "../../Contracts/DataModels";
|
||||
import { userContext } from "../../UserContext";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/cosmos/cassandraResources";
|
||||
import { listGremlinDatabases } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
|
||||
import { listMongoDBDatabases } from "../../Utils/arm/generatedClients/cosmos/mongoDBResources";
|
||||
import { listSqlDatabases } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import { client } from "../CosmosClient";
|
||||
import { handleError } from "../ErrorHandlingUtils";
|
||||
|
||||
export async function readDatabases(): Promise<DataModels.Database[]> {
|
||||
let databases: DataModels.Database[];
|
||||
const clearMessage = logConsoleProgress(`Querying databases`);
|
||||
|
||||
if (configContext.platform === Platform.Fabric && userContext.fabricContext?.databaseConnectionInfo.resourceTokens) {
|
||||
const tokensData = userContext.fabricContext.databaseConnectionInfo;
|
||||
|
||||
const databaseIdsSet = new Set<string>(); // databaseId
|
||||
|
||||
for (const collectionResourceId in tokensData.resourceTokens) {
|
||||
// Dictionary key looks like this: dbs/SampleDB/colls/Container
|
||||
const resourceIdObj = collectionResourceId.split("/");
|
||||
|
||||
if (resourceIdObj.length !== 4) {
|
||||
handleError(`Resource key not recognized: ${resourceIdObj}`, "ReadDatabases", `Error while querying databases`);
|
||||
clearMessage();
|
||||
return [];
|
||||
}
|
||||
|
||||
const databaseId = resourceIdObj[1];
|
||||
|
||||
databaseIdsSet.add(databaseId);
|
||||
}
|
||||
|
||||
const databases: DataModels.Database[] = Array.from(databaseIdsSet.values())
|
||||
.sort((a, b) => a.localeCompare(b))
|
||||
.map((databaseId) => ({
|
||||
_rid: "",
|
||||
_self: "",
|
||||
_etag: "",
|
||||
_ts: 0,
|
||||
id: databaseId,
|
||||
collections: [],
|
||||
}));
|
||||
clearMessage();
|
||||
return databases;
|
||||
}
|
||||
|
||||
try {
|
||||
if (
|
||||
userContext.authType === AuthType.AAD &&
|
||||
|
||||
@@ -7,7 +7,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
|
||||
export async function readMongoDBCollectionThroughRP(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
collectionId: string
|
||||
): Promise<MongoDBCollectionResource> {
|
||||
if (userContext.authType !== AuthType.AAD) {
|
||||
return undefined;
|
||||
|
||||
@@ -9,7 +9,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
|
||||
export async function readStoredProcedures(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
collectionId: string
|
||||
): Promise<(StoredProcedureDefinition & Resource)[]> {
|
||||
const clearMessage = logConsoleProgress(`Querying stored procedures for container ${collectionId}`);
|
||||
try {
|
||||
@@ -23,7 +23,7 @@ export async function readStoredProcedures(
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
collectionId
|
||||
);
|
||||
const listResult = rpResponse as SqlStoredProcedureListResult;
|
||||
if (listResult) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
|
||||
export async function readTriggers(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
collectionId: string
|
||||
): Promise<SqlTriggerResource[] | TriggerDefinition[]> {
|
||||
const clearMessage = logConsoleProgress(`Querying triggers for container ${collectionId}`);
|
||||
try {
|
||||
@@ -23,7 +23,7 @@ export async function readTriggers(
|
||||
userContext.resourceGroup,
|
||||
userContext.databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
collectionId
|
||||
);
|
||||
return rpResponse?.value?.map((trigger) => trigger.properties?.resource);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
|
||||
export async function readUserDefinedFunctions(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
collectionId: string
|
||||
): Promise<(UserDefinedFunctionDefinition & Resource)[]> {
|
||||
const clearMessage = logConsoleProgress(`Querying user defined functions for container ${collectionId}`);
|
||||
const { authType, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
|
||||
@@ -19,7 +19,7 @@ export async function readUserDefinedFunctions(
|
||||
resourceGroup,
|
||||
databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
collectionId
|
||||
);
|
||||
return rpResponse?.value?.map((udf) => udf.properties?.resource as UserDefinedFunctionDefinition & Resource);
|
||||
}
|
||||
@@ -34,7 +34,7 @@ export async function readUserDefinedFunctions(
|
||||
handleError(
|
||||
error,
|
||||
"ReadUserDefinedFunctions",
|
||||
`Failed to query user defined functions for container ${collectionId}`,
|
||||
`Failed to query user defined functions for container ${collectionId}`
|
||||
);
|
||||
throw error;
|
||||
} finally {
|
||||
|
||||
@@ -27,7 +27,7 @@ export async function updateCollection(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
newCollection: Partial<Collection>,
|
||||
options: RequestOptions = {},
|
||||
options: RequestOptions = {}
|
||||
): Promise<Collection> {
|
||||
let collection: Collection;
|
||||
const clearMessage = logConsoleProgress(`Updating container ${collectionId}`);
|
||||
@@ -61,7 +61,7 @@ export async function updateCollection(
|
||||
async function updateCollectionWithARM(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
newCollection: Partial<Collection>,
|
||||
newCollection: Partial<Collection>
|
||||
): Promise<Collection> {
|
||||
const { subscriptionId, resourceGroup, apiType, databaseAccount } = userContext;
|
||||
const accountName = databaseAccount.name;
|
||||
@@ -82,7 +82,7 @@ async function updateCollectionWithARM(
|
||||
subscriptionId,
|
||||
resourceGroup,
|
||||
accountName,
|
||||
newCollection,
|
||||
newCollection
|
||||
);
|
||||
default:
|
||||
throw new Error(`Unsupported default experience type: ${apiType}`);
|
||||
@@ -95,7 +95,7 @@ async function updateSqlContainer(
|
||||
subscriptionId: string,
|
||||
resourceGroup: string,
|
||||
accountName: string,
|
||||
newCollection: Partial<Collection>,
|
||||
newCollection: Partial<Collection>
|
||||
): Promise<Collection> {
|
||||
const getResponse = await getSqlContainer(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||
@@ -106,7 +106,7 @@ async function updateSqlContainer(
|
||||
accountName,
|
||||
databaseId,
|
||||
collectionId,
|
||||
getResponse as SqlContainerCreateUpdateParameters,
|
||||
getResponse as SqlContainerCreateUpdateParameters
|
||||
);
|
||||
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||
}
|
||||
@@ -120,7 +120,7 @@ export async function updateMongoDBCollection(
|
||||
subscriptionId: string,
|
||||
resourceGroup: string,
|
||||
accountName: string,
|
||||
newCollection: Partial<Collection>,
|
||||
newCollection: Partial<Collection>
|
||||
): Promise<Collection> {
|
||||
const getResponse = await getMongoDBCollection(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||
@@ -131,13 +131,13 @@ export async function updateMongoDBCollection(
|
||||
accountName,
|
||||
databaseId,
|
||||
collectionId,
|
||||
getResponse as MongoDBCollectionCreateUpdateParameters,
|
||||
getResponse as MongoDBCollectionCreateUpdateParameters
|
||||
);
|
||||
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`MongoDB collection to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`,
|
||||
`MongoDB collection to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ async function updateCassandraTable(
|
||||
subscriptionId: string,
|
||||
resourceGroup: string,
|
||||
accountName: string,
|
||||
newCollection: Partial<Collection>,
|
||||
newCollection: Partial<Collection>
|
||||
): Promise<Collection> {
|
||||
const getResponse = await getCassandraTable(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||
@@ -158,13 +158,13 @@ async function updateCassandraTable(
|
||||
accountName,
|
||||
databaseId,
|
||||
collectionId,
|
||||
getResponse as SqlContainerCreateUpdateParameters,
|
||||
getResponse as SqlContainerCreateUpdateParameters
|
||||
);
|
||||
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Cassandra table to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`,
|
||||
`Cassandra table to update does not exist. Database id: ${databaseId} Collection id: ${collectionId}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ async function updateGremlinGraph(
|
||||
subscriptionId: string,
|
||||
resourceGroup: string,
|
||||
accountName: string,
|
||||
newCollection: Partial<Collection>,
|
||||
newCollection: Partial<Collection>
|
||||
): Promise<Collection> {
|
||||
const getResponse = await getGremlinGraph(subscriptionId, resourceGroup, accountName, databaseId, collectionId);
|
||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||
@@ -185,7 +185,7 @@ async function updateGremlinGraph(
|
||||
accountName,
|
||||
databaseId,
|
||||
collectionId,
|
||||
getResponse as SqlContainerCreateUpdateParameters,
|
||||
getResponse as SqlContainerCreateUpdateParameters
|
||||
);
|
||||
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||
}
|
||||
@@ -198,7 +198,7 @@ async function updateTable(
|
||||
subscriptionId: string,
|
||||
resourceGroup: string,
|
||||
accountName: string,
|
||||
newCollection: Partial<Collection>,
|
||||
newCollection: Partial<Collection>
|
||||
): Promise<Collection> {
|
||||
const getResponse = await getTable(subscriptionId, resourceGroup, accountName, collectionId);
|
||||
if (getResponse && getResponse.properties && getResponse.properties.resource) {
|
||||
@@ -208,7 +208,7 @@ async function updateTable(
|
||||
resourceGroup,
|
||||
accountName,
|
||||
collectionId,
|
||||
getResponse as SqlContainerCreateUpdateParameters,
|
||||
getResponse as SqlContainerCreateUpdateParameters
|
||||
);
|
||||
return updateResponse && (updateResponse.properties.resource as Collection);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { getPartitionKeyValue } from "./getPartitionKeyValue";
|
||||
export const updateDocument = async (
|
||||
collection: CollectionBase,
|
||||
documentId: DocumentId,
|
||||
newDocument: Item,
|
||||
newDocument: Item
|
||||
): Promise<Item> => {
|
||||
const entityName = getEntityName();
|
||||
const clearMessage = logConsoleProgress(`Updating ${entityName} ${documentId.id()}`);
|
||||
|
||||
@@ -152,7 +152,7 @@ const updateSqlContainerOffer = async (params: UpdateOfferParams): Promise<void>
|
||||
resourceGroup,
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
params.collectionId
|
||||
);
|
||||
} else if (params.migrateToManual) {
|
||||
await migrateSqlContainerToManualThroughput(
|
||||
@@ -160,7 +160,7 @@ const updateSqlContainerOffer = async (params: UpdateOfferParams): Promise<void>
|
||||
resourceGroup,
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
params.collectionId
|
||||
);
|
||||
} else {
|
||||
const body: ThroughputSettingsUpdateParameters = createUpdateOfferBody(params);
|
||||
@@ -170,7 +170,7 @@ const updateSqlContainerOffer = async (params: UpdateOfferParams): Promise<void>
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
body,
|
||||
body
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -185,7 +185,7 @@ const updateMongoCollectionOffer = async (params: UpdateOfferParams): Promise<vo
|
||||
resourceGroup,
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
params.collectionId
|
||||
);
|
||||
} else if (params.migrateToManual) {
|
||||
await migrateMongoDBCollectionToManualThroughput(
|
||||
@@ -193,7 +193,7 @@ const updateMongoCollectionOffer = async (params: UpdateOfferParams): Promise<vo
|
||||
resourceGroup,
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
params.collectionId
|
||||
);
|
||||
} else {
|
||||
const body: ThroughputSettingsUpdateParameters = createUpdateOfferBody(params);
|
||||
@@ -203,7 +203,7 @@ const updateMongoCollectionOffer = async (params: UpdateOfferParams): Promise<vo
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
body,
|
||||
body
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -218,7 +218,7 @@ const updateCassandraTableOffer = async (params: UpdateOfferParams): Promise<voi
|
||||
resourceGroup,
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
params.collectionId
|
||||
);
|
||||
} else if (params.migrateToManual) {
|
||||
await migrateCassandraTableToManualThroughput(
|
||||
@@ -226,7 +226,7 @@ const updateCassandraTableOffer = async (params: UpdateOfferParams): Promise<voi
|
||||
resourceGroup,
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
params.collectionId
|
||||
);
|
||||
} else {
|
||||
const body: ThroughputSettingsUpdateParameters = createUpdateOfferBody(params);
|
||||
@@ -236,7 +236,7 @@ const updateCassandraTableOffer = async (params: UpdateOfferParams): Promise<voi
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
body,
|
||||
body
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -251,7 +251,7 @@ const updateGremlinGraphOffer = async (params: UpdateOfferParams): Promise<void>
|
||||
resourceGroup,
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
params.collectionId
|
||||
);
|
||||
} else if (params.migrateToManual) {
|
||||
await migrateGremlinGraphToManualThroughput(
|
||||
@@ -259,7 +259,7 @@ const updateGremlinGraphOffer = async (params: UpdateOfferParams): Promise<void>
|
||||
resourceGroup,
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
params.collectionId
|
||||
);
|
||||
} else {
|
||||
const body: ThroughputSettingsUpdateParameters = createUpdateOfferBody(params);
|
||||
@@ -269,7 +269,7 @@ const updateGremlinGraphOffer = async (params: UpdateOfferParams): Promise<void>
|
||||
accountName,
|
||||
params.databaseId,
|
||||
params.collectionId,
|
||||
body,
|
||||
body
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -404,7 +404,7 @@ const updateOfferWithSDK = async (params: UpdateOfferParams): Promise<Offer> =>
|
||||
const sdkResponse = await client()
|
||||
.offer(params.currentOffer.id)
|
||||
// TODO Remove casting when SDK types are fixed (https://github.com/Azure/azure-sdk-for-js/issues/10660)
|
||||
.replace(newOffer as unknown as OfferDefinition, options);
|
||||
.replace((newOffer as unknown) as OfferDefinition, options);
|
||||
|
||||
return parseSDKOfferResponse(sdkResponse);
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
export async function updateStoredProcedure(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
storedProcedure: StoredProcedureDefinition,
|
||||
storedProcedure: StoredProcedureDefinition
|
||||
): Promise<StoredProcedureDefinition & Resource> {
|
||||
const clearMessage = logConsoleProgress(`Updating stored procedure ${storedProcedure.id}`);
|
||||
try {
|
||||
@@ -29,7 +29,7 @@ export async function updateStoredProcedure(
|
||||
databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
storedProcedure.id,
|
||||
storedProcedure.id
|
||||
);
|
||||
|
||||
if (getResponse?.properties?.resource) {
|
||||
@@ -46,7 +46,7 @@ export async function updateStoredProcedure(
|
||||
databaseId,
|
||||
collectionId,
|
||||
storedProcedure.id,
|
||||
createSprocParams,
|
||||
createSprocParams
|
||||
);
|
||||
return rpResponse && (rpResponse.properties?.resource as StoredProcedureDefinition & Resource);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
export async function updateTrigger(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
trigger: SqlTriggerResource,
|
||||
trigger: SqlTriggerResource
|
||||
): Promise<SqlTriggerResource | TriggerDefinition> {
|
||||
const clearMessage = logConsoleProgress(`Updating trigger ${trigger.id}`);
|
||||
const { authType, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
|
||||
@@ -22,7 +22,7 @@ export async function updateTrigger(
|
||||
databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
trigger.id,
|
||||
trigger.id
|
||||
);
|
||||
|
||||
if (getResponse?.properties?.resource) {
|
||||
@@ -39,7 +39,7 @@ export async function updateTrigger(
|
||||
databaseId,
|
||||
collectionId,
|
||||
trigger.id,
|
||||
createTriggerParams,
|
||||
createTriggerParams
|
||||
);
|
||||
return rpResponse && rpResponse.properties?.resource;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ export async function updateTrigger(
|
||||
.database(databaseId)
|
||||
.container(collectionId)
|
||||
.scripts.trigger(trigger.id)
|
||||
.replace(trigger as unknown as TriggerDefinition); // TODO: TypeScript does not like the SQL SDK trigger type
|
||||
.replace((trigger as unknown) as TriggerDefinition); // TODO: TypeScript does not like the SQL SDK trigger type
|
||||
return response?.resource;
|
||||
} catch (error) {
|
||||
handleError(error, "UpdateTrigger", `Error while updating trigger ${trigger.id}`);
|
||||
|
||||
@@ -16,7 +16,7 @@ import { handleError } from "../ErrorHandlingUtils";
|
||||
export async function updateUserDefinedFunction(
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
userDefinedFunction: UserDefinedFunctionDefinition,
|
||||
userDefinedFunction: UserDefinedFunctionDefinition
|
||||
): Promise<UserDefinedFunctionDefinition & Resource> {
|
||||
const clearMessage = logConsoleProgress(`Updating user defined function ${userDefinedFunction.id}`);
|
||||
const { authType, apiType, subscriptionId, resourceGroup, databaseAccount } = userContext;
|
||||
@@ -28,7 +28,7 @@ export async function updateUserDefinedFunction(
|
||||
databaseAccount.name,
|
||||
databaseId,
|
||||
collectionId,
|
||||
userDefinedFunction.id,
|
||||
userDefinedFunction.id
|
||||
);
|
||||
|
||||
if (getResponse?.properties?.resource) {
|
||||
@@ -45,7 +45,7 @@ export async function updateUserDefinedFunction(
|
||||
databaseId,
|
||||
collectionId,
|
||||
userDefinedFunction.id,
|
||||
createUDFParams,
|
||||
createUDFParams
|
||||
);
|
||||
return rpResponse && (rpResponse.properties?.resource as UserDefinedFunctionDefinition & Resource);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ export async function updateUserDefinedFunction(
|
||||
handleError(
|
||||
error,
|
||||
"UpdateUserupdateUserDefinedFunction",
|
||||
`Error while updating user defined function ${userDefinedFunction.id}`,
|
||||
`Error while updating user defined function ${userDefinedFunction.id}`
|
||||
);
|
||||
throw error;
|
||||
} finally {
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
export function getAuthorizationTokenUsingResourceTokens(
|
||||
resourceTokens: { [resourceId: string]: string },
|
||||
path: string,
|
||||
resourceId: string,
|
||||
): string {
|
||||
// console.log(`getting token for path: "${path}" and resourceId: "${resourceId}"`);
|
||||
|
||||
if (resourceTokens && Object.keys(resourceTokens).length > 0) {
|
||||
// For database account access(through getDatabaseAccount API), path and resourceId are "",
|
||||
// so in this case we return the first token to be used for creating the auth header as the
|
||||
// service will accept any token in this case
|
||||
if (!path && !resourceId) {
|
||||
return resourceTokens[Object.keys(resourceTokens)[0]];
|
||||
}
|
||||
|
||||
// If we have exact resource token for the path use it
|
||||
if (resourceId && resourceTokens[resourceId]) {
|
||||
return resourceTokens[resourceId];
|
||||
}
|
||||
|
||||
// minimum valid path /dbs
|
||||
if (!path || path.length < 4) {
|
||||
console.error(
|
||||
`Unable to get authotization token for Path:"${path}" and resourcerId:"${resourceId}". Invalid path.`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
path = trimSlashFromLeftAndRight(path);
|
||||
const pathSegments = (path && path.split("/")) || [];
|
||||
|
||||
// Item path
|
||||
if (pathSegments.length === 6) {
|
||||
// Look for a container token matching the item path
|
||||
const containerPath = pathSegments.slice(0, 4).map(decodeURIComponent).join("/");
|
||||
if (resourceTokens[containerPath]) {
|
||||
return resourceTokens[containerPath];
|
||||
}
|
||||
}
|
||||
|
||||
// This is legacy behavior that lets someone use a resource token pointing ONLY at an ID
|
||||
// It was used when _rid was exposed by the SDK, but now that we are using user provided ids it is not needed
|
||||
// However removing it now would be a breaking change
|
||||
// if it's an incomplete path like /dbs/db1/colls/, start from the parent resource
|
||||
let index = pathSegments.length % 2 === 0 ? pathSegments.length - 1 : pathSegments.length - 2;
|
||||
for (; index > 0; index -= 2) {
|
||||
const id = decodeURI(pathSegments[index]);
|
||||
if (resourceTokens[id]) {
|
||||
return resourceTokens[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.error(`Unable to get authotization token for Path:"${path}" and resourcerId:"${resourceId}"`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const trimLeftSlashes = new RegExp("^[/]+");
|
||||
const trimRightSlashes = new RegExp("[/]+$");
|
||||
function trimSlashFromLeftAndRight(inputString: string): string {
|
||||
if (typeof inputString !== "string") {
|
||||
throw new Error("invalid input: input is not string");
|
||||
}
|
||||
|
||||
return inputString.replace(trimLeftSlashes, "").replace(trimRightSlashes, "");
|
||||
}
|
||||
@@ -1,31 +1,21 @@
|
||||
import {
|
||||
BackendApi,
|
||||
CassandraProxyEndpoints,
|
||||
JunoEndpoints,
|
||||
MongoProxyEndpoints,
|
||||
PortalBackendEndpoints,
|
||||
} from "Common/Constants";
|
||||
import {
|
||||
allowedAadEndpoints,
|
||||
allowedArcadiaEndpoints,
|
||||
allowedCassandraProxyEndpoints,
|
||||
allowedEmulatorEndpoints,
|
||||
allowedGraphEndpoints,
|
||||
allowedHostedExplorerEndpoints,
|
||||
allowedJunoOrigins,
|
||||
allowedMongoBackendEndpoints,
|
||||
allowedMongoProxyEndpoints,
|
||||
allowedMsalRedirectEndpoints,
|
||||
defaultAllowedArmEndpoints,
|
||||
defaultAllowedBackendEndpoints,
|
||||
validateEndpoint,
|
||||
} from "Utils/EndpointUtils";
|
||||
} from "Utils/EndpointValidation";
|
||||
|
||||
export enum Platform {
|
||||
Portal = "Portal",
|
||||
Hosted = "Hosted",
|
||||
Emulator = "Emulator",
|
||||
Fabric = "Fabric",
|
||||
}
|
||||
|
||||
export interface ConfigContext {
|
||||
@@ -45,15 +35,7 @@ export interface ConfigContext {
|
||||
ARCADIA_ENDPOINT: string;
|
||||
ARCADIA_LIVY_ENDPOINT_DNS_ZONE: string;
|
||||
BACKEND_ENDPOINT?: string;
|
||||
PORTAL_BACKEND_ENDPOINT?: string;
|
||||
NEW_BACKEND_APIS?: BackendApi[];
|
||||
MONGO_BACKEND_ENDPOINT?: string;
|
||||
MONGO_PROXY_ENDPOINT?: string;
|
||||
MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED?: boolean;
|
||||
NEW_MONGO_APIS?: string[];
|
||||
CASSANDRA_PROXY_ENDPOINT?: string;
|
||||
CASSANDRA_PROXY_OUTBOUND_IPS_ALLOWLISTED: boolean;
|
||||
NEW_CASSANDRA_APIS?: string[];
|
||||
PROXY_PATH?: string;
|
||||
JUNO_ENDPOINT: string;
|
||||
GITHUB_CLIENT_ID: string;
|
||||
@@ -78,11 +60,6 @@ let configContext: Readonly<ConfigContext> = {
|
||||
`^https:\\/\\/[\\.\\w]*ext\\.azure\\.(com|cn|us)$`,
|
||||
`^https:\\/\\/[\\.\\w]*\\.ext\\.microsoftazure\\.de$`,
|
||||
`^https:\\/\\/cosmos-db-dataexplorer-germanycentral\\.azurewebsites\\.de$`,
|
||||
`^https:\\/\\/.*\\.fabric\\.microsoft\\.com$`,
|
||||
`^https:\\/\\/.*\\.powerbi\\.com$`,
|
||||
`^https:\\/\\/.*\\.analysis-df\\.net$`,
|
||||
`^https:\\/\\/.*\\.analysis-df\\.windows\\.net$`,
|
||||
`^https:\\/\\/.*\\.azure-test\\.net$`,
|
||||
], // Webpack injects this at build time
|
||||
gitSha: process.env.GIT_SHA,
|
||||
hostedExplorerURL: "https://cosmos.azure.com/",
|
||||
@@ -90,29 +67,14 @@ let configContext: Readonly<ConfigContext> = {
|
||||
ARM_AUTH_AREA: "https://management.azure.com/",
|
||||
ARM_ENDPOINT: "https://management.azure.com/",
|
||||
ARM_API_VERSION: "2016-06-01",
|
||||
GRAPH_ENDPOINT: "https://graph.microsoft.com",
|
||||
GRAPH_ENDPOINT: "https://graph.windows.net",
|
||||
GRAPH_API_VERSION: "1.6",
|
||||
ARCADIA_ENDPOINT: "https://workspaceartifacts.projectarcadia.net",
|
||||
ARCADIA_LIVY_ENDPOINT_DNS_ZONE: "dev.azuresynapse.net",
|
||||
GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/organizations/AzureCosmosDBNotebooks/settings/applications/1189306
|
||||
GITHUB_TEST_ENV_CLIENT_ID: "b63fc8cbf87fd3c6e2eb", // Registered OAuth app: https://github.com/organizations/AzureCosmosDBNotebooks/settings/applications/1777772
|
||||
JUNO_ENDPOINT: JunoEndpoints.Prod,
|
||||
JUNO_ENDPOINT: "https://tools.cosmos.azure.com",
|
||||
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
|
||||
PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Prod,
|
||||
MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Prod,
|
||||
NEW_MONGO_APIS: [
|
||||
"resourcelist",
|
||||
"queryDocuments",
|
||||
"createDocument",
|
||||
"readDocument",
|
||||
"updateDocument",
|
||||
"deleteDocument",
|
||||
"createCollectionWithProxy",
|
||||
],
|
||||
MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED: false,
|
||||
CASSANDRA_PROXY_ENDPOINT: CassandraProxyEndpoints.Prod,
|
||||
NEW_CASSANDRA_APIS: ["postQuery", "createOrDelete", "getKeys", "getSchema"],
|
||||
CASSANDRA_PROXY_OUTBOUND_IPS_ALLOWLISTED: false,
|
||||
isTerminalEnabled: false,
|
||||
isPhoenixEnabled: false,
|
||||
};
|
||||
@@ -152,24 +114,16 @@ export function updateConfigContext(newContext: Partial<ConfigContext>): void {
|
||||
if (
|
||||
!validateEndpoint(
|
||||
newContext.BACKEND_ENDPOINT,
|
||||
configContext.allowedBackendEndpoints || defaultAllowedBackendEndpoints,
|
||||
configContext.allowedBackendEndpoints || defaultAllowedBackendEndpoints
|
||||
)
|
||||
) {
|
||||
delete newContext.BACKEND_ENDPOINT;
|
||||
}
|
||||
|
||||
if (!validateEndpoint(newContext.MONGO_PROXY_ENDPOINT, allowedMongoProxyEndpoints)) {
|
||||
delete newContext.MONGO_PROXY_ENDPOINT;
|
||||
}
|
||||
|
||||
if (!validateEndpoint(newContext.MONGO_BACKEND_ENDPOINT, allowedMongoBackendEndpoints)) {
|
||||
delete newContext.MONGO_BACKEND_ENDPOINT;
|
||||
}
|
||||
|
||||
if (!validateEndpoint(newContext.CASSANDRA_PROXY_ENDPOINT, allowedCassandraProxyEndpoints)) {
|
||||
delete newContext.CASSANDRA_PROXY_ENDPOINT;
|
||||
}
|
||||
|
||||
if (!validateEndpoint(newContext.JUNO_ENDPOINT, allowedJunoOrigins)) {
|
||||
delete newContext.JUNO_ENDPOINT;
|
||||
}
|
||||
@@ -187,7 +141,10 @@ export function updateConfigContext(newContext: Partial<ConfigContext>): void {
|
||||
|
||||
// Injected for local development. These will be removed in the production bundle by webpack
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
const port: string = process.env.PORT || "1234";
|
||||
updateConfigContext({
|
||||
BACKEND_ENDPOINT: "https://localhost:" + port,
|
||||
MONGO_BACKEND_ENDPOINT: "https://localhost:" + port,
|
||||
PROXY_PATH: "/proxy",
|
||||
EMULATOR_ENDPOINT: "https://localhost:8081",
|
||||
});
|
||||
@@ -230,7 +187,6 @@ export async function initializeConfiguration(): Promise<ConfigContext> {
|
||||
console.error(`Invalid platform query parameter: ${platform}`);
|
||||
break;
|
||||
case Platform.Portal:
|
||||
case Platform.Fabric:
|
||||
case Platform.Hosted:
|
||||
case Platform.Emulator:
|
||||
updateConfigContext({ platform });
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
export interface QueryRequestOptions {
|
||||
$skipToken?: string;
|
||||
$top?: number;
|
||||
subscriptions: string[];
|
||||
}
|
||||
|
||||
export interface QueryResponse {
|
||||
$skipToken: string;
|
||||
count: number;
|
||||
data: any;
|
||||
resultTruncated: boolean;
|
||||
totalRecords: number;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { MessageTypes } from "./MessageTypes";
|
||||
|
||||
// This is the current version of these messages
|
||||
export const DATA_EXPLORER_RPC_VERSION = "2";
|
||||
|
||||
// Data Explorer to Fabric
|
||||
|
||||
// TODO Remove when upgrading to Fabric v2
|
||||
export type DataExploreMessageV1 =
|
||||
| "ready"
|
||||
| {
|
||||
type: MessageTypes.GetAuthorizationToken;
|
||||
id: string;
|
||||
params: GetCosmosTokenMessageOptions[];
|
||||
}
|
||||
| {
|
||||
type: MessageTypes.GetAllResourceTokens;
|
||||
id: string;
|
||||
};
|
||||
// -----------------------------
|
||||
|
||||
export type DataExploreMessageV2 =
|
||||
| {
|
||||
type: MessageTypes.Ready;
|
||||
id: string;
|
||||
params: [string]; // version
|
||||
}
|
||||
| {
|
||||
type: MessageTypes.GetAuthorizationToken;
|
||||
id: string;
|
||||
params: GetCosmosTokenMessageOptions[];
|
||||
}
|
||||
| {
|
||||
type: MessageTypes.GetAllResourceTokens;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type GetCosmosTokenMessageOptions = {
|
||||
verb: "connect" | "delete" | "get" | "head" | "options" | "patch" | "post" | "put" | "trace";
|
||||
resourceType: "" | "dbs" | "colls" | "docs" | "sprocs" | "pkranges";
|
||||
resourceId: string;
|
||||
};
|
||||
@@ -1,14 +1,11 @@
|
||||
import { ConnectionStatusType, ContainerStatusType } from "../Common/Constants";
|
||||
|
||||
export interface ArmEntity {
|
||||
export interface DatabaseAccount {
|
||||
id: string;
|
||||
name: string;
|
||||
location: string;
|
||||
type: string;
|
||||
kind: string;
|
||||
}
|
||||
|
||||
export interface DatabaseAccount extends ArmEntity {
|
||||
properties: DatabaseAccountExtendedProperties;
|
||||
systemData?: DatabaseAccountSystemData;
|
||||
}
|
||||
@@ -38,8 +35,6 @@ export interface DatabaseAccountExtendedProperties {
|
||||
locations?: DatabaseAccountResponseLocation[];
|
||||
postgresqlEndpoint?: string;
|
||||
publicNetworkAccess?: string;
|
||||
enablePriorityBasedExecution?: boolean;
|
||||
vcoreMongoEndpoint?: string;
|
||||
}
|
||||
|
||||
export interface DatabaseAccountResponseLocation {
|
||||
@@ -88,13 +83,13 @@ export interface GenerateTokenResponse {
|
||||
}
|
||||
|
||||
export interface Subscription {
|
||||
uniqueDisplayName?: string;
|
||||
uniqueDisplayName: string;
|
||||
displayName: string;
|
||||
subscriptionId: string;
|
||||
tenantId?: string;
|
||||
tenantId: string;
|
||||
state: string;
|
||||
subscriptionPolicies?: SubscriptionPolicies;
|
||||
authorizationSource?: string;
|
||||
subscriptionPolicies: SubscriptionPolicies;
|
||||
authorizationSource: string;
|
||||
}
|
||||
|
||||
export interface SubscriptionPolicies {
|
||||
@@ -159,7 +154,6 @@ export interface Collection extends Resource {
|
||||
geospatialConfig?: GeospatialConfig;
|
||||
schema?: ISchema;
|
||||
requestSchema?: () => void;
|
||||
computedProperties?: ComputedProperties;
|
||||
}
|
||||
|
||||
export interface CollectionsWithPagination {
|
||||
@@ -198,13 +192,6 @@ export interface IndexingPolicy {
|
||||
spatialIndexes?: any;
|
||||
}
|
||||
|
||||
export interface ComputedProperty {
|
||||
name: string;
|
||||
query: string;
|
||||
}
|
||||
|
||||
export type ComputedProperties = ComputedProperty[];
|
||||
|
||||
export interface PartitionKey {
|
||||
paths: string[];
|
||||
kind: "Hash" | "Range" | "MultiHash";
|
||||
@@ -326,7 +313,7 @@ export interface CreateCollectionParams {
|
||||
collectionId: string;
|
||||
databaseId: string;
|
||||
databaseLevelThroughput: boolean;
|
||||
offerThroughput?: number;
|
||||
offerThroughput: number;
|
||||
analyticalStorageTtl?: number;
|
||||
autoPilotMaxThroughput?: number;
|
||||
indexingPolicy?: IndexingPolicy;
|
||||
@@ -465,11 +452,8 @@ export interface ContainerInfo {
|
||||
}
|
||||
|
||||
export interface IProvisionData {
|
||||
cosmosEndpoint?: string;
|
||||
cosmosEndpoint: string;
|
||||
poolId: string;
|
||||
databaseId?: string;
|
||||
containerId?: string;
|
||||
mode?: string;
|
||||
}
|
||||
|
||||
export interface IContainerData {
|
||||
@@ -591,7 +575,7 @@ export interface ContainerConnectionInfo {
|
||||
//need to add ram and rom info
|
||||
}
|
||||
|
||||
export interface FirewallRule {
|
||||
export interface PostgresFirewallRule {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
@@ -612,14 +596,3 @@ export enum PhoenixErrorType {
|
||||
PhoenixFlightFallback = "PhoenixFlightFallback",
|
||||
UserMissingPermissionsError = "UserMissingPermissionsError",
|
||||
}
|
||||
|
||||
export interface CopilotEnabledConfiguration {
|
||||
isEnabled: boolean;
|
||||
}
|
||||
|
||||
export interface FeatureRegistration {
|
||||
name: string;
|
||||
properties: {
|
||||
state: string;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,44 @@
|
||||
import * as ActionContracts from "./ActionContracts";
|
||||
import * as Diagnostics from "./Diagnostics";
|
||||
import { MessageTypes } from "./MessageTypes";
|
||||
import * as Versions from "./Versions";
|
||||
|
||||
export { ActionContracts, Diagnostics, MessageTypes, Versions };
|
||||
/**
|
||||
* Messaging types used with Data Explorer <-> Portal communication
|
||||
* and Hosted <-> Explorer communication
|
||||
*/
|
||||
export enum MessageTypes {
|
||||
TelemetryInfo,
|
||||
LogInfo,
|
||||
RefreshResources,
|
||||
AllDatabases,
|
||||
CollectionsForDatabase,
|
||||
RefreshOffers,
|
||||
AllOffers,
|
||||
UpdateLocationHash,
|
||||
SingleOffer,
|
||||
RefreshOffer,
|
||||
UpdateAccountName,
|
||||
ForbiddenError,
|
||||
AadSignIn,
|
||||
GetAccessAadRequest,
|
||||
GetAccessAadResponse,
|
||||
UpdateAccountSwitch,
|
||||
UpdateDirectoryControl,
|
||||
SwitchAccount,
|
||||
SendNotification,
|
||||
ClearNotification,
|
||||
ExplorerClickEvent,
|
||||
LoadingStatus,
|
||||
GetArcadiaToken,
|
||||
CreateWorkspace,
|
||||
CreateSparkPool,
|
||||
RefreshDatabaseAccount,
|
||||
CloseTab,
|
||||
OpenQuickstartBlade,
|
||||
OpenPostgreSQLPasswordReset,
|
||||
OpenPostgresNetworkingBlade,
|
||||
OpenCosmosDBNetworkingBlade,
|
||||
DisplayNPSSurvey,
|
||||
}
|
||||
|
||||
export { Versions, ActionContracts, Diagnostics };
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import { AuthorizationToken } from "./MessageTypes";
|
||||
|
||||
// This is the version of these messages
|
||||
export const FABRIC_RPC_VERSION = "2";
|
||||
|
||||
// Fabric to Data Explorer
|
||||
|
||||
// TODO Deprecated. Remove this section once DE is updated
|
||||
export type FabricMessageV1 =
|
||||
| {
|
||||
type: "newContainer";
|
||||
databaseName: string;
|
||||
}
|
||||
| {
|
||||
type: "initialize";
|
||||
message: {
|
||||
endpoint: string | undefined;
|
||||
databaseId: string | undefined;
|
||||
resourceTokens: unknown | undefined;
|
||||
resourceTokensTimestamp: number | undefined;
|
||||
error: string | undefined;
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: "authorizationToken";
|
||||
message: {
|
||||
id: string;
|
||||
error: string | undefined;
|
||||
data: AuthorizationToken | undefined;
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: "allResourceTokens";
|
||||
message: {
|
||||
id: string;
|
||||
error: string | undefined;
|
||||
endpoint: string | undefined;
|
||||
databaseId: string | undefined;
|
||||
resourceTokens: unknown | undefined;
|
||||
resourceTokensTimestamp: number | undefined;
|
||||
};
|
||||
};
|
||||
// -----------------------------
|
||||
|
||||
export type FabricMessageV2 =
|
||||
| {
|
||||
type: "newContainer";
|
||||
databaseName: string;
|
||||
}
|
||||
| {
|
||||
type: "initialize";
|
||||
version: string;
|
||||
id: string;
|
||||
message: {
|
||||
connectionId: string;
|
||||
isVisible: boolean;
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: "authorizationToken";
|
||||
message: {
|
||||
id: string;
|
||||
error: string | undefined;
|
||||
data: AuthorizationToken | undefined;
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: "allResourceTokens_v2";
|
||||
message: {
|
||||
id: string;
|
||||
error: string | undefined;
|
||||
data: FabricDatabaseConnectionInfo | undefined;
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: "explorerVisible";
|
||||
message: {
|
||||
visible: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type CosmosDBTokenResponse = {
|
||||
token: string;
|
||||
date: string;
|
||||
};
|
||||
|
||||
export type CosmosDBConnectionInfoResponse = {
|
||||
endpoint: string;
|
||||
databaseId: string;
|
||||
resourceTokens: { [resourceId: string]: string };
|
||||
};
|
||||
|
||||
export interface FabricDatabaseConnectionInfo extends CosmosDBConnectionInfoResponse {
|
||||
resourceTokensTimestamp: number;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* Messaging types used with Data Explorer <-> Portal communication,
|
||||
* Hosted <-> Explorer communication and Data Explorer -> Fabric communication.
|
||||
*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* WARNING: !!!!!!! YOU CAN ONLY ADD NEW TYPES TO THE END OF THIS ENUM !!!!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
*
|
||||
* Enum are integers, so inserting or deleting a type will break the communication.
|
||||
*/
|
||||
export enum MessageTypes {
|
||||
TelemetryInfo,
|
||||
LogInfo,
|
||||
RefreshResources,
|
||||
AllDatabases,
|
||||
CollectionsForDatabase,
|
||||
RefreshOffers,
|
||||
AllOffers,
|
||||
UpdateLocationHash,
|
||||
SingleOffer,
|
||||
RefreshOffer,
|
||||
UpdateAccountName,
|
||||
ForbiddenError,
|
||||
AadSignIn,
|
||||
GetAccessAadRequest,
|
||||
GetAccessAadResponse,
|
||||
UpdateAccountSwitch,
|
||||
UpdateDirectoryControl,
|
||||
SwitchAccount,
|
||||
SendNotification,
|
||||
ClearNotification,
|
||||
ExplorerClickEvent,
|
||||
LoadingStatus,
|
||||
GetArcadiaToken,
|
||||
CreateWorkspace,
|
||||
CreateSparkPool,
|
||||
RefreshDatabaseAccount,
|
||||
CloseTab,
|
||||
OpenQuickstartBlade,
|
||||
OpenPostgreSQLPasswordReset,
|
||||
OpenPostgresNetworkingBlade,
|
||||
OpenCosmosDBNetworkingBlade,
|
||||
DisplayNPSSurvey,
|
||||
OpenVCoreMongoNetworkingBlade,
|
||||
OpenVCoreMongoConnectionStringsBlade,
|
||||
GetAuthorizationToken, // Data Explorer -> Fabric
|
||||
GetAllResourceTokens, // Data Explorer -> Fabric
|
||||
Ready, // Data Explorer -> Fabric
|
||||
OpenCESCVAFeedbackBlade,
|
||||
ActivateTab,
|
||||
}
|
||||
|
||||
export interface AuthorizationToken {
|
||||
XDate: string;
|
||||
PrimaryReadWriteToken: string;
|
||||
}
|
||||
@@ -135,7 +135,6 @@ export interface Collection extends CollectionBase {
|
||||
changeFeedPolicy: ko.Observable<DataModels.ChangeFeedPolicy>;
|
||||
geospatialConfig: ko.Observable<DataModels.GeospatialConfig>;
|
||||
documentIds: ko.ObservableArray<DocumentId>;
|
||||
computedProperties: ko.Observable<DataModels.ComputedProperties>;
|
||||
|
||||
cassandraKeys: CassandraTableKeys;
|
||||
cassandraSchema: CassandraTableKey[];
|
||||
@@ -373,7 +372,6 @@ export enum TerminalKind {
|
||||
Mongo = 1,
|
||||
Cassandra = 2,
|
||||
Postgres = 3,
|
||||
VCoreMongo = 4,
|
||||
}
|
||||
|
||||
export interface DataExplorerInputsFrame {
|
||||
@@ -387,11 +385,9 @@ export interface DataExplorerInputsFrame {
|
||||
dnsSuffix?: string;
|
||||
serverId?: string;
|
||||
extensionEndpoint?: string;
|
||||
portalBackendEndpoint?: string;
|
||||
mongoProxyEndpoint?: string;
|
||||
cassandraProxyEndpoint?: string;
|
||||
subscriptionType?: SubscriptionType;
|
||||
quotaId?: string;
|
||||
addCollectionDefaultFlight?: string;
|
||||
isTryCosmosDBSubscription?: boolean;
|
||||
loadDatabaseAccountTimestamp?: number;
|
||||
sharedThroughputMinimum?: number;
|
||||
@@ -401,7 +397,6 @@ export interface DataExplorerInputsFrame {
|
||||
defaultCollectionThroughput?: CollectionCreationDefaults;
|
||||
isPostgresAccount?: boolean;
|
||||
isReplica?: boolean;
|
||||
isVCoreMongoAccount?: boolean;
|
||||
clientIpAddress?: string;
|
||||
// TODO: Update this param in the OSS extension to remove isFreeTier, isMarlinServerGroup, and make nodes a flat array instead of an nested array
|
||||
connectionStringParams?: any;
|
||||
@@ -409,7 +404,6 @@ export interface DataExplorerInputsFrame {
|
||||
features?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
feedbackPolicies?: any;
|
||||
}
|
||||
|
||||
export interface SelfServeFrameInputs {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
@@ -109,7 +109,6 @@ describe("iframe rendering when there is no data", () => {
|
||||
theme: 4,
|
||||
},
|
||||
},
|
||||
origin: "http://localhost",
|
||||
};
|
||||
|
||||
const divElement = `<div id="${Heatmap.elementId}"></div>`;
|
||||
@@ -130,7 +129,6 @@ describe("iframe rendering when there is no data", () => {
|
||||
theme: 2,
|
||||
},
|
||||
},
|
||||
origin: "http://localhost",
|
||||
};
|
||||
|
||||
const divElement = `<div id="${Heatmap.elementId}"></div>`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import dayjs from "dayjs";
|
||||
import * as Plotly from "plotly.js-cartesian-dist-min";
|
||||
import { StyleConstants } from "../../Common/Constants";
|
||||
import { sendCachedDataMessage, sendReadyMessage } from "../../Common/MessageHandler";
|
||||
import { StyleConstants } from "../../Common/StyleConstants";
|
||||
import { MessageTypes } from "../../Contracts/ExplorerContracts";
|
||||
import { isInvalidParentFrameOrigin } from "../../Utils/MessageValidation";
|
||||
import "./Heatmap.less";
|
||||
@@ -191,7 +191,7 @@ export class Heatmap {
|
||||
Heatmap.elementId,
|
||||
this._getChartSettings(),
|
||||
this._getLayoutSettings(),
|
||||
this._getChartDisplaySettings(),
|
||||
this._getChartDisplaySettings()
|
||||
);
|
||||
const plotDiv: any = document.getElementById(Heatmap.elementId);
|
||||
plotDiv.on("plotly_click", (data: any) => {
|
||||
|
||||
1954
src/Definitions/datatables.d.ts
vendored
Normal file
2
src/Definitions/jquery-typescript.d.ts
vendored
@@ -5,7 +5,7 @@
|
||||
* https://github.com/running-coder/jquery-typeahead/issues/156
|
||||
* TODO: Replace this minimum definition by the official one when it comes out.
|
||||
*/
|
||||
/// <reference types="jquery" />
|
||||
/// <reference path="jquery.d.ts" />
|
||||
|
||||
interface JQueryTypeaheadParam {
|
||||
input: string;
|
||||
|
||||
16
src/Definitions/jquery-ui.d.ts
vendored
@@ -3,7 +3,7 @@
|
||||
// Definitions by: Boris Yankov <https://github.com/borisyankov/>, John Reilly <https://github.com/johnnyreilly>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/// <reference types="jquery"/>
|
||||
/// <reference path="jquery.d.ts"/>
|
||||
|
||||
declare namespace JQueryUI {
|
||||
// Accordion //////////////////////////////////////////////////
|
||||
@@ -1001,7 +1001,7 @@ interface JQuery {
|
||||
date: Date,
|
||||
onSelect?: () => void,
|
||||
settings?: JQueryUI.DatepickerOptions,
|
||||
pos?: number[],
|
||||
pos?: number[]
|
||||
): JQuery;
|
||||
/**
|
||||
* Opens the datepicker in a dialog box.
|
||||
@@ -1017,7 +1017,7 @@ interface JQuery {
|
||||
date: Date,
|
||||
onSelect?: () => void,
|
||||
settings?: JQueryUI.DatepickerOptions,
|
||||
pos?: MouseEvent,
|
||||
pos?: MouseEvent
|
||||
): JQuery;
|
||||
/**
|
||||
* Opens the datepicker in a dialog box.
|
||||
@@ -1033,7 +1033,7 @@ interface JQuery {
|
||||
date: string,
|
||||
onSelect?: () => void,
|
||||
settings?: JQueryUI.DatepickerOptions,
|
||||
pos?: number[],
|
||||
pos?: number[]
|
||||
): JQuery;
|
||||
/**
|
||||
* Opens the datepicker in a dialog box.
|
||||
@@ -1049,7 +1049,7 @@ interface JQuery {
|
||||
date: string,
|
||||
onSelect?: () => void,
|
||||
settings?: JQueryUI.DatepickerOptions,
|
||||
pos?: MouseEvent,
|
||||
pos?: MouseEvent
|
||||
): JQuery;
|
||||
/**
|
||||
* Returns the current date for the datepicker or null if no date has been selected.
|
||||
@@ -1199,7 +1199,7 @@ interface JQuery {
|
||||
datepicker(
|
||||
methodName: "option",
|
||||
optionName: "beforeShow",
|
||||
beforeShowValue: (input: Element, inst: any) => JQueryUI.DatepickerOptions,
|
||||
beforeShowValue: (input: Element, inst: any) => JQueryUI.DatepickerOptions
|
||||
): JQuery;
|
||||
|
||||
/**
|
||||
@@ -1716,14 +1716,14 @@ interface JQuery {
|
||||
addClassName: string,
|
||||
duration?: number,
|
||||
easing?: string,
|
||||
complete?: Function,
|
||||
complete?: Function
|
||||
): JQuery;
|
||||
switchClass(
|
||||
removeClassName: string,
|
||||
addClassName: string,
|
||||
duration?: string,
|
||||
easing?: string,
|
||||
complete?: Function,
|
||||
complete?: Function
|
||||
): JQuery;
|
||||
|
||||
toggleClass(className: string, duration?: number, easing?: string, complete?: Function): JQuery;
|
||||
|
||||
1890
src/Definitions/jquery.d.ts
vendored
Normal file
4
src/Definitions/less.d.ts
vendored
@@ -1,4 +0,0 @@
|
||||
declare module "*.less" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
@@ -18,7 +18,6 @@ import * as ViewModels from "../Contracts/ViewModels";
|
||||
import { userContext } from "../UserContext";
|
||||
import { getCollectionName, getDatabaseName } from "../Utils/APITypeUtils";
|
||||
import { useSidePanel } from "../hooks/useSidePanel";
|
||||
import { Platform, configContext } from "./../ConfigContext";
|
||||
import { TreeNodeMenuItem } from "./Controls/TreeComponent/TreeComponent";
|
||||
import Explorer from "./Explorer";
|
||||
import { useNotebook } from "./Notebook/useNotebook";
|
||||
@@ -57,7 +56,7 @@ export const createDatabaseContextMenu = (container: Explorer, databaseId: strin
|
||||
.getState()
|
||||
.openSidePanel(
|
||||
"Delete " + getDatabaseName(),
|
||||
<DeleteDatabaseConfirmationPanel refreshDatabases={() => container.refreshAllDatabases()} />,
|
||||
<DeleteDatabaseConfirmationPanel refreshDatabases={() => container.refreshAllDatabases()} />
|
||||
),
|
||||
label: `Delete ${getDatabaseName()}`,
|
||||
styleClass: "deleteDatabaseMenuItem",
|
||||
@@ -68,7 +67,7 @@ export const createDatabaseContextMenu = (container: Explorer, databaseId: strin
|
||||
|
||||
export const createCollectionContextMenuButton = (
|
||||
container: Explorer,
|
||||
selectedCollection: ViewModels.Collection,
|
||||
selectedCollection: ViewModels.Collection
|
||||
): TreeNodeMenuItem[] => {
|
||||
const items: TreeNodeMenuItem[] = [];
|
||||
if (userContext.apiType === "SQL" || userContext.apiType === "Gremlin") {
|
||||
@@ -100,13 +99,11 @@ export const createCollectionContextMenuButton = (
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
configContext.platform !== Platform.Fabric &&
|
||||
(userContext.apiType === "SQL" || userContext.apiType === "Gremlin")
|
||||
) {
|
||||
if (userContext.apiType === "SQL" || userContext.apiType === "Gremlin") {
|
||||
items.push({
|
||||
iconSrc: AddStoredProcedureIcon,
|
||||
onClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = useSelectedNode.getState().findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewStoredProcedureClick(selectedCollection, undefined);
|
||||
},
|
||||
label: "New Stored Procedure",
|
||||
@@ -115,6 +112,7 @@ export const createCollectionContextMenuButton = (
|
||||
items.push({
|
||||
iconSrc: AddUdfIcon,
|
||||
onClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = useSelectedNode.getState().findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewUserDefinedFunctionClick(selectedCollection);
|
||||
},
|
||||
label: "New UDF",
|
||||
@@ -123,28 +121,25 @@ export const createCollectionContextMenuButton = (
|
||||
items.push({
|
||||
iconSrc: AddTriggerIcon,
|
||||
onClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = useSelectedNode.getState().findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewTriggerClick(selectedCollection, undefined);
|
||||
},
|
||||
label: "New Trigger",
|
||||
});
|
||||
}
|
||||
|
||||
if (configContext.platform !== Platform.Fabric) {
|
||||
items.push({
|
||||
iconSrc: DeleteCollectionIcon,
|
||||
onClick: () => {
|
||||
useSelectedNode.getState().setSelectedNode(selectedCollection);
|
||||
useSidePanel
|
||||
.getState()
|
||||
.openSidePanel(
|
||||
"Delete " + getCollectionName(),
|
||||
<DeleteCollectionConfirmationPane refreshDatabases={() => container.refreshAllDatabases()} />,
|
||||
);
|
||||
},
|
||||
label: `Delete ${getCollectionName()}`,
|
||||
styleClass: "deleteCollectionMenuItem",
|
||||
});
|
||||
}
|
||||
items.push({
|
||||
iconSrc: DeleteCollectionIcon,
|
||||
onClick: () =>
|
||||
useSidePanel
|
||||
.getState()
|
||||
.openSidePanel(
|
||||
"Delete " + getCollectionName(),
|
||||
<DeleteCollectionConfirmationPane refreshDatabases={() => container.refreshAllDatabases()} />
|
||||
),
|
||||
label: `Delete ${getCollectionName()}`,
|
||||
styleClass: "deleteCollectionMenuItem",
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
@@ -177,7 +172,7 @@ export const createSampleCollectionContextMenuButton = (): TreeNodeMenuItem[] =>
|
||||
|
||||
export const createStoreProcedureContextMenuItems = (
|
||||
container: Explorer,
|
||||
storedProcedure: StoredProcedure,
|
||||
storedProcedure: StoredProcedure
|
||||
): TreeNodeMenuItem[] => {
|
||||
if (userContext.apiType === "Cassandra") {
|
||||
return [];
|
||||
@@ -208,7 +203,7 @@ export const createTriggerContextMenuItems = (container: Explorer, trigger: Trig
|
||||
|
||||
export const createUserDefinedFunctionContextMenuItems = (
|
||||
container: Explorer,
|
||||
userDefinedFunction: UserDefinedFunction,
|
||||
userDefinedFunction: UserDefinedFunction
|
||||
): TreeNodeMenuItem[] => {
|
||||
if (userContext.apiType === "Cassandra") {
|
||||
return [];
|
||||
|
||||
@@ -27,7 +27,6 @@ export interface AccordionItemComponentProps {
|
||||
isExpanded?: boolean;
|
||||
containerStyles?: React.CSSProperties;
|
||||
styles?: React.CSSProperties;
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
interface AccordionItemComponentState {
|
||||
|
||||
@@ -16,7 +16,6 @@ export interface CollapsiblePanelProps {
|
||||
isCollapsed: boolean;
|
||||
onCollapsedChanged: (newValue: boolean) => void;
|
||||
collapseToLeft?: boolean;
|
||||
children: JSX.Element | JSX.Element[];
|
||||
}
|
||||
|
||||
export class CollapsiblePanel extends React.Component<CollapsiblePanelProps> {
|
||||
|
||||
@@ -7,7 +7,6 @@ describe("CollapsibleSectionComponent", () => {
|
||||
const props: CollapsibleSectionProps = {
|
||||
title: "Sample title",
|
||||
isExpandedByDefault: true,
|
||||
children: <></>,
|
||||
};
|
||||
|
||||
const wrapper = shallow(<CollapsibleSectionComponent {...props} />);
|
||||
|
||||
@@ -7,7 +7,6 @@ export interface CollapsibleSectionProps {
|
||||
title: string;
|
||||
isExpandedByDefault: boolean;
|
||||
onExpand?: () => void;
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
export interface CollapsibleSectionState {
|
||||
|
||||
@@ -203,9 +203,11 @@ export class CommandButtonComponent extends React.Component<CommandButtonCompone
|
||||
}}
|
||||
>
|
||||
<div className="commandDropdown">
|
||||
{this.props.children.map((c: CommandButtonComponentProps, index: number): JSX.Element => {
|
||||
return CommandButtonComponent.renderButton(c, `${index}`);
|
||||
})}
|
||||
{this.props.children.map(
|
||||
(c: CommandButtonComponentProps, index: number): JSX.Element => {
|
||||
return CommandButtonComponent.renderButton(c, `${index}`);
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -215,7 +217,7 @@ export class CommandButtonComponent extends React.Component<CommandButtonCompone
|
||||
public static renderLabel(
|
||||
props: CommandButtonComponentProps,
|
||||
key?: string,
|
||||
refct?: (input: HTMLElement) => void,
|
||||
refct?: (input: HTMLElement) => void
|
||||
): JSX.Element {
|
||||
if (!props.commandButtonLabel) {
|
||||
return <React.Fragment />;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {
|
||||
ChoiceGroup,
|
||||
DefaultButton,
|
||||
Dialog as FluentDialog,
|
||||
DialogFooter,
|
||||
DialogType,
|
||||
Dialog as FluentDialog,
|
||||
FontIcon,
|
||||
IButtonProps,
|
||||
IChoiceGroupProps,
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
ProgressIndicator,
|
||||
TextField,
|
||||
} from "@fluentui/react";
|
||||
import React, { FC, useEffect } from "react";
|
||||
import React, { FC } from "react";
|
||||
import create, { UseStore } from "zustand";
|
||||
|
||||
export interface DialogState {
|
||||
@@ -33,7 +33,7 @@ export interface DialogState {
|
||||
contentHtml?: JSX.Element,
|
||||
choiceGroupProps?: IChoiceGroupProps,
|
||||
textFieldProps?: TextFieldProps,
|
||||
primaryButtonDisabled?: boolean,
|
||||
primaryButtonDisabled?: boolean
|
||||
) => void;
|
||||
showOkModalDialog: (title: string, subText: string) => void;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ export const useDialog: UseStore<DialogState> = create((set, get) => ({
|
||||
showOkCancelModalDialog: state.showOkCancelModalDialog,
|
||||
showOkModalDialog: state.showOkModalDialog,
|
||||
}),
|
||||
true, // TODO: This probably should not be true but its causing a prod bug so easier to just set the proper state above
|
||||
true // TODO: This probably should not be true but its causing a prod bug so easier to just set the proper state above
|
||||
),
|
||||
showOkCancelModalDialog: (
|
||||
title: string,
|
||||
@@ -62,7 +62,7 @@ export const useDialog: UseStore<DialogState> = create((set, get) => ({
|
||||
contentHtml?: JSX.Element,
|
||||
choiceGroupProps?: IChoiceGroupProps,
|
||||
textFieldProps?: TextFieldProps,
|
||||
primaryButtonDisabled?: boolean,
|
||||
primaryButtonDisabled?: boolean
|
||||
): void =>
|
||||
get().openDialog({
|
||||
isModal: true,
|
||||
@@ -157,20 +157,6 @@ export const Dialog: FC = () => {
|
||||
contentHtml,
|
||||
} = props || {};
|
||||
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === "Escape") {
|
||||
useDialog.getState().closeDialog();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
} else {
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
const dialogProps: IDialogProps = {
|
||||
hidden: !visible,
|
||||
dialogContentProps: {
|
||||
|
||||
@@ -95,11 +95,11 @@ export class DiffEditorViewModel {
|
||||
protected async createDiffEditor(
|
||||
originalContent: string,
|
||||
modifiedContent: string,
|
||||
createCallback: (e: monaco.editor.IStandaloneDiffEditor) => void,
|
||||
createCallback: (e: monaco.editor.IStandaloneDiffEditor) => void
|
||||
) {
|
||||
this.editorContainer = document.getElementById(this.getEditorId());
|
||||
this.editorContainer.innerHTML = "";
|
||||
const options: monaco.editor.IStandaloneDiffEditorConstructionOptions = {
|
||||
const options: monaco.editor.IDiffEditorConstructionOptions = {
|
||||
lineNumbers: this.params.lineNumbers || "off",
|
||||
fontSize: 12,
|
||||
ariaLabel: this.params.ariaLabel,
|
||||
@@ -116,7 +116,7 @@ export class DiffEditorViewModel {
|
||||
const modifiedModel = monaco.editor.createModel(modifiedContent, language);
|
||||
const diffEditor: monaco.editor.IStandaloneDiffEditor = monaco.editor.createDiffEditor(
|
||||
this.editorContainer,
|
||||
options,
|
||||
options
|
||||
);
|
||||
diffEditor.setModel({
|
||||
original: originalModel,
|
||||
|
||||