mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-01-07 19:46:53 +00:00
Compare commits
3 Commits
dependabot
...
copilot_re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06973bd3d5 | ||
|
|
44667beba9 | ||
|
|
0566f19e87 |
@@ -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;
|
||||
}
|
||||
@@ -2576,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 {
|
||||
@@ -2649,7 +2648,7 @@ a:link {
|
||||
|
||||
.nav-tabs > li.active > .tabNavContentContainer > .tab_Content > .tabNavText {
|
||||
font-weight: bolder;
|
||||
border-bottom: 2px solid rgba(0, 120, 212, 1);
|
||||
border-bottom: 2px solid rgba(0,120,212,1);
|
||||
}
|
||||
|
||||
.nav-tabs > li.active:focus > .tabNavContentContainer {
|
||||
@@ -3097,3 +3096,4 @@ a:link {
|
||||
background: white;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
256
package-lock.json
generated
256
package-lock.json
generated
@@ -533,11 +533,6 @@
|
||||
"regexpu-core": "^4.7.1"
|
||||
}
|
||||
},
|
||||
"@babel/helper-environment-visitor": {
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
|
||||
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA=="
|
||||
},
|
||||
"@babel/helper-explode-assignable-expression": {
|
||||
"version": "7.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz",
|
||||
@@ -625,7 +620,24 @@
|
||||
"@babel/parser": {
|
||||
"version": "7.13.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz",
|
||||
"integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw=="
|
||||
"integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.13.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz",
|
||||
"integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.12.13",
|
||||
"@babel/generator": "^7.13.9",
|
||||
"@babel/helper-function-name": "^7.12.13",
|
||||
"@babel/helper-split-export-declaration": "^7.12.13",
|
||||
"@babel/parser": "^7.13.13",
|
||||
"@babel/types": "^7.13.13",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.13.14",
|
||||
@@ -706,6 +718,28 @@
|
||||
"@babel/types": "^7.12.13"
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.13.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz",
|
||||
"integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.12.13",
|
||||
"@babel/generator": "^7.13.9",
|
||||
"@babel/helper-function-name": "^7.12.13",
|
||||
"@babel/helper-split-export-declaration": "^7.12.13",
|
||||
"@babel/parser": "^7.13.13",
|
||||
"@babel/types": "^7.13.13",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/parser": {
|
||||
"version": "7.13.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz",
|
||||
"integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.13.14",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz",
|
||||
@@ -783,6 +817,21 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz",
|
||||
"integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw=="
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.13.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz",
|
||||
"integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.12.13",
|
||||
"@babel/generator": "^7.13.9",
|
||||
"@babel/helper-function-name": "^7.12.13",
|
||||
"@babel/helper-split-export-declaration": "^7.12.13",
|
||||
"@babel/parser": "^7.13.13",
|
||||
"@babel/types": "^7.13.13",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.13.14",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz",
|
||||
@@ -844,11 +893,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/helper-string-parser": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
|
||||
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
|
||||
},
|
||||
"@babel/helper-validator-identifier": {
|
||||
"version": "7.12.11",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
|
||||
@@ -883,6 +927,30 @@
|
||||
"@babel/types": "^7.12.13"
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.13.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz",
|
||||
"integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.12.13",
|
||||
"@babel/generator": "^7.13.9",
|
||||
"@babel/helper-function-name": "^7.12.13",
|
||||
"@babel/helper-split-export-declaration": "^7.12.13",
|
||||
"@babel/parser": "^7.13.13",
|
||||
"@babel/types": "^7.13.13",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/parser": {
|
||||
"version": "7.13.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz",
|
||||
"integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.13.14",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz",
|
||||
@@ -916,6 +984,28 @@
|
||||
"@babel/types": "^7.12.13"
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.13.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz",
|
||||
"integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.12.13",
|
||||
"@babel/generator": "^7.13.9",
|
||||
"@babel/helper-function-name": "^7.12.13",
|
||||
"@babel/helper-split-export-declaration": "^7.12.13",
|
||||
"@babel/parser": "^7.13.13",
|
||||
"@babel/types": "^7.13.13",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/parser": {
|
||||
"version": "7.13.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz",
|
||||
"integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.13.14",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz",
|
||||
@@ -1941,107 +2031,19 @@
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
"version": "7.23.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
|
||||
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
|
||||
"version": "7.12.12",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz",
|
||||
"integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/generator": "^7.23.0",
|
||||
"@babel/helper-environment-visitor": "^7.22.20",
|
||||
"@babel/helper-function-name": "^7.23.0",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.23.0",
|
||||
"@babel/types": "^7.23.0",
|
||||
"@babel/code-frame": "^7.12.11",
|
||||
"@babel/generator": "^7.12.11",
|
||||
"@babel/helper-function-name": "^7.12.11",
|
||||
"@babel/helper-split-export-declaration": "^7.12.11",
|
||||
"@babel/parser": "^7.12.11",
|
||||
"@babel/types": "^7.12.12",
|
||||
"debug": "^4.1.0",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.22.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
|
||||
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.22.13",
|
||||
"chalk": "^2.4.2"
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
|
||||
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
|
||||
"requires": {
|
||||
"@babel/types": "^7.23.0",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
}
|
||||
},
|
||||
"@babel/helper-function-name": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
|
||||
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
|
||||
"requires": {
|
||||
"@babel/template": "^7.22.15",
|
||||
"@babel/types": "^7.23.0"
|
||||
}
|
||||
},
|
||||
"@babel/helper-hoist-variables": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
|
||||
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
|
||||
"requires": {
|
||||
"@babel/types": "^7.22.5"
|
||||
}
|
||||
},
|
||||
"@babel/helper-split-export-declaration": {
|
||||
"version": "7.22.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
|
||||
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
|
||||
"requires": {
|
||||
"@babel/types": "^7.22.5"
|
||||
}
|
||||
},
|
||||
"@babel/helper-validator-identifier": {
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
|
||||
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A=="
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.22.20",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
|
||||
"integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
|
||||
"requires": {
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"chalk": "^2.4.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
|
||||
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw=="
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
|
||||
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/parser": "^7.22.15",
|
||||
"@babel/types": "^7.22.15"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
|
||||
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
|
||||
"requires": {
|
||||
"@babel/helper-string-parser": "^7.22.5",
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
}
|
||||
"globals": "^11.1.0",
|
||||
"lodash": "^4.17.19"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
@@ -4006,40 +4008,6 @@
|
||||
"@types/yargs": "^13.0.0"
|
||||
}
|
||||
},
|
||||
"@jridgewell/gen-mapping": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
|
||||
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
|
||||
"requires": {
|
||||
"@jridgewell/set-array": "^1.0.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
"@jridgewell/trace-mapping": "^0.3.9"
|
||||
}
|
||||
},
|
||||
"@jridgewell/resolve-uri": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
|
||||
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA=="
|
||||
},
|
||||
"@jridgewell/set-array": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
||||
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw=="
|
||||
},
|
||||
"@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||
},
|
||||
"@jridgewell/trace-mapping": {
|
||||
"version": "0.3.19",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
|
||||
"integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
|
||||
"requires": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"@jupyterlab/apputils": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@jupyterlab/apputils/-/apputils-3.0.2.tgz",
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import * as Cosmos from "@azure/cosmos";
|
||||
import { sendCachedDataMessage } from "Common/MessageHandler";
|
||||
import { AuthorizationToken, MessageTypes } from "Contracts/MessageTypes";
|
||||
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";
|
||||
import { AuthType } from "../AuthType";
|
||||
|
||||
const _global = typeof self === "undefined" ? window : self;
|
||||
|
||||
@@ -27,15 +26,6 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
||||
return decodeURIComponent(headers.authorization);
|
||||
}
|
||||
|
||||
if (configContext.platform === Platform.Fabric) {
|
||||
const authorizationToken = await sendCachedDataMessage<AuthorizationToken>(MessageTypes.GetAuthorizationToken, [
|
||||
requestInfo,
|
||||
]);
|
||||
console.log("Response from Fabric: ", authorizationToken);
|
||||
headers[HttpHeaders.msDate] = authorizationToken.XDate;
|
||||
return 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);
|
||||
@@ -66,11 +56,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", {
|
||||
|
||||
@@ -22,7 +22,7 @@ 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();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,46 @@
|
||||
import { MessageTypes } from "Contracts/MessageTypes";
|
||||
import * as ActionContracts from "./ActionContracts";
|
||||
import * as Diagnostics from "./Diagnostics";
|
||||
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,
|
||||
OpenVCoreMongoNetworkingBlade,
|
||||
OpenVCoreMongoConnectionStringsBlade,
|
||||
}
|
||||
|
||||
export { ActionContracts, Diagnostics, Versions };
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { AuthorizationToken, MessageTypes } from "./MessageTypes";
|
||||
|
||||
export type FabricMessage =
|
||||
| {
|
||||
type: "newContainer";
|
||||
@@ -7,52 +5,21 @@ export type FabricMessage =
|
||||
}
|
||||
| {
|
||||
type: "initialize";
|
||||
message: {
|
||||
endpoint: string | undefined;
|
||||
error: string | undefined;
|
||||
};
|
||||
connectionString: string | undefined;
|
||||
}
|
||||
| {
|
||||
type: "openTab";
|
||||
databaseName: string;
|
||||
collectionName: string | undefined;
|
||||
}
|
||||
| {
|
||||
type: "authorizationToken";
|
||||
message: {
|
||||
id: string;
|
||||
error: string | undefined;
|
||||
data: AuthorizationToken | undefined;
|
||||
};
|
||||
};
|
||||
|
||||
export type DataExploreMessage =
|
||||
| "ready"
|
||||
| {
|
||||
type: MessageTypes.TelemetryInfo;
|
||||
type: number;
|
||||
data: {
|
||||
action: "LoadDatabases";
|
||||
actionModifier: "success" | "start";
|
||||
defaultExperience: "SQL";
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: MessageTypes.GetAuthorizationToken;
|
||||
id: string;
|
||||
params: GetCosmosTokenMessageOptions[];
|
||||
};
|
||||
|
||||
export type GetCosmosTokenMessageOptions = {
|
||||
verb: "connect" | "delete" | "get" | "head" | "options" | "patch" | "post" | "put" | "trace";
|
||||
resourceType: "" | "dbs" | "colls" | "docs" | "sprocs" | "pkranges";
|
||||
resourceId: string;
|
||||
};
|
||||
|
||||
export type CosmosDBTokenResponse = {
|
||||
token: string;
|
||||
date: string;
|
||||
};
|
||||
|
||||
export type CosmosDBConnectionInfoResponse = {
|
||||
endpoint: string;
|
||||
};
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Messaging types used with Data Explorer <-> Portal communication,
|
||||
* Hosted <-> Explorer communication and Data Explorer -> Fabric 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,
|
||||
|
||||
// Data Explorer -> Fabric communication
|
||||
GetAuthorizationToken,
|
||||
}
|
||||
|
||||
export interface AuthorizationToken {
|
||||
XDate: string;
|
||||
PrimaryReadWriteToken: string;
|
||||
}
|
||||
@@ -123,6 +123,19 @@ describe("ContainerSampleGenerator", () => {
|
||||
await generator.createSampleContainerAsync();
|
||||
});
|
||||
|
||||
it("should not create any sample for Mongo API account", async () => {
|
||||
const experience = "Sample generation not supported for this API Mongo";
|
||||
updateUserContext({
|
||||
databaseAccount: {
|
||||
properties: {
|
||||
capabilities: [{ name: "EnableMongo" }],
|
||||
},
|
||||
} as DatabaseAccount,
|
||||
});
|
||||
|
||||
expect(ContainerSampleGenerator.createSampleGeneratorAsync(explorerStub)).rejects.toMatch(experience);
|
||||
});
|
||||
|
||||
it("should not create any sample for Table API account", async () => {
|
||||
const experience = "Sample generation not supported for this API Tables";
|
||||
updateUserContext({
|
||||
|
||||
@@ -102,7 +102,7 @@ describe("Query Copilot Feedback Modal snapshot test", () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should not submit submission if required description field is null", () => {
|
||||
it("should submit submission", () => {
|
||||
const explorer = new Explorer();
|
||||
const wrapper = shallow(<QueryCopilotFeedbackModal explorer={explorer} />);
|
||||
|
||||
@@ -110,24 +110,12 @@ describe("Query Copilot Feedback Modal snapshot test", () => {
|
||||
submitButton.simulate("click");
|
||||
wrapper.setProps({});
|
||||
|
||||
expect(SubmitFeedback).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it("should submit submission", () => {
|
||||
useQueryCopilot.getState().openFeedbackModal("test query", false, "test prompt");
|
||||
const explorer = new Explorer();
|
||||
const wrapper = shallow(<QueryCopilotFeedbackModal explorer={explorer} />);
|
||||
|
||||
const submitButton = wrapper.find("form");
|
||||
submitButton.simulate("submit");
|
||||
wrapper.setProps({});
|
||||
|
||||
expect(SubmitFeedback).toHaveBeenCalledTimes(1);
|
||||
expect(SubmitFeedback).toHaveBeenCalledWith({
|
||||
params: {
|
||||
likeQuery: false,
|
||||
generatedQuery: "test query",
|
||||
userPrompt: "test prompt",
|
||||
generatedQuery: "",
|
||||
userPrompt: "",
|
||||
description: "",
|
||||
contact: getUserEmail(),
|
||||
},
|
||||
|
||||
@@ -25,94 +25,93 @@ export const QueryCopilotFeedbackModal = ({ explorer }: { explorer: Explorer }):
|
||||
closeFeedbackModal,
|
||||
setHideFeedbackModalForLikedQueries,
|
||||
} = useQueryCopilot();
|
||||
const [isContactAllowed, setIsContactAllowed] = React.useState<boolean>(false);
|
||||
const [isContactAllowed, setIsContactAllowed] = React.useState<boolean>(true);
|
||||
const [description, setDescription] = React.useState<string>("");
|
||||
const [doNotShowAgainChecked, setDoNotShowAgainChecked] = React.useState<boolean>(false);
|
||||
const [contact, setContact] = React.useState<string>(getUserEmail());
|
||||
|
||||
const handleSubmit = () => {
|
||||
closeFeedbackModal();
|
||||
setHideFeedbackModalForLikedQueries(doNotShowAgainChecked);
|
||||
SubmitFeedback({
|
||||
params: { generatedQuery, likeQuery, description, userPrompt, contact },
|
||||
explorer: explorer,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={showFeedbackModal}>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Stack style={{ padding: 24 }}>
|
||||
<Stack horizontal horizontalAlign="space-between">
|
||||
<Text style={{ fontSize: 20, fontWeight: 600, marginBottom: 20 }}>Send feedback to Microsoft</Text>
|
||||
<IconButton iconProps={{ iconName: "Cancel" }} onClick={() => closeFeedbackModal()} />
|
||||
</Stack>
|
||||
<Text style={{ fontSize: 14, marginBottom: 14 }}>Your feedback will help improve the experience.</Text>
|
||||
<TextField
|
||||
styles={{ root: { marginBottom: 14 } }}
|
||||
label="Description"
|
||||
required
|
||||
placeholder="Provide more details"
|
||||
value={description}
|
||||
onChange={(_, newValue) => setDescription(newValue)}
|
||||
multiline
|
||||
rows={3}
|
||||
/>
|
||||
<TextField
|
||||
styles={{ root: { marginBottom: 14 } }}
|
||||
label="Query generated"
|
||||
defaultValue={generatedQuery}
|
||||
readOnly
|
||||
/>
|
||||
<ChoiceGroup
|
||||
styles={{
|
||||
root: {
|
||||
marginBottom: 14,
|
||||
},
|
||||
flexContainer: {
|
||||
selectors: {
|
||||
".ms-ChoiceField-field::before": { marginTop: 4 },
|
||||
".ms-ChoiceField-field::after": { marginTop: 4 },
|
||||
".ms-ChoiceFieldLabel": { paddingLeft: 6 },
|
||||
},
|
||||
},
|
||||
}}
|
||||
label="May we contact you about your feedback?"
|
||||
options={[
|
||||
{ key: "yes", text: "Yes, you may contact me." },
|
||||
{ key: "no", text: "No, do not contact me." },
|
||||
]}
|
||||
selectedKey={isContactAllowed ? "yes" : "no"}
|
||||
onChange={(_, option) => {
|
||||
setIsContactAllowed(option.key === "yes");
|
||||
setContact(option.key === "yes" ? getUserEmail() : "");
|
||||
}}
|
||||
></ChoiceGroup>
|
||||
<Text style={{ fontSize: 12, marginBottom: 14 }}>
|
||||
By pressing submit, your feedback will be used to improve Microsoft products and services. Please see the{" "}
|
||||
{
|
||||
<Link href="https://privacy.microsoft.com/privacystatement" target="_blank">
|
||||
Privacy statement
|
||||
</Link>
|
||||
}{" "}
|
||||
for more information.
|
||||
</Text>
|
||||
{likeQuery && (
|
||||
<Checkbox
|
||||
styles={{ label: { paddingLeft: 0 }, root: { marginBottom: 14 } }}
|
||||
label="Don't show me this next time"
|
||||
checked={doNotShowAgainChecked}
|
||||
onChange={(_, checked) => setDoNotShowAgainChecked(checked)}
|
||||
/>
|
||||
)}
|
||||
<Stack horizontal horizontalAlign="end">
|
||||
<PrimaryButton styles={{ root: { marginRight: 8 } }} type="submit">
|
||||
Submit
|
||||
</PrimaryButton>
|
||||
<DefaultButton onClick={() => closeFeedbackModal()}>Cancel</DefaultButton>
|
||||
</Stack>
|
||||
<Stack style={{ padding: 24 }}>
|
||||
<Stack horizontal horizontalAlign="space-between">
|
||||
<Text style={{ fontSize: 20, fontWeight: 600, marginBottom: 20 }}>Send feedback to Microsoft</Text>
|
||||
<IconButton iconProps={{ iconName: "Cancel" }} onClick={() => closeFeedbackModal()} />
|
||||
</Stack>
|
||||
</form>
|
||||
<Text style={{ fontSize: 14, marginBottom: 14 }}>Your feedback will help improve the experience.</Text>
|
||||
<TextField
|
||||
styles={{ root: { marginBottom: 14 } }}
|
||||
label="Description"
|
||||
required
|
||||
placeholder="Provide more details"
|
||||
value={description}
|
||||
onChange={(_, newValue) => setDescription(newValue)}
|
||||
multiline
|
||||
rows={3}
|
||||
/>
|
||||
<TextField
|
||||
styles={{ root: { marginBottom: 14 } }}
|
||||
label="Query generated"
|
||||
defaultValue={generatedQuery}
|
||||
readOnly
|
||||
/>
|
||||
<ChoiceGroup
|
||||
styles={{
|
||||
root: {
|
||||
marginBottom: 14,
|
||||
},
|
||||
flexContainer: {
|
||||
selectors: {
|
||||
".ms-ChoiceField-field::before": { marginTop: 4 },
|
||||
".ms-ChoiceField-field::after": { marginTop: 4 },
|
||||
".ms-ChoiceFieldLabel": { paddingLeft: 6 },
|
||||
},
|
||||
},
|
||||
}}
|
||||
label="May we contact you about your feedback?"
|
||||
options={[
|
||||
{ key: "yes", text: "Yes, you may contact me." },
|
||||
{ key: "no", text: "No, do not contact me." },
|
||||
]}
|
||||
selectedKey={isContactAllowed ? "yes" : "no"}
|
||||
onChange={(_, option) => {
|
||||
setIsContactAllowed(option.key === "yes");
|
||||
setContact(option.key === "yes" ? getUserEmail() : "");
|
||||
}}
|
||||
></ChoiceGroup>
|
||||
<Text style={{ fontSize: 12, marginBottom: 14 }}>
|
||||
By pressing submit, your feedback will be used to improve Microsoft products and services. Please see the{" "}
|
||||
{
|
||||
<Link href="https://privacy.microsoft.com/privacystatement" target="_blank">
|
||||
Privacy statement
|
||||
</Link>
|
||||
}{" "}
|
||||
for more information.
|
||||
</Text>
|
||||
{likeQuery && (
|
||||
<Checkbox
|
||||
styles={{ label: { paddingLeft: 0 }, root: { marginBottom: 14 } }}
|
||||
label="Don't show me this next time"
|
||||
checked={doNotShowAgainChecked}
|
||||
onChange={(_, checked) => setDoNotShowAgainChecked(checked)}
|
||||
/>
|
||||
)}
|
||||
<Stack horizontal horizontalAlign="end">
|
||||
<PrimaryButton
|
||||
styles={{ root: { marginRight: 8 } }}
|
||||
onClick={() => {
|
||||
closeFeedbackModal();
|
||||
setHideFeedbackModalForLikedQueries(doNotShowAgainChecked);
|
||||
SubmitFeedback({
|
||||
params: { generatedQuery, likeQuery, description, userPrompt, contact },
|
||||
explorer: explorer,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</PrimaryButton>
|
||||
<DefaultButton onClick={() => closeFeedbackModal()}>Cancel</DefaultButton>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-console */
|
||||
import {
|
||||
Callout,
|
||||
CommandBarButton,
|
||||
@@ -140,7 +141,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
||||
|
||||
// Filter suggested prompts
|
||||
const filteredSuggested = suggestedPrompts.filter((prompt) =>
|
||||
prompt.text.toLowerCase().includes(value.toLowerCase()),
|
||||
prompt.text.toLowerCase().includes(value.toLowerCase())
|
||||
);
|
||||
setFilteredSuggestedPrompts(filteredSuggested);
|
||||
};
|
||||
@@ -150,7 +151,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
||||
const existingHistories = histories.map((history) => history.replace(/\s+/g, " ").trim());
|
||||
|
||||
const updatedHistories = existingHistories.filter(
|
||||
(history) => history.toLowerCase() !== formattedUserPrompt.toLowerCase(),
|
||||
(history) => history.toLowerCase() !== formattedUserPrompt.toLowerCase()
|
||||
);
|
||||
const newHistories = [formattedUserPrompt, ...updatedHistories.slice(0, 2)];
|
||||
|
||||
@@ -237,7 +238,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
||||
const showTeachingBubble = (): void => {
|
||||
if (!inputEdited.current) {
|
||||
setTimeout(() => {
|
||||
if (!inputEdited.current && !isWelcomModalVisible()) {
|
||||
if (!inputEdited.current) {
|
||||
toggleCopilotTeachingBubbleVisible();
|
||||
inputEdited.current = true;
|
||||
}
|
||||
@@ -245,10 +246,6 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
const isWelcomModalVisible = (): boolean => {
|
||||
return localStorage.getItem("hideWelcomeModal") !== "true";
|
||||
};
|
||||
|
||||
const clearFeedback = () => {
|
||||
resetButtonState();
|
||||
resetQueryResults();
|
||||
@@ -301,7 +298,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
||||
setShowSamplePrompts(true);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" && userPrompt) {
|
||||
if (e.key === "Enter") {
|
||||
inputEdited.current = true;
|
||||
startGenerateQueryProcess();
|
||||
}
|
||||
@@ -537,7 +534,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
||||
iconProps={{ iconName: "Copy" }}
|
||||
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
|
||||
>
|
||||
Copy query
|
||||
Copy code
|
||||
</CommandBarButton>
|
||||
<CommandBarButton
|
||||
onClick={() => {
|
||||
@@ -546,11 +543,11 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
||||
iconProps={{ iconName: "Delete" }}
|
||||
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
|
||||
>
|
||||
Delete query
|
||||
Delete code
|
||||
</CommandBarButton>
|
||||
</Stack>
|
||||
)}
|
||||
<WelcomeModal visible={isWelcomModalVisible()} />
|
||||
<WelcomeModal visible={localStorage.getItem("hideWelcomeModal") !== "true"} />
|
||||
{isSamplePromptsOpen && <SamplePrompts sampleProps={sampleProps} />}
|
||||
{query !== "" && query.trim().length !== 0 && (
|
||||
<DeletePopup
|
||||
|
||||
@@ -21,13 +21,8 @@ import * as StringUtility from "../../Shared/StringUtility";
|
||||
export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: QueryCopilotProps): JSX.Element => {
|
||||
const { query, setQuery, selectedQuery, setSelectedQuery, isGeneratingQuery } = useQueryCopilot();
|
||||
|
||||
const cachedCopilotToggleStatus: string = localStorage.getItem(
|
||||
`${userContext.databaseAccount?.id}-queryCopilotToggleStatus`,
|
||||
);
|
||||
const copilotInitialActive: boolean = cachedCopilotToggleStatus
|
||||
? StringUtility.toBoolean(cachedCopilotToggleStatus)
|
||||
: true;
|
||||
const [copilotActive, setCopilotActive] = useState<boolean>(copilotInitialActive);
|
||||
const cachedCopilotToggleStatus = localStorage.getItem(`${userContext.databaseAccount?.id}-queryCopilotToggleStatus`);
|
||||
const [copilotActive, setCopilotActive] = useState<boolean>(StringUtility.toBoolean(cachedCopilotToggleStatus));
|
||||
|
||||
const getCommandbarButtons = (): CommandButtonComponentProps[] => {
|
||||
const executeQueryBtnLabel = selectedQuery ? "Execute Selection" : "Execute Query";
|
||||
@@ -92,7 +87,7 @@ export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: Query
|
||||
<QueryCopilotPromptbar explorer={explorer} toggleCopilot={toggleCopilot}></QueryCopilotPromptbar>
|
||||
)}
|
||||
<Stack className="tabPaneContentContainer">
|
||||
<SplitterLayout percentage={true} vertical={true} primaryIndex={0} primaryMinSize={30} secondaryMinSize={70}>
|
||||
<SplitterLayout vertical={true} primaryIndex={0} primaryMinSize={100} secondaryMinSize={200}>
|
||||
<EditorReact
|
||||
language={"sql"}
|
||||
content={query}
|
||||
|
||||
@@ -166,7 +166,7 @@ export const OnExecuteQueryClick = async (): Promise<void> => {
|
||||
|
||||
export const QueryDocumentsPerPage = async (
|
||||
firstItemIndex: number,
|
||||
queryIterator: MinimalQueryIterator,
|
||||
queryIterator: MinimalQueryIterator
|
||||
): Promise<void> => {
|
||||
try {
|
||||
useQueryCopilot.getState().setIsExecuting(true);
|
||||
@@ -174,8 +174,7 @@ export const QueryDocumentsPerPage = async (
|
||||
useTabs.getState().setIsQueryErrorThrown(false);
|
||||
const queryResults: QueryResults = await queryPagesUntilContentPresent(
|
||||
firstItemIndex,
|
||||
async (firstItemIndex: number) =>
|
||||
queryDocumentsPage(QueryCopilotSampleContainerId, queryIterator, firstItemIndex),
|
||||
async (firstItemIndex: number) => queryDocumentsPage(QueryCopilotSampleContainerId, queryIterator, firstItemIndex)
|
||||
);
|
||||
|
||||
useQueryCopilot.getState().setQueryResults(queryResults);
|
||||
@@ -186,7 +185,7 @@ export const QueryDocumentsPerPage = async (
|
||||
});
|
||||
} catch (error) {
|
||||
const isCopilotActive = StringUtility.toBoolean(
|
||||
localStorage.getItem(`${userContext.databaseAccount?.id}-queryCopilotToggleStatus`),
|
||||
localStorage.getItem(`${userContext.databaseAccount?.id}-queryCopilotToggleStatus`)
|
||||
);
|
||||
const errorMessage = getErrorMessage(error);
|
||||
traceFailure(Action.ExecuteQueryGeneratedFromQueryCopilot, {
|
||||
|
||||
@@ -17,37 +17,6 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
|
||||
}
|
||||
}
|
||||
>
|
||||
<QueryCopilotPromptbar
|
||||
explorer={
|
||||
Explorer {
|
||||
"_isInitializingNotebooks": false,
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||
"isTabsContentExpanded": [Function],
|
||||
"onRefreshDatabasesKeyPress": [Function],
|
||||
"onRefreshResourcesClick": [Function],
|
||||
"phoenixClient": PhoenixClient {
|
||||
"armResourceId": undefined,
|
||||
"retryOptions": Object {
|
||||
"maxTimeout": 5000,
|
||||
"minTimeout": 5000,
|
||||
"retries": 3,
|
||||
},
|
||||
},
|
||||
"provideFeedbackEmail": [Function],
|
||||
"queriesClient": QueriesClient {
|
||||
"container": [Circular],
|
||||
},
|
||||
"refreshNotebookList": [Function],
|
||||
"resourceTree": ResourceTreeAdapter {
|
||||
"container": [Circular],
|
||||
"copyNotebook": [Function],
|
||||
"parameters": [Function],
|
||||
},
|
||||
}
|
||||
}
|
||||
toggleCopilot={[Function]}
|
||||
/>
|
||||
<Stack
|
||||
className="tabPaneContentContainer"
|
||||
>
|
||||
@@ -56,10 +25,10 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] =
|
||||
onDragEnd={null}
|
||||
onDragStart={null}
|
||||
onSecondaryPaneSizeChange={null}
|
||||
percentage={true}
|
||||
percentage={false}
|
||||
primaryIndex={0}
|
||||
primaryMinSize={30}
|
||||
secondaryMinSize={70}
|
||||
primaryMinSize={100}
|
||||
secondaryMinSize={200}
|
||||
vertical={true}
|
||||
>
|
||||
<EditorReact
|
||||
|
||||
@@ -346,22 +346,6 @@ export default class DocumentsTab extends TabsBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query first page of documents
|
||||
* Select and query first document and display content
|
||||
*/
|
||||
private async autoPopulateContent() {
|
||||
// reset iterator
|
||||
this._documentsIterator = this.createIterator();
|
||||
// load documents
|
||||
await this.loadNextPage();
|
||||
|
||||
// Select first document and load content
|
||||
if (this.documentIds().length > 0) {
|
||||
this.documentIds()[0].click();
|
||||
}
|
||||
}
|
||||
|
||||
public onShowFilterClick(): Q.Promise<any> {
|
||||
this.isFilterCreated(true);
|
||||
this.isFilterExpanded(true);
|
||||
@@ -396,7 +380,10 @@ export default class DocumentsTab extends TabsBase {
|
||||
this.documentIds([]);
|
||||
|
||||
try {
|
||||
await this.autoPopulateContent();
|
||||
// reset iterator
|
||||
this._documentsIterator = this.createIterator();
|
||||
// load documents
|
||||
await this.loadNextPage();
|
||||
// collapse filter
|
||||
this.appliedFilter(this.filterContent());
|
||||
this.isFilterExpanded(false);
|
||||
@@ -419,11 +406,6 @@ export default class DocumentsTab extends TabsBase {
|
||||
this.queryAbortController.abort();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO Doesn't seem to be used: remove?
|
||||
* @param clickedDocumentId
|
||||
* @returns
|
||||
*/
|
||||
public onDocumentIdClick(clickedDocumentId: DocumentId): Q.Promise<any> {
|
||||
if (this.editorState() !== ViewModels.DocumentExplorerState.noDocumentSelected) {
|
||||
return Q();
|
||||
@@ -642,7 +624,8 @@ export default class DocumentsTab extends TabsBase {
|
||||
|
||||
if (!this._documentsIterator) {
|
||||
try {
|
||||
await this.autoPopulateContent();
|
||||
this._documentsIterator = this.createIterator();
|
||||
await this.loadNextPage();
|
||||
} catch (error) {
|
||||
if (this.onLoadStartKey != null && this.onLoadStartKey != undefined) {
|
||||
TelemetryProcessor.traceFailure(
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
jest.mock("../../../hooks/useDirectories");
|
||||
import "@testing-library/jest-dom";
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import { extractFeatures } from "Platform/Hosted/extractFeatures";
|
||||
import { updateUserContext, userContext } from "UserContext";
|
||||
import React from "react";
|
||||
import { ConnectExplorer } from "./ConnectExplorer";
|
||||
|
||||
@@ -18,24 +16,3 @@ it("shows the connect form", () => {
|
||||
fireEvent.click(screen.getByText("Connect to your account with connection string"));
|
||||
expect(screen.queryByPlaceholderText("Please enter a connection string")).toBeDefined();
|
||||
});
|
||||
|
||||
it("hides the connection string link when feature.disableConnectionStringLogin is true", () => {
|
||||
const connectionString = "fakeConnectionString";
|
||||
const login = jest.fn();
|
||||
const setConnectionString = jest.fn();
|
||||
const setEncryptedToken = jest.fn();
|
||||
const setAuthType = jest.fn();
|
||||
const oldFeatures = userContext.features;
|
||||
|
||||
const params = new URLSearchParams({
|
||||
"feature.disableConnectionStringLogin": "true",
|
||||
});
|
||||
|
||||
const testFeatures = extractFeatures(params);
|
||||
updateUserContext({ features: testFeatures });
|
||||
|
||||
render(<ConnectExplorer {...{ login, setEncryptedToken, setAuthType, connectionString, setConnectionString }} />);
|
||||
expect(screen.queryByPlaceholderText("Connect to your account with connection string")).toBeNull();
|
||||
|
||||
updateUserContext({ features: oldFeatures });
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useBoolean } from "@fluentui/react-hooks";
|
||||
import { userContext } from "UserContext";
|
||||
import * as React from "react";
|
||||
import ConnectImage from "../../../../images/HdeConnectCosmosDB.svg";
|
||||
import ErrorImage from "../../../../images/error.svg";
|
||||
@@ -38,7 +37,6 @@ export const ConnectExplorer: React.FunctionComponent<Props> = ({
|
||||
setConnectionString,
|
||||
}: Props) => {
|
||||
const [isFormVisible, { setTrue: showForm }] = useBoolean(false);
|
||||
const enableConnectionStringLogin = !userContext.features.disableConnectionStringLogin;
|
||||
|
||||
return (
|
||||
<div id="connectExplorer" className="connectExplorerContainer" style={{ display: "flex" }}>
|
||||
@@ -48,7 +46,7 @@ export const ConnectExplorer: React.FunctionComponent<Props> = ({
|
||||
<img src={ConnectImage} alt="Azure Cosmos DB" />
|
||||
</p>
|
||||
<p className="welcomeText">Welcome to Azure Cosmos DB</p>
|
||||
{isFormVisible && enableConnectionStringLogin ? (
|
||||
{isFormVisible ? (
|
||||
<form
|
||||
id="connectWithConnectionString"
|
||||
onSubmit={async (event) => {
|
||||
@@ -91,11 +89,9 @@ export const ConnectExplorer: React.FunctionComponent<Props> = ({
|
||||
) : (
|
||||
<div id="connectWithAad">
|
||||
<input className="filterbtnstyle" type="button" value="Sign In" onClick={login} />
|
||||
{enableConnectionStringLogin && (
|
||||
<p className="switchConnectTypeText" onClick={showForm}>
|
||||
Connect to your account with connection string
|
||||
</p>
|
||||
)}
|
||||
<p className="switchConnectTypeText" onClick={showForm}>
|
||||
Connect to your account with connection string
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,6 @@ export type Features = {
|
||||
readonly enableCopilotFullSchema: boolean;
|
||||
readonly copilotChatFixedMonacoEditorHeight: boolean;
|
||||
readonly enablePriorityBasedExecution: boolean;
|
||||
readonly disableConnectionStringLogin: boolean;
|
||||
|
||||
// can be set via both flight and feature flag
|
||||
autoscaleDefault: boolean;
|
||||
@@ -115,7 +114,6 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
|
||||
enableCopilotFullSchema: "true" === get("enablecopilotfullschema", "true"),
|
||||
copilotChatFixedMonacoEditorHeight: "true" === get("copilotchatfixedmonacoeditorheight"),
|
||||
enablePriorityBasedExecution: "true" === get("enableprioritybasedexecution"),
|
||||
disableConnectionStringLogin: "true" === get("disableconnectionstringlogin"),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,15 @@ import { createUri } from "Common/UrlUtility";
|
||||
import { FabricMessage } from "Contracts/FabricContract";
|
||||
import Explorer from "Explorer/Explorer";
|
||||
import { useSelectedNode } from "Explorer/useSelectedNode";
|
||||
import { fetchEncryptedToken } from "Platform/Hosted/Components/ConnectExplorer";
|
||||
import { getNetworkSettingsWarningMessage } from "Utils/NetworkUtility";
|
||||
import { fetchAccessData } from "hooks/usePortalAccessToken";
|
||||
import { ReactTabKind, useTabs } from "hooks/useTabs";
|
||||
import { useEffect, useState } from "react";
|
||||
import { AuthType } from "../AuthType";
|
||||
import { AccountKind, Flights } from "../Common/Constants";
|
||||
import { normalizeArmEndpoint } from "../Common/EnvironmentUtility";
|
||||
import { handleCachedDataMessage, sendMessage, sendReadyMessage } from "../Common/MessageHandler";
|
||||
import { sendMessage, sendReadyMessage } from "../Common/MessageHandler";
|
||||
import { Platform, configContext, updateConfigContext } from "../ConfigContext";
|
||||
import { ActionType, DataExplorerAction, TabKind } from "../Contracts/ActionContracts";
|
||||
import { MessageTypes } from "../Contracts/ExplorerContracts";
|
||||
@@ -105,7 +107,23 @@ async function configureFabric(): Promise<Explorer> {
|
||||
|
||||
switch (data.type) {
|
||||
case "initialize": {
|
||||
explorer = await configureWithFabric(data.message.endpoint);
|
||||
// TODO For now, retrieve info from session storage. Replace with info injected into Data Explorer
|
||||
const connectionString = data.connectionString ?? sessionStorage.getItem("connectionString");
|
||||
if (!connectionString) {
|
||||
console.error("No connection string found in session storage");
|
||||
return undefined;
|
||||
}
|
||||
const encryptedToken = await fetchEncryptedToken(connectionString);
|
||||
// TODO Duplicated from useTokenMetadata
|
||||
const encryptedTokenMetadata = await fetchAccessData(encryptedToken);
|
||||
|
||||
const hostedConfig: EncryptedToken = {
|
||||
authType: AuthType.EncryptedToken,
|
||||
encryptedToken,
|
||||
encryptedTokenMetadata,
|
||||
};
|
||||
|
||||
explorer = await configureWithEncryptedToken(hostedConfig);
|
||||
resolve(explorer);
|
||||
break;
|
||||
}
|
||||
@@ -148,10 +166,6 @@ async function configureFabric(): Promise<Explorer> {
|
||||
|
||||
break;
|
||||
}
|
||||
case "authorizationToken": {
|
||||
handleCachedDataMessage(data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.error(`Unknown Fabric message type: ${JSON.stringify(data)}`);
|
||||
break;
|
||||
@@ -301,25 +315,6 @@ function configureHostedWithResourceToken(config: ResourceToken): Explorer {
|
||||
return explorer;
|
||||
}
|
||||
|
||||
function configureWithFabric(documentEndpoint: string): Explorer {
|
||||
updateUserContext({
|
||||
authType: AuthType.ConnectionString,
|
||||
databaseAccount: {
|
||||
id: "",
|
||||
location: "",
|
||||
type: "",
|
||||
name: "Mounted",
|
||||
kind: AccountKind.Default,
|
||||
properties: {
|
||||
documentEndpoint,
|
||||
},
|
||||
},
|
||||
});
|
||||
const explorer = new Explorer();
|
||||
setTimeout(() => explorer.refreshAllDatabases(), 0);
|
||||
return explorer;
|
||||
}
|
||||
|
||||
function configureWithEncryptedToken(config: EncryptedToken): Explorer {
|
||||
const apiExperience = DefaultExperienceUtility.getDefaultExperienceFromApiKind(config.encryptedTokenMetadata.apiKind);
|
||||
updateUserContext({
|
||||
|
||||
@@ -128,7 +128,7 @@ export const useQueryCopilot: QueryCopilotStore = create((set) => ({
|
||||
|
||||
openFeedbackModal: (generatedQuery: string, likeQuery: boolean, userPrompt: string) =>
|
||||
set({ generatedQuery, likeQuery, userPrompt, showFeedbackModal: true }),
|
||||
closeFeedbackModal: () => set({ showFeedbackModal: false }),
|
||||
closeFeedbackModal: () => set({ generatedQuery: "", likeQuery: false, userPrompt: "", showFeedbackModal: false }),
|
||||
setHideFeedbackModalForLikedQueries: (hideFeedbackModalForLikedQueries: boolean) =>
|
||||
set({ hideFeedbackModalForLikedQueries }),
|
||||
refreshCorrelationId: () => set({ correlationId: guid() }),
|
||||
|
||||
@@ -6,15 +6,6 @@
|
||||
<mimeMap fileExtension="woff" mimeType="application/font-woff" />
|
||||
</staticContent>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="AAD-Redirect" stopProcessing="true">
|
||||
<match url="^aad" ignoreCase="true"/>
|
||||
<conditions>
|
||||
<add input="{HTTP_HOST}" pattern="^cosmos.azure.com" />
|
||||
</conditions>
|
||||
<action type="Redirect" url="/?feature.enableAadDataPlane=true&feature.disableConnectionStringLogin=true" redirectType="Permanent" />
|
||||
</rule>
|
||||
</rules>
|
||||
<outboundRules>
|
||||
<rule name="Strict-Transport-Security" enabled="true">
|
||||
<match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
|
||||
|
||||
Reference in New Issue
Block a user