Compare commits

..

1 Commits

Author SHA1 Message Date
Steve Faulkner
e41230e8c4 WIP 2020-12-26 20:01:42 -06:00
50 changed files with 2629 additions and 4891 deletions

View File

@@ -42,7 +42,6 @@ src/Contracts/ViewModels.ts
src/Controls/Heatmap/Heatmap.test.ts src/Controls/Heatmap/Heatmap.test.ts
src/Controls/Heatmap/Heatmap.ts src/Controls/Heatmap/Heatmap.ts
src/Controls/Heatmap/HeatmapDatatypes.ts src/Controls/Heatmap/HeatmapDatatypes.ts
src/Definitions/adal.d.ts
src/Definitions/datatables.d.ts src/Definitions/datatables.d.ts
src/Definitions/gif.d.ts src/Definitions/gif.d.ts
src/Definitions/globals.d.ts src/Definitions/globals.d.ts

View File

@@ -1,7 +0,0 @@
# Why?
This adds a mock module for `canvas`. Nteract has a ignored require and undeclared dependency on this module. `cavnas` is a server side node module and is not used in browser side code for nteract.
Installing it locally (`npm install canvas`) will resolve the problem, but it is a native module so it is flaky depending on the system, node version, processor arch, etc. This module provides a simpler, more robust solution.
Remove this workaround if [this bug](https://github.com/nteract/any-vega/issues/2) ever gets resolved

View File

@@ -1 +0,0 @@
module.exports = {}

View File

@@ -1,11 +0,0 @@
{
"name": "canvas",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

1963
externals/adal.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,8 @@
/******************************************************************************/ /******************************************************************************/
@font-face { @font-face {
font-family: wf_segoe-ui_normal; font-family: wf_segoe-ui_normal;
src: url("../../fonts/segoe-ui/west-european/normal/latest.woff"); src: url('../../fonts/segoe-ui/west-european/normal/latest.woff');
} }
@DataExplorerFont: wf_segoe-ui_normal, "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif; @DataExplorerFont: wf_segoe-ui_normal, "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif;
@@ -20,26 +20,26 @@
COLORS COLORS
/******************************************************************************/ /******************************************************************************/
@AccentMediumHigh: #0058ad; @AccentMediumHigh: #0058AD;
@AccentMedium: #004e87; @AccentMedium: #004E87;
@AccentHigh: #1ebaed; @AccentHigh: #1EBAED;
@AccentExtraHigh: #55b3ff; @AccentExtraHigh: #55B3FF;
@AccentLow: #edf6ff; @AccentLow: #EDF6FF;
@AccentMediumLow: #ddeefe; @AccentMediumLow: #DDEEFE;
@AccentLight: #eef7ff; @AccentLight: #EEF7FF;
@AccentExtra: #ddf0ff; @AccentExtra: #DDF0FF;
@SelectionHigh: #b91f26; @SelectionHigh: #B91F26;
@BaseLight: #ffffff; @BaseLight: #FFFFFF;
@BaseDark: #000000; @BaseDark: #000000;
@NotificationLow: #fff4ce; @NotificationLow: #FFF4CE;
@NotificationHigh: #f9e9b0; @NotificationHigh: #F9E9B0;
@Purple1: #8a2da5; @Purple1: #8A2DA5;
@Dirty: #9b4f96; @Dirty: #9b4f96;
@BaseLow: #f2f2f2; @BaseLow: #F2F2F2;
@BaseMediumLow: #e6e6e6; @BaseMediumLow: #E6E6E6;
@BaseMedium: #cccccc; @BaseMedium: #CCCCCC;
@BaseMediumHigh: #767676; @BaseMediumHigh: #767676;
@BaseHigh: #393939; @BaseHigh: #393939;
@@ -53,7 +53,7 @@
@ErrorColor: @SelectionHigh; @ErrorColor: @SelectionHigh;
@SelectionColor: #3074b0; @SelectionColor: #3074B0;
@FocusColor: #605e5c; @FocusColor: #605e5c;
@@ -80,7 +80,7 @@
@ImgWidth: 14px; @ImgWidth: 14px;
@ImgHeight: 14px; @ImgHeight: 14px;
@toggleFontWeight: 700; @toggleFontWeight:700;
//Resource Tree //Resource Tree
@TreeLineHeight: 17px; @TreeLineHeight: 17px;
@@ -144,16 +144,16 @@
/**********************************************************************************/ /**********************************************************************************/
.flex-display(@display: flex) { .flex-display(@display: flex) {
display: ~"-webkit-@{display}"; display: ~"-webkit-@{display}";
display: ~"-ms-@{display}box"; // IE10 uses -ms-flexbox display: ~"-ms-@{display}box"; // IE10 uses -ms-flexbox
display: ~"-ms-@{display}"; // IE11 display: ~"-ms-@{display}"; // IE11
display: @display; display: @display;
} }
.flex-direction(@direction: column) { .flex-direction(@direction: column) {
-webkit-flex-direction: @direction; -webkit-flex-direction: @direction;
-ms-flex-direction: @direction; -ms-flex-direction: @direction;
flex-direction: @direction; flex-direction: @direction;
} }
/************************************************************************************* /*************************************************************************************
@@ -161,31 +161,32 @@
**************************************************************************************/ **************************************************************************************/
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
.selectedRadio, .selectedRadio,
.selectedRadio:hover, .selectedRadio:hover,
.selectedRadio:active, .selectedRadio:active,
.selectedRadio.dirty, .selectedRadio.dirty,
.tab [type="radio"]:checked ~ label, .tab [type=radio]:checked ~ label,
.tab [type="radio"]:checked ~ label:hover { .tab [type=radio]:checked ~ label:hover {
-ms-high-contrast-adjust: none; -ms-high-contrast-adjust: none;
-webkit-text-fill-color: HighlightText; -webkit-text-fill-color: HighlightText;
color: HighlightText; color: HighlightText;
border-color: HighlightText; border-color: HighlightText;
background-color: Highlight; background-color: Highlight;
} }
.queryMetricsSummaryTuple { .queryMetricsSummaryTuple {
th,
td { th, td {
&:nth-child(2) {
width: @IETableDataWidth; &:nth-child(2) {
} width: @IETableDataWidth;
}
&:nth-child(3) {
width: 50%; &:nth-child(3) {
} width: 50%;
}
}
} }
}
} }
/******************************************************************************************** /********************************************************************************************
@@ -193,15 +194,15 @@
*********************************************************************************************/ *********************************************************************************************/
.hover() { .hover() {
background-color: @AccentLight; background-color: @AccentLight;
} }
.active() { .active() {
background-color: @AccentExtra; background-color: @AccentExtra;
} }
.focus() { .focus() {
outline: 1px dashed @FocusColor; outline: 1px dashed @FocusColor;
} }
/************************************************************************************************ /************************************************************************************************
@@ -211,87 +212,63 @@
@ToggleWidth: 180px; @ToggleWidth: 180px;
.toggleSwitch() { .toggleSwitch() {
max-width: 100%; max-width: 100%;
margin-bottom: @SmallSpace; margin-bottom: @SmallSpace;
padding: @SmallSpace; padding: @SmallSpace;
cursor: pointer; cursor: pointer;
color: @BaseHigh; color: @BaseHigh;
font-weight: 400; font-weight: 400;
font-size: @mediumFontSize; font-size: @mediumFontSize;
font-family: @DataExplorerFont; font-family: @DataExplorerFont;
} }
.selectedToggle() { .selectedToggle() {
border-bottom: 2px solid @BaseHigh; border-bottom: 2px solid @BaseHigh;
} }
.unselectedToggle() { .unselectedToggle() {
color: @AccentMediumHigh; color: @AccentMediumHigh;
} }
/******************************************************************************************************** /********************************************************************************************************
Common Data Explorer Icons Common Data Explorer Icons
*********************************************************************************************************/ *********************************************************************************************************/
.dataExplorerIcons() { .dataExplorerIcons() {
cursor: pointer; cursor: pointer;
width: @ImgWidth; width: @ImgWidth;
height: @ImgHeight; height: @ImgHeight;
} }
/********************************************************************************************************* /*********************************************************************************************************
Info Tooltip Info Tooltip
**********************************************************************************************************/ **********************************************************************************************************/
.infoTooltip() { .infoTooltip() {
position: relative; position: relative;
display: inline-block; display: inline-block;
} }
.tooltipText(@textColor: @BaseLight, @backgroundColor: @BaseHigh) { .tooltipText(@textColor: @BaseLight, @backgroundColor: @BaseHigh) {
visibility: hidden; visibility: hidden;
background-color: @backgroundColor; background-color: @backgroundColor;
color: @textColor; color: @textColor;
position: absolute; position: absolute;
z-index: 1; z-index: 1;
left: @MediumSpace; left: @MediumSpace;
padding: @MediumSpace; padding: @MediumSpace;
} }
.tooltipTextAfter(@color: @BaseDark) { .tooltipTextAfter(@color: @BaseDark) {
content: ""; content: "";
position: absolute; position: absolute;
right: 100%; right: 100%;
border-style: solid; border-style: solid;
border-color: transparent @color transparent transparent; border-color: transparent @color transparent transparent;
left: 0px; left: 0px;
width: 0; width: 0;
height: 0; height: 0;
border-color: @InfoPointerColor transparent; border-color: @InfoPointerColor transparent;
} }
.tooltipVisible() { .tooltipVisible() {
visibility: visible; visibility: visible;
}
.inputTooltip() {
position: relative;
}
.inputTooltipText(@textColor: @BaseLight, @backgroundColor: @BaseHigh) {
background-color: @backgroundColor;
color: @textColor;
position: absolute;
z-index: 1;
padding: @MediumSpace;
}
.inputTooltipTextAfter(@color: @BaseDark) {
content: "";
position: absolute;
right: 100%;
border-style: solid;
border-color: transparent @color transparent transparent;
left: 10px;
width: 0;
height: 0;
border-color: @InfoPointerColor transparent;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,20 @@
@import "./Common/Constants"; @import "./Common/Constants";
.main {
width: 100%;
float: left;
transition: all .0s ease-in-out;
-ms-transition: all 0s ease-in-out;
-webkit-transition: all 0s ease-in-out;
-moz-transition: all .0s ease-in-out;
height: 100%;
background-color: white;
border-left: 0px solid white;
}
.resourceTree { .resourceTree {
height: 100%; height: 100%;
flex: 0 0 auto; flex: 0 0 auto;
.main {
height: 100%;
}
} }
.resourceTreeScroll { .resourceTreeScroll {

247
package-lock.json generated
View File

@@ -275,6 +275,27 @@
} }
} }
}, },
"@azure/msal-browser": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.8.0.tgz",
"integrity": "sha512-I6n7EQnwsZXgKPOLlS5X48jhzUNUFwMVm180wDBA/pwEkUy8ei6zWiPMBfWaMSxz9uNx9WHaEhgAyhJy0ze3AQ==",
"requires": {
"@azure/msal-common": "^2.0.0"
}
},
"@azure/msal-common": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-2.0.0.tgz",
"integrity": "sha512-d1RNcJb+P1EGzMHtgbZoVlHLQWjlVfr504jywNk9YEfoq8Hw3BxJ0wepu+1w0hc64D8zG0wljcvHaIH1jTn2SA==",
"requires": {
"debug": "^4.1.1"
}
},
"@azure/msal-react": {
"version": "1.0.0-alpha.1",
"resolved": "https://registry.npmjs.org/@azure/msal-react/-/msal-react-1.0.0-alpha.1.tgz",
"integrity": "sha512-8BftMP1DyXf7/Fa7mxi14/fmHBdDGDUONmE8sm1T6w7ERJyY1RN7PZgdnUOcYcqj2xMnxfz9++8HsrzMrtMc0Q=="
},
"@babel/code-frame": { "@babel/code-frame": {
"version": "7.10.4", "version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
@@ -5393,6 +5414,11 @@
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
"integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==" "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q=="
}, },
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"abort-controller": { "abort-controller": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -5443,12 +5469,6 @@
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA=="
}, },
"adal-angular": {
"version": "1.0.15",
"resolved": "https://registry.npmjs.org/adal-angular/-/adal-angular-1.0.15.tgz",
"integrity": "sha1-8qnvgvNYxEToMUKs5l0yJ6RBBDs=",
"dev": true
},
"agent-base": { "agent-base": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -5636,7 +5656,6 @@
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
"optional": true,
"requires": { "requires": {
"delegates": "^1.0.0", "delegates": "^1.0.0",
"readable-stream": "^2.0.6" "readable-stream": "^2.0.6"
@@ -6879,7 +6898,14 @@
"dev": true "dev": true
}, },
"canvas": { "canvas": {
"version": "file:canvas" "version": "2.6.1",
"resolved": "https://registry.npmjs.org/canvas/-/canvas-2.6.1.tgz",
"integrity": "sha512-S98rKsPcuhfTcYbtF53UIJhcbgIAK533d1kJKMwsMwAIFgfd58MOyxRud3kktlzWiEkFliaJtvyZCBtud/XVEA==",
"requires": {
"nan": "^2.14.0",
"node-pre-gyp": "^0.11.0",
"simple-get": "^3.0.3"
}
}, },
"capture-exit": { "capture-exit": {
"version": "2.0.0", "version": "2.0.0",
@@ -7443,8 +7469,7 @@
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
"optional": true
}, },
"constants-browserify": { "constants-browserify": {
"version": "1.0.0", "version": "1.0.0",
@@ -8425,7 +8450,6 @@
"version": "4.2.1", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
"optional": true,
"requires": { "requires": {
"mimic-response": "^2.0.0" "mimic-response": "^2.0.0"
} }
@@ -8451,8 +8475,7 @@
"deep-extend": { "deep-extend": {
"version": "0.6.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
"optional": true
}, },
"deep-is": { "deep-is": {
"version": "0.1.3", "version": "0.1.3",
@@ -8644,8 +8667,7 @@
"delegates": { "delegates": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
"optional": true
}, },
"depd": { "depd": {
"version": "1.1.2", "version": "1.1.2",
@@ -8681,8 +8703,7 @@
"detect-libc": { "detect-libc": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
"optional": true
}, },
"detect-newline": { "detect-newline": {
"version": "2.1.0", "version": "2.1.0",
@@ -10668,6 +10689,14 @@
"universalify": "^0.1.0" "universalify": "^0.1.0"
} }
}, },
"fs-minipass": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
"integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
"requires": {
"minipass": "^2.6.0"
}
},
"fs-observable": { "fs-observable": {
"version": "4.1.14", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/fs-observable/-/fs-observable-4.1.14.tgz", "resolved": "https://registry.npmjs.org/fs-observable/-/fs-observable-4.1.14.tgz",
@@ -10809,7 +10838,6 @@
"version": "2.7.4", "version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"optional": true,
"requires": { "requires": {
"aproba": "^1.0.3", "aproba": "^1.0.3",
"console-control-strings": "^1.0.0", "console-control-strings": "^1.0.0",
@@ -10824,14 +10852,12 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
"optional": true
}, },
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@@ -10840,7 +10866,6 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@@ -10851,7 +10876,6 @@
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@@ -11341,8 +11365,7 @@
"has-unicode": { "has-unicode": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
"optional": true
}, },
"has-value": { "has-value": {
"version": "1.0.0", "version": "1.0.0",
@@ -11824,6 +11847,14 @@
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw=="
}, },
"ignore-walk": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
"integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
"requires": {
"minimatch": "^3.0.4"
}
},
"image-size": { "image-size": {
"version": "0.5.5", "version": "0.5.5",
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
@@ -15528,8 +15559,7 @@
"mimic-response": { "mimic-response": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA=="
"optional": true
}, },
"min-document": { "min-document": {
"version": "2.19.0", "version": "2.19.0",
@@ -15586,6 +15616,15 @@
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
}, },
"minipass": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
}
},
"minipass-collect": { "minipass-collect": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
@@ -15655,6 +15694,14 @@
} }
} }
}, },
"minizlib": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
"integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
"requires": {
"minipass": "^2.9.0"
}
},
"mississippi": { "mississippi": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
@@ -15829,8 +15876,7 @@
"nan": { "nan": {
"version": "2.14.2", "version": "2.14.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ=="
"optional": true
}, },
"nanomatch": { "nanomatch": {
"version": "1.2.13", "version": "1.2.13",
@@ -15880,6 +15926,26 @@
"semver": "^5.4.1" "semver": "^5.4.1"
} }
}, },
"needle": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz",
"integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==",
"requires": {
"debug": "^3.2.6",
"iconv-lite": "^0.4.4",
"sax": "^1.2.4"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
}
}
},
"negotiator": { "negotiator": {
"version": "0.6.2", "version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@@ -16048,6 +16114,41 @@
"which": "^1.3.0" "which": "^1.3.0"
} }
}, },
"node-pre-gyp": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz",
"integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==",
"requires": {
"detect-libc": "^1.0.2",
"mkdirp": "^0.5.1",
"needle": "^2.2.1",
"nopt": "^4.0.1",
"npm-packlist": "^1.1.6",
"npmlog": "^4.0.2",
"rc": "^1.2.7",
"rimraf": "^2.6.1",
"semver": "^5.3.0",
"tar": "^4"
},
"dependencies": {
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"requires": {
"minimist": "^1.2.5"
}
},
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"requires": {
"glob": "^7.1.3"
}
}
}
},
"node-releases": { "node-releases": {
"version": "1.1.66", "version": "1.1.66",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.66.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.66.tgz",
@@ -16060,6 +16161,15 @@
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=",
"optional": true "optional": true
}, },
"nopt": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
"integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
"requires": {
"abbrev": "1",
"osenv": "^0.1.4"
}
},
"normalize-package-data": { "normalize-package-data": {
"version": "2.5.0", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -16084,6 +16194,29 @@
"resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz", "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz",
"integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==" "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
}, },
"npm-bundled": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
"integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
"requires": {
"npm-normalize-package-bin": "^1.0.1"
}
},
"npm-normalize-package-bin": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
},
"npm-packlist": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
"integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
"requires": {
"ignore-walk": "^3.0.1",
"npm-bundled": "^1.0.1",
"npm-normalize-package-bin": "^1.0.1"
}
},
"npm-run-path": { "npm-run-path": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -16096,7 +16229,6 @@
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"optional": true,
"requires": { "requires": {
"are-we-there-yet": "~1.1.2", "are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0", "console-control-strings": "~1.1.0",
@@ -16488,8 +16620,7 @@
"os-homedir": { "os-homedir": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
"dev": true
}, },
"os-locale": { "os-locale": {
"version": "1.4.0", "version": "1.4.0",
@@ -16508,6 +16639,20 @@
"windows-release": "^3.1.0" "windows-release": "^3.1.0"
} }
}, },
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"osenv": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"requires": {
"os-homedir": "^1.0.0",
"os-tmpdir": "^1.0.0"
}
},
"p-defer": { "p-defer": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
@@ -17560,7 +17705,6 @@
"version": "1.2.8", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"optional": true,
"requires": { "requires": {
"deep-extend": "^0.6.0", "deep-extend": "^0.6.0",
"ini": "~1.3.0", "ini": "~1.3.0",
@@ -18987,14 +19131,12 @@
"simple-concat": { "simple-concat": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
"optional": true
}, },
"simple-get": { "simple-get": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
"integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
"optional": true,
"requires": { "requires": {
"decompress-response": "^4.2.0", "decompress-response": "^4.2.0",
"once": "^1.3.1", "once": "^1.3.1",
@@ -19986,6 +20128,30 @@
"integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
"dev": true "dev": true
}, },
"tar": {
"version": "4.4.13",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
"integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
"minipass": "^2.8.6",
"minizlib": "^1.2.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.2",
"yallist": "^3.0.3"
},
"dependencies": {
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"requires": {
"minimist": "^1.2.5"
}
}
}
},
"tar-fs": { "tar-fs": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
@@ -22041,7 +22207,6 @@
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"optional": true,
"requires": { "requires": {
"string-width": "^1.0.2 || 2" "string-width": "^1.0.2 || 2"
}, },
@@ -22049,14 +22214,12 @@
"ansi-regex": { "ansi-regex": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
"optional": true
}, },
"string-width": { "string-width": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"optional": true,
"requires": { "requires": {
"is-fullwidth-code-point": "^2.0.0", "is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0" "strip-ansi": "^4.0.0"
@@ -22066,7 +22229,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"optional": true,
"requires": { "requires": {
"ansi-regex": "^3.0.0" "ansi-regex": "^3.0.0"
} }
@@ -22236,8 +22398,7 @@
"yallist": { "yallist": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
"dev": true
}, },
"yargs": { "yargs": {
"version": "13.3.2", "version": "13.3.2",

View File

@@ -6,8 +6,10 @@
"dependencies": { "dependencies": {
"@azure/arm-cosmosdb": "9.1.0", "@azure/arm-cosmosdb": "9.1.0",
"@azure/cosmos": "3.9.0", "@azure/cosmos": "3.9.0",
"@azure/identity": "1.1.0",
"@azure/cosmos-language-service": "0.0.5", "@azure/cosmos-language-service": "0.0.5",
"@azure/identity": "1.1.0",
"@azure/msal-browser": "2.8.0",
"@azure/msal-react": "1.0.0-alpha.1",
"@jupyterlab/services": "6.0.0-rc.2", "@jupyterlab/services": "6.0.0-rc.2",
"@jupyterlab/terminal": "3.0.0-rc.2", "@jupyterlab/terminal": "3.0.0-rc.2",
"@microsoft/applicationinsights-web": "2.5.9", "@microsoft/applicationinsights-web": "2.5.9",
@@ -44,7 +46,7 @@
"applicationinsights": "1.8.0", "applicationinsights": "1.8.0",
"babel-polyfill": "6.26.0", "babel-polyfill": "6.26.0",
"bootstrap": "3.4.1", "bootstrap": "3.4.1",
"canvas": "file:./canvas", "canvas": "2.6.1",
"clean-webpack-plugin": "0.1.19", "clean-webpack-plugin": "0.1.19",
"copy-webpack-plugin": "6.0.2", "copy-webpack-plugin": "6.0.2",
"crossroads": "0.12.2", "crossroads": "0.12.2",
@@ -128,7 +130,6 @@
"@types/webfontloader": "1.6.29", "@types/webfontloader": "1.6.29",
"@typescript-eslint/eslint-plugin": "4.0.1", "@typescript-eslint/eslint-plugin": "4.0.1",
"@typescript-eslint/parser": "4.0.1", "@typescript-eslint/parser": "4.0.1",
"adal-angular": "1.0.15",
"axe-puppeteer": "1.1.0", "axe-puppeteer": "1.1.0",
"babel-jest": "24.9.0", "babel-jest": "24.9.0",
"babel-loader": "8.1.0", "babel-loader": "8.1.0",

View File

@@ -132,7 +132,6 @@ export class Features {
export class Flights { export class Flights {
public static readonly SettingsV2 = "settingsv2"; public static readonly SettingsV2 = "settingsv2";
public static readonly MongoIndexEditor = "mongoindexeditor"; public static readonly MongoIndexEditor = "mongoindexeditor";
public static readonly MongoIndexing = "mongoindexing";
} }
export class AfecFeatures { export class AfecFeatures {

View File

@@ -23,10 +23,10 @@ export class Splitter {
public splitterId: string; public splitterId: string;
public leftSideId: string; public leftSideId: string;
public splitter!: HTMLElement; public splitter: HTMLElement;
public leftSide!: HTMLElement; public leftSide: HTMLElement;
public lastX!: number; public lastX: number;
public lastWidth!: number; public lastWidth: number;
private isCollapsed: ko.Observable<boolean>; private isCollapsed: ko.Observable<boolean>;
private bounds: SplitterBounds; private bounds: SplitterBounds;
@@ -42,10 +42,9 @@ export class Splitter {
} }
public initialize() { public initialize() {
if (document.getElementById(this.splitterId) !== null && document.getElementById(this.leftSideId) != null) { this.splitter = document.getElementById(this.splitterId);
this.splitter = <HTMLElement>document.getElementById(this.splitterId); this.leftSide = document.getElementById(this.leftSideId);
this.leftSide = <HTMLElement>document.getElementById(this.leftSideId);
}
const isVerticalSplitter: boolean = this.direction === SplitterDirection.Vertical; const isVerticalSplitter: boolean = this.direction === SplitterDirection.Vertical;
const splitterOptions: JQueryUI.ResizableOptions = { const splitterOptions: JQueryUI.ResizableOptions = {
animate: true, animate: true,

View File

@@ -1,383 +0,0 @@
// Type definitions for adal-angular 1.0.1.1
// Project: https://github.com/AzureAD/azure-activedirectory-library-for-js#readme
// Definitions by: Daniel Perez Alvarez <https://github.com/unindented>
// Anthony Ciccarello <https://github.com/aciccarello>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
//This is a customized version of adal on top of version 1.0.1 which does not support multi tenant
// Customized version add tenantId to stored tokens so when tenant change, adal will refetch instead of read from sessionStorage
// In module contexts the class constructor function is the exported object
// export = AuthenticationContext;
// This class is defined globally in not in a module context
declare class AuthenticationContext {
instance: string;
config: AuthenticationContext.Options;
callback: AuthenticationContext.TokenCallback;
popUp: boolean;
isAngular: boolean;
/**
* Enum for request type
*/
REQUEST_TYPE: AuthenticationContext.RequestType;
RESPONSE_TYPE: AuthenticationContext.ResponseType;
CONSTANTS: AuthenticationContext.Constants;
constructor(options: AuthenticationContext.Options);
/**
* Initiates the login process by redirecting the user to Azure AD authorization endpoint.
*/
login(): void;
/**
* Returns whether a login is in progress.
*/
loginInProgress(): boolean;
/**
* Gets token for the specified resource from the cache.
* @param resource A URI that identifies the resource for which the token is requested.
* @param tenantId tenant Id.
*/
getCachedToken(resource: string, tenantId: string): string;
/**
* If user object exists, returns it. Else creates a new user object by decoding `id_token` from the cache.
*/
getCachedUser(): AuthenticationContext.UserInfo;
/**
* Adds the passed callback to the array of callbacks for the specified resource.
* @param resource A URI that identifies the resource for which the token is requested.
* @param expectedState A unique identifier (guid).
* @param callback The callback provided by the caller. It will be called with token or error.
*/
registerCallback(
expectedState: string,
resource: string,
callback: AuthenticationContext.TokenCallback,
tenantId: string
): void;
/**
* Acquires token from the cache if it is not expired. Otherwise sends request to AAD to obtain a new token.
* @param resource Resource URI identifying the target resource.
* @param callback The callback provided by the caller. It will be called with token or error.
*/
acquireToken(resource: string, tenantId: string, callback: AuthenticationContext.TokenCallback): void;
/**
* Acquires token (interactive flow using a popup window) by sending request to AAD to obtain a new token.
* @param resource Resource URI identifying the target resource.
* @param extraQueryParameters Query parameters to add to the authentication request.
* @param claims Claims to add to the authentication request.
* @param callback The callback provided by the caller. It will be called with token or error.
*/
acquireTokenPopup(
resource: string,
tenantId: string,
extraQueryParameters: string | null | undefined,
claims: string | null | undefined,
callback: AuthenticationContext.TokenCallback
): void;
/**
* Acquires token (interactive flow using a redirect) by sending request to AAD to obtain a new token. In this case the callback passed in the authentication request constructor will be called.
* @param resource Resource URI identifying the target resource.
* @param extraQueryParameters Query parameters to add to the authentication request.
* @param claims Claims to add to the authentication request.
*/
acquireTokenRedirect(
resource: string,
tenantId: string,
extraQueryParameters?: string | null,
claims?: string | null
): void;
/**
* Redirects the browser to Azure AD authorization endpoint.
* @param urlNavigate URL of the authorization endpoint.
*/
promptUser(urlNavigate: string): void;
/**
* Clears cache items.
*/
clearCache(): void;
/**
* Clears cache items for a given resource.
* @param resource Resource URI identifying the target resource.
*/
clearCacheForResource(resource: string): void;
/**
* Redirects user to logout endpoint. After logout, it will redirect to `postLogoutRedirectUri` if added as a property on the config object.
*/
logOut(): void;
/**
* Calls the passed in callback with the user object or error message related to the user.
* @param callback The callback provided by the caller. It will be called with user or error.
*/
getUser(callback: AuthenticationContext.UserCallback): void;
/**
* Checks if the URL fragment contains access token, id token or error description.
* @param hash Hash passed from redirect page.
*/
isCallback(hash: string): boolean;
/**
* Gets login error.
*/
getLoginError(): string;
/**
* Creates a request info object from the URL fragment and returns it.
*/
getRequestInfo(hash: string): AuthenticationContext.RequestInfo;
/**
* Saves token or error received in the response from AAD in the cache. In case of `id_token`, it also creates the user object.
*/
saveTokenFromHash(requestInfo: AuthenticationContext.RequestInfo): void;
/**
* Gets resource for given endpoint if mapping is provided with config.
* @param endpoint Resource URI identifying the target resource.
*/
getResourceForEndpoint(resource: string): string;
/**
* This method must be called for processing the response received from AAD. It extracts the hash, processes the token or error, saves it in the cache and calls the callbacks with the result.
* @param hash Hash fragment of URL. Defaults to `window.location.hash`.
*/
handleWindowCallback(hash?: string): void;
/**
* Checks the logging Level, constructs the log message and logs it. Users need to implement/override this method to turn on logging.
* @param level Level can be set 0, 1, 2 and 3 which turns on 'error', 'warning', 'info' or 'verbose' level logging respectively.
* @param message Message to log.
* @param error Error to log.
*/
log(level: AuthenticationContext.LoggingLevel, message: string, error: any): void;
/**
* Logs messages when logging level is set to 0.
* @param message Message to log.
* @param error Error to log.
*/
error(message: string, error: any): void;
/**
* Logs messages when logging level is set to 1.
* @param message Message to log.
*/
warn(message: string): void;
/**
* Logs messages when logging level is set to 2.
* @param message Message to log.
*/
info(message: string): void;
/**
* Logs messages when logging level is set to 3.
* @param message Message to log.
*/
verbose(message: string): void;
/**
* Logs Pii messages when Logging Level is set to 0 and window.piiLoggingEnabled is set to true.
* @param message Message to log.
* @param error Error to log.
*/
errorPii(message: string, error: any): void;
/**
* Logs Pii messages when Logging Level is set to 1 and window.piiLoggingEnabled is set to true.
* @param message Message to log.
*/
warnPii(message: string): void;
/**
* Logs messages when Logging Level is set to 2 and window.piiLoggingEnabled is set to true.
* @param message Message to log.
*/
infoPii(message: string): void;
/**
* Logs messages when Logging Level is set to 3 and window.piiLoggingEnabled is set to true.
* @param message Message to log.
*/
verbosePii(message: string): void;
}
declare namespace AuthenticationContext {
function inject(config: Options): AuthenticationContext;
type LoggingLevel = 0 | 1 | 2 | 3;
type RequestType = "LOGIN" | "RENEW_TOKEN" | "UNKNOWN";
type ResponseType = "id_token token" | "token";
interface RequestInfo {
/**
* Object comprising of fields such as id_token/error, session_state, state, e.t.c.
*/
parameters: any;
/**
* Request type.
*/
requestType: RequestType;
/**
* Whether state is valid.
*/
stateMatch: boolean;
/**
* Unique guid used to match the response with the request.
*/
stateResponse: string;
/**
* Whether `requestType` contains `id_token`, `access_token` or error.
*/
valid: boolean;
}
interface UserInfo {
/**
* Username assigned from UPN or email.
*/
userName: string;
/**
* Properties parsed from `id_token`.
*/
profile: any;
}
type TokenCallback = (errorDesc: string | null, token: string | null, error: any) => void;
type UserCallback = (errorDesc: string | null, user: UserInfo | null) => void;
/**
* Configuration options for Authentication Context
*/
interface Options {
/**
* Client ID assigned to your app by Azure Active Directory.
*/
clientId: string;
/**
* Endpoint at which you expect to receive tokens.Defaults to `window.location.href`.
*/
redirectUri?: string;
/**
* Azure Active Directory instance. Defaults to `https://login.microsoftonline.com/`.
*/
instance?: string;
/**
* Your target tenant. Defaults to `common`.
*/
tenant?: string;
/**
* Query parameters to add to the authentication request.
*/
extraQueryParameter?: string;
/**
* Unique identifier used to map the request with the response. Defaults to RFC4122 version 4 guid (128 bits).
*/
correlationId?: string;
/**
* User defined function of handling the navigation to Azure AD authorization endpoint in case of login.
*/
displayCall?: (url: string) => void;
/**
* Set this to true to enable login in a popup winodow instead of a full redirect. Defaults to `false`.
*/
popUp?: boolean;
/**
* Set this to the resource to request on login. Defaults to `clientId`.
*/
loginResource?: string;
/**
* Set this to redirect the user to a custom login page.
*/
localLoginUrl?: string;
/**
* Redirects to start page after login. Defaults to `true`.
*/
navigateToLoginRequestUrl?: boolean;
/**
* Set this to redirect the user to a custom logout page.
*/
logOutUri?: string;
/**
* Redirects the user to postLogoutRedirectUri after logout. Defaults to `redirectUri`.
*/
postLogoutRedirectUri?: string;
/**
* Sets browser storage to either 'localStorage' or sessionStorage'. Defaults to `sessionStorage`.
*/
cacheLocation?: "localStorage" | "sessionStorage";
/**
* Array of keywords or URIs. Adal will attach a token to outgoing requests that have these keywords or URIs.
*/
endpoints?: { [resource: string]: string };
/**
* Array of keywords or URIs. Adal will not attach a token to outgoing requests that have these keywords or URIs.
*/
anonymousEndpoints?: string[];
/**
* If the cached token is about to be expired in the expireOffsetSeconds (in seconds), Adal will renew the token instead of using the cached token. Defaults to 300 seconds.
*/
expireOffsetSeconds?: number;
/**
* The number of milliseconds of inactivity before a token renewal response from AAD should be considered timed out. Defaults to 6 seconds.
*/
loadFrameTimeout?: number;
/**
* Callback to be invoked when a token is acquired.
*/
callback?: TokenCallback;
}
interface LoggingConfig {
level: LoggingLevel;
log: (message: string) => void;
piiLoggingEnabled: boolean;
}
/**
* Enum for storage constants
*/
interface Constants {
ACCESS_TOKEN: "access_token";
EXPIRES_IN: "expires_in";
ID_TOKEN: "id_token";
ERROR_DESCRIPTION: "error_description";
SESSION_STATE: "session_state";
STORAGE: {
TOKEN_KEYS: "adal.token.keys";
ACCESS_TOKEN_KEY: "adal.access.token.key";
EXPIRATION_KEY: "adal.expiration.key";
STATE_LOGIN: "adal.state.login";
STATE_RENEW: "adal.state.renew";
NONCE_IDTOKEN: "adal.nonce.idtoken";
SESSION_STATE: "adal.session.state";
USERNAME: "adal.username";
IDTOKEN: "adal.idtoken";
ERROR: "adal.error";
ERROR_DESCRIPTION: "adal.error.description";
LOGIN_REQUEST: "adal.login.request";
LOGIN_ERROR: "adal.login.error";
RENEW_STATUS: "adal.token.renew.status";
};
RESOURCE_DELIMETER: "|";
LOADFRAME_TIMEOUT: "6000";
TOKEN_RENEW_STATUS_CANCELED: "Canceled";
TOKEN_RENEW_STATUS_COMPLETED: "Completed";
TOKEN_RENEW_STATUS_IN_PROGRESS: "In Progress";
LOGGING_LEVEL: {
ERROR: 0;
WARN: 1;
INFO: 2;
VERBOSE: 3;
};
LEVEL_STRING_MAP: {
0: "ERROR:";
1: "WARNING:";
2: "INFO:";
3: "VERBOSE:";
};
POPUP_WIDTH: 483;
POPUP_HEIGHT: 600;
}
}
// declare global {
// interface Window {
// Logging: AuthenticationContext.LoggingConfig;
// }
// }

View File

@@ -38,7 +38,7 @@ export interface CommandButtonComponentProps {
/** /**
* Label for the button * Label for the button
*/ */
commandButtonLabel: string; commandButtonLabel?: string;
/** /**
* True if this button opens a tab or pane, false otherwise. * True if this button opens a tab or pane, false otherwise.

View File

@@ -138,8 +138,8 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
// Mongo container with system partition key still treat as "Fixed" // Mongo container with system partition key still treat as "Fixed"
this.isFixedContainer = this.isFixedContainer =
this.container.isPreferredApiMongoDB() && !this.collection.partitionKey ||
(!this.collection.partitionKey || this.collection.partitionKey.systemKey); (this.container.isPreferredApiMongoDB() && this.collection.partitionKey.systemKey);
this.state = { this.state = {
throughput: undefined, throughput: undefined,

View File

@@ -66,7 +66,7 @@ export interface PriceBreakdown {
currencySign: string; currencySign: string;
} }
export const infoAndToolTipTextStyle: ITextStyles = { root: { fontSize: 14 } }; export const infoAndToolTipTextStyle: ITextStyles = { root: { fontSize: 12 } };
export const noLeftPaddingCheckBoxStyle: ICheckboxStyles = { export const noLeftPaddingCheckBoxStyle: ICheckboxStyles = {
label: { label: {
@@ -166,10 +166,7 @@ export const separatorStyles: Partial<ISeparatorStyles> = {
] ]
}; };
export const messageBarStyles: Partial<IMessageBarStyles> = { export const messageBarStyles: Partial<IMessageBarStyles> = { root: { marginTop: "5px" } };
root: { marginTop: "5px", backgroundColor: "white" },
text: { fontSize: 14 }
};
export const throughputUnit = "RU/s"; export const throughputUnit = "RU/s";

View File

@@ -8,7 +8,7 @@ exports[`IndexingPolicyRefreshComponent renders 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }

View File

@@ -16,7 +16,7 @@ import {
} from "../SettingsRenderUtils"; } from "../SettingsRenderUtils";
import { hasDatabaseSharedThroughput } from "../SettingsUtils"; import { hasDatabaseSharedThroughput } from "../SettingsUtils";
import * as AutoPilotUtils from "../../../../Utils/AutoPilotUtils"; import * as AutoPilotUtils from "../../../../Utils/AutoPilotUtils";
import { Link, Text, TextField, Stack, Label, MessageBar, MessageBarType } from "office-ui-fabric-react"; import { Text, TextField, Stack, Label, MessageBar, MessageBarType } from "office-ui-fabric-react";
import { configContext, Platform } from "../../../../ConfigContext"; import { configContext, Platform } from "../../../../ConfigContext";
export interface ScaleComponentProps { export interface ScaleComponentProps {
@@ -176,7 +176,6 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
label={this.getThroughputTitle()} label={this.getThroughputTitle()}
isEmulator={this.isEmulator} isEmulator={this.isEmulator}
isFixed={this.props.isFixedContainer} isFixed={this.props.isFixedContainer}
isFreeTierAccount={this.isFreeTierAccount()}
isAutoPilotSelected={this.props.isAutoPilotSelected} isAutoPilotSelected={this.props.isAutoPilotSelected}
onAutoPilotSelected={this.props.onAutoPilotSelected} onAutoPilotSelected={this.props.onAutoPilotSelected}
wasAutopilotOriginallySet={this.props.wasAutopilotOriginallySet} wasAutopilotOriginallySet={this.props.wasAutopilotOriginallySet}
@@ -191,37 +190,9 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
/> />
); );
private isFreeTierAccount(): boolean {
const databaseAccount = this.props.container?.databaseAccount();
return databaseAccount?.properties?.enableFreeTier;
}
private getFreeTierInfoMessage(): JSX.Element {
return (
<Text>
With free tier, you will get the first 400 RU/s and 5 GB of storage in this account for free. To keep your
account free, keep the total RU/s across all resources in the account to 400 RU/s.
<Link
href="https://docs.microsoft.com/en-us/azure/cosmos-db/understand-your-bill#billing-examples-with-free-tier-accounts"
target="_blank"
>
Learn more.
</Link>
</Text>
);
}
public render(): JSX.Element { public render(): JSX.Element {
return ( return (
<Stack {...subComponentStackProps}> <Stack {...subComponentStackProps}>
{this.isFreeTierAccount() && (
<MessageBar
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
styles={{ text: { fontSize: 14 } }}
>
{this.getFreeTierInfoMessage()}
</MessageBar>
)}
{this.getInitialNotificationElement() && ( {this.getInitialNotificationElement() && (
<MessageBar messageBarType={MessageBarType.warning}>{this.getInitialNotificationElement()}</MessageBar> <MessageBar messageBarType={MessageBarType.warning}>{this.getInitialNotificationElement()}</MessageBar>
)} )}

View File

@@ -13,7 +13,16 @@ import {
} from "../SettingsUtils"; } from "../SettingsUtils";
import Explorer from "../../../Explorer"; import Explorer from "../../../Explorer";
import { Int32 } from "../../../Panes/Tables/Validators/EntityPropertyValidationCommon"; import { Int32 } from "../../../Panes/Tables/Validators/EntityPropertyValidationCommon";
import { Label, Text, TextField, Stack, IChoiceGroupOption, ChoiceGroup, MessageBar } from "office-ui-fabric-react"; import {
Label,
Text,
TextField,
Stack,
IChoiceGroupOption,
ChoiceGroup,
MessageBar,
MessageBarType
} from "office-ui-fabric-react";
import { import {
getTextFieldStyles, getTextFieldStyles,
changeFeedPolicyToolTip, changeFeedPolicyToolTip,
@@ -181,10 +190,7 @@ export class SubSettingsComponent extends React.Component<SubSettingsComponentPr
styles={getChoiceGroupStyles(this.props.timeToLive, this.props.timeToLiveBaseline)} styles={getChoiceGroupStyles(this.props.timeToLive, this.props.timeToLiveBaseline)}
/> />
{isDirty(this.props.timeToLive, this.props.timeToLiveBaseline) && this.props.timeToLive === TtlType.On && ( {isDirty(this.props.timeToLive, this.props.timeToLiveBaseline) && this.props.timeToLive === TtlType.On && (
<MessageBar <MessageBar messageBarType={MessageBarType.warning} styles={messageBarStyles}>
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
styles={messageBarStyles}
>
{ttlWarning} {ttlWarning}
</MessageBar> </MessageBar>
)} )}

View File

@@ -26,7 +26,6 @@ describe("ThroughputInputAutoPilotV3Component", () => {
spendAckVisible: false, spendAckVisible: false,
showAsMandatory: true, showAsMandatory: true,
isFixed: false, isFixed: false,
isFreeTierAccount: false,
label: "label", label: "label",
infoBubbleText: "infoBubbleText", infoBubbleText: "infoBubbleText",
canExceedMaximumValue: true, canExceedMaximumValue: true,

View File

@@ -28,6 +28,7 @@ import {
Label, Label,
Link, Link,
MessageBar, MessageBar,
MessageBarType,
FontIcon, FontIcon,
IColumn IColumn
} from "office-ui-fabric-react"; } from "office-ui-fabric-react";
@@ -57,7 +58,6 @@ export interface ThroughputInputAutoPilotV3Props {
spendAckVisible?: boolean; spendAckVisible?: boolean;
showAsMandatory?: boolean; showAsMandatory?: boolean;
isFixed: boolean; isFixed: boolean;
isFreeTierAccount: boolean;
isEmulator: boolean; isEmulator: boolean;
label: string; label: string;
infoBubbleText?: string; infoBubbleText?: string;
@@ -76,7 +76,6 @@ export interface ThroughputInputAutoPilotV3Props {
interface ThroughputInputAutoPilotV3State { interface ThroughputInputAutoPilotV3State {
spendAckChecked: boolean; spendAckChecked: boolean;
exceedFreeTierThroughput: boolean;
} }
export class ThroughputInputAutoPilotV3Component extends React.Component< export class ThroughputInputAutoPilotV3Component extends React.Component<
@@ -150,9 +149,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
public constructor(props: ThroughputInputAutoPilotV3Props) { public constructor(props: ThroughputInputAutoPilotV3Props) {
super(props); super(props);
this.state = { this.state = {
spendAckChecked: this.props.spendAckChecked, spendAckChecked: this.props.spendAckChecked
exceedFreeTierThroughput:
this.props.isFreeTierAccount && !this.props.isAutoPilotSelected && this.props.throughput > 400
}; };
this.step = this.props.step ?? ThroughputInputAutoPilotV3Component.defaultStep; this.step = this.props.step ?? ThroughputInputAutoPilotV3Component.defaultStep;
@@ -427,7 +424,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
newValue?: string newValue?: string
): void => { ): void => {
const newThroughput = getSanitizedInputValue(newValue); const newThroughput = getSanitizedInputValue(newValue, this.autoPilotInputMaxValue);
this.props.onMaxAutoPilotThroughputChange(newThroughput); this.props.onMaxAutoPilotThroughputChange(newThroughput);
}; };
@@ -435,11 +432,10 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
newValue?: string newValue?: string
): void => { ): void => {
const newThroughput = getSanitizedInputValue(newValue); const newThroughput = getSanitizedInputValue(newValue, this.throughputInputMaxValue);
if (this.overrideWithAutoPilotSettings()) { if (this.overrideWithAutoPilotSettings()) {
this.props.onMaxAutoPilotThroughputChange(newThroughput); this.props.onMaxAutoPilotThroughputChange(newThroughput);
} else { } else {
this.setState({ exceedFreeTierThroughput: this.props.isFreeTierAccount && newThroughput > 400 });
this.props.onThroughputChange(newThroughput); this.props.onThroughputChange(newThroughput);
} }
}; };
@@ -483,10 +479,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
/> />
</Label> </Label>
{this.overrideWithProvisionedThroughputSettings() && ( {this.overrideWithProvisionedThroughputSettings() && (
<MessageBar <MessageBar messageBarType={MessageBarType.warning} styles={messageBarStyles}>
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
styles={messageBarStyles}
>
{manualToAutoscaleDisclaimerElement} {manualToAutoscaleDisclaimerElement}
</MessageBar> </MessageBar>
)} )}
@@ -563,21 +556,8 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
} }
onChange={this.onThroughputChange} onChange={this.onThroughputChange}
/> />
{this.state.exceedFreeTierThroughput && (
<MessageBar
messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}
styles={messageBarStyles}
>
{
"Billing will apply if you provision more than 400 RU/s of manual throughput, or if the resource scales beyond 400 RU/s with autoscale."
}
</MessageBar>
)}
{this.props.getThroughputWarningMessage() && ( {this.props.getThroughputWarningMessage() && (
<MessageBar <MessageBar messageBarType={MessageBarType.warning} styles={messageBarStyles}>
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
styles={messageBarStyles}
>
{this.props.getThroughputWarningMessage()} {this.props.getThroughputWarningMessage()}
</MessageBar> </MessageBar>
)} )}
@@ -603,15 +583,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
warningMessage = saveThroughputWarningMessage; warningMessage = saveThroughputWarningMessage;
} }
return ( return <>{warningMessage && <MessageBar messageBarType={MessageBarType.warning}>{warningMessage}</MessageBar>}</>;
<>
{warningMessage && (
<MessageBar messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}>
{warningMessage}
</MessageBar>
)}
</>
);
}; };
public render(): JSX.Element { public render(): JSX.Element {

View File

@@ -9,18 +9,13 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = `
} }
> >
<StyledMessageBarBase <StyledMessageBarBase
messageBarIconProps={ messageBarType={5}
Object {
"className": "messageBarWarningIcon",
"iconName": "WarningSolid",
}
}
> >
<Text <Text
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -39,7 +34,7 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -50,21 +45,12 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = `
/> />
</StyledLabelBase> </StyledLabelBase>
<StyledMessageBarBase <StyledMessageBarBase
messageBarIconProps={ messageBarType={5}
Object {
"className": "messageBarInfoIcon",
"iconName": "InfoSolid",
}
}
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"backgroundColor": "white",
"marginTop": "5px", "marginTop": "5px",
}, },
"text": Object {
"fontSize": 14,
},
} }
} }
> >
@@ -73,7 +59,7 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -185,7 +171,7 @@ exports[`ThroughputInputAutoPilotV3Component spendAck checkbox visible 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -458,7 +444,7 @@ exports[`ThroughputInputAutoPilotV3Component throughput input visible 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }

View File

@@ -16,7 +16,7 @@ exports[`ScaleComponent renders with correct initial notification 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }

View File

@@ -136,7 +136,7 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -412,7 +412,7 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -952,7 +952,7 @@ exports[`SubSettingsComponent renders 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -1228,7 +1228,7 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }

View File

@@ -101,13 +101,13 @@ export const parseConflictResolutionProcedure = (procedureFromBackEnd: string):
return procedureFromBackEnd; return procedureFromBackEnd;
}; };
export const getSanitizedInputValue = (newValueString: string, max?: number): number => { export const getSanitizedInputValue = (newValueString: string, max: number): number => {
const newValue = parseInt(newValueString); const newValue = parseInt(newValueString);
if (isNaN(newValue)) { if (isNaN(newValue)) {
return zeroValue; return zeroValue;
} }
// make sure new value does not exceed the maximum throughput // make sure new value does not exceed the maximum throughput
return max ? Math.min(newValue, max) : newValue; return Math.min(newValue, max);
}; };
export const isDirty = (current: isDirtyTypes, baseline: isDirtyTypes): boolean => { export const isDirty = (current: isDirtyTypes, baseline: isDirtyTypes): boolean => {

View File

@@ -55,7 +55,6 @@ exports[`SettingsComponent renders 1`] = `
"firstFieldHasFocus": [Function], "firstFieldHasFocus": [Function],
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "adddatabasepane", "id": "adddatabasepane",
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
"isExecuting": [Function], "isExecuting": [Function],
@@ -105,7 +104,6 @@ exports[`SettingsComponent renders 1`] = `
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"formWarnings": [Function], "formWarnings": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "addcollectionpane", "id": "addcollectionpane",
"isAnalyticalStorageOn": [Function], "isAnalyticalStorageOn": [Function],
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
@@ -593,7 +591,6 @@ exports[`SettingsComponent renders 1`] = `
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"formWarnings": [Function], "formWarnings": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "addcollectionpane", "id": "addcollectionpane",
"isAnalyticalStorageOn": [Function], "isAnalyticalStorageOn": [Function],
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
@@ -668,7 +665,6 @@ exports[`SettingsComponent renders 1`] = `
"firstFieldHasFocus": [Function], "firstFieldHasFocus": [Function],
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "adddatabasepane", "id": "adddatabasepane",
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
"isExecuting": [Function], "isExecuting": [Function],
@@ -954,7 +950,6 @@ exports[`SettingsComponent renders 1`] = `
"isHostedDataExplorerEnabled": [Function], "isHostedDataExplorerEnabled": [Function],
"isLeftPaneExpanded": [Function], "isLeftPaneExpanded": [Function],
"isLinkInjectionEnabled": [Function], "isLinkInjectionEnabled": [Function],
"isMongoIndexingEnabled": [Function],
"isNotebookEnabled": [Function], "isNotebookEnabled": [Function],
"isNotebooksEnabledForAccount": [Function], "isNotebooksEnabledForAccount": [Function],
"isNotificationConsoleExpanded": [Function], "isNotificationConsoleExpanded": [Function],
@@ -1180,9 +1175,11 @@ exports[`SettingsComponent renders 1`] = `
}, },
"direction": "vertical", "direction": "vertical",
"isCollapsed": [Function], "isCollapsed": [Function],
"leftSide": null,
"leftSideId": "resourcetree", "leftSideId": "resourcetree",
"onResizeStart": [Function], "onResizeStart": [Function],
"onResizeStop": [Function], "onResizeStop": [Function],
"splitter": null,
"splitterId": "h_splitter1", "splitterId": "h_splitter1",
}, },
"stringInputPane": StringInputPane { "stringInputPane": StringInputPane {
@@ -1329,7 +1326,6 @@ exports[`SettingsComponent renders 1`] = `
"firstFieldHasFocus": [Function], "firstFieldHasFocus": [Function],
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "adddatabasepane", "id": "adddatabasepane",
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
"isExecuting": [Function], "isExecuting": [Function],
@@ -1379,7 +1375,6 @@ exports[`SettingsComponent renders 1`] = `
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"formWarnings": [Function], "formWarnings": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "addcollectionpane", "id": "addcollectionpane",
"isAnalyticalStorageOn": [Function], "isAnalyticalStorageOn": [Function],
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
@@ -1867,7 +1862,6 @@ exports[`SettingsComponent renders 1`] = `
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"formWarnings": [Function], "formWarnings": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "addcollectionpane", "id": "addcollectionpane",
"isAnalyticalStorageOn": [Function], "isAnalyticalStorageOn": [Function],
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
@@ -1942,7 +1936,6 @@ exports[`SettingsComponent renders 1`] = `
"firstFieldHasFocus": [Function], "firstFieldHasFocus": [Function],
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "adddatabasepane", "id": "adddatabasepane",
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
"isExecuting": [Function], "isExecuting": [Function],
@@ -2228,7 +2221,6 @@ exports[`SettingsComponent renders 1`] = `
"isHostedDataExplorerEnabled": [Function], "isHostedDataExplorerEnabled": [Function],
"isLeftPaneExpanded": [Function], "isLeftPaneExpanded": [Function],
"isLinkInjectionEnabled": [Function], "isLinkInjectionEnabled": [Function],
"isMongoIndexingEnabled": [Function],
"isNotebookEnabled": [Function], "isNotebookEnabled": [Function],
"isNotebooksEnabledForAccount": [Function], "isNotebooksEnabledForAccount": [Function],
"isNotificationConsoleExpanded": [Function], "isNotificationConsoleExpanded": [Function],
@@ -2454,9 +2446,11 @@ exports[`SettingsComponent renders 1`] = `
}, },
"direction": "vertical", "direction": "vertical",
"isCollapsed": [Function], "isCollapsed": [Function],
"leftSide": null,
"leftSideId": "resourcetree", "leftSideId": "resourcetree",
"onResizeStart": [Function], "onResizeStart": [Function],
"onResizeStop": [Function], "onResizeStop": [Function],
"splitter": null,
"splitterId": "h_splitter1", "splitterId": "h_splitter1",
}, },
"stringInputPane": StringInputPane { "stringInputPane": StringInputPane {
@@ -2616,7 +2610,6 @@ exports[`SettingsComponent renders 1`] = `
"firstFieldHasFocus": [Function], "firstFieldHasFocus": [Function],
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "adddatabasepane", "id": "adddatabasepane",
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
"isExecuting": [Function], "isExecuting": [Function],
@@ -2666,7 +2659,6 @@ exports[`SettingsComponent renders 1`] = `
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"formWarnings": [Function], "formWarnings": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "addcollectionpane", "id": "addcollectionpane",
"isAnalyticalStorageOn": [Function], "isAnalyticalStorageOn": [Function],
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
@@ -3154,7 +3146,6 @@ exports[`SettingsComponent renders 1`] = `
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"formWarnings": [Function], "formWarnings": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "addcollectionpane", "id": "addcollectionpane",
"isAnalyticalStorageOn": [Function], "isAnalyticalStorageOn": [Function],
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
@@ -3229,7 +3220,6 @@ exports[`SettingsComponent renders 1`] = `
"firstFieldHasFocus": [Function], "firstFieldHasFocus": [Function],
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "adddatabasepane", "id": "adddatabasepane",
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
"isExecuting": [Function], "isExecuting": [Function],
@@ -3515,7 +3505,6 @@ exports[`SettingsComponent renders 1`] = `
"isHostedDataExplorerEnabled": [Function], "isHostedDataExplorerEnabled": [Function],
"isLeftPaneExpanded": [Function], "isLeftPaneExpanded": [Function],
"isLinkInjectionEnabled": [Function], "isLinkInjectionEnabled": [Function],
"isMongoIndexingEnabled": [Function],
"isNotebookEnabled": [Function], "isNotebookEnabled": [Function],
"isNotebooksEnabledForAccount": [Function], "isNotebooksEnabledForAccount": [Function],
"isNotificationConsoleExpanded": [Function], "isNotificationConsoleExpanded": [Function],
@@ -3741,9 +3730,11 @@ exports[`SettingsComponent renders 1`] = `
}, },
"direction": "vertical", "direction": "vertical",
"isCollapsed": [Function], "isCollapsed": [Function],
"leftSide": null,
"leftSideId": "resourcetree", "leftSideId": "resourcetree",
"onResizeStart": [Function], "onResizeStart": [Function],
"onResizeStop": [Function], "onResizeStop": [Function],
"splitter": null,
"splitterId": "h_splitter1", "splitterId": "h_splitter1",
}, },
"stringInputPane": StringInputPane { "stringInputPane": StringInputPane {
@@ -3890,7 +3881,6 @@ exports[`SettingsComponent renders 1`] = `
"firstFieldHasFocus": [Function], "firstFieldHasFocus": [Function],
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "adddatabasepane", "id": "adddatabasepane",
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
"isExecuting": [Function], "isExecuting": [Function],
@@ -3940,7 +3930,6 @@ exports[`SettingsComponent renders 1`] = `
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"formWarnings": [Function], "formWarnings": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "addcollectionpane", "id": "addcollectionpane",
"isAnalyticalStorageOn": [Function], "isAnalyticalStorageOn": [Function],
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
@@ -4428,7 +4417,6 @@ exports[`SettingsComponent renders 1`] = `
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"formWarnings": [Function], "formWarnings": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "addcollectionpane", "id": "addcollectionpane",
"isAnalyticalStorageOn": [Function], "isAnalyticalStorageOn": [Function],
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
@@ -4503,7 +4491,6 @@ exports[`SettingsComponent renders 1`] = `
"firstFieldHasFocus": [Function], "firstFieldHasFocus": [Function],
"formErrors": [Function], "formErrors": [Function],
"formErrorsDetails": [Function], "formErrorsDetails": [Function],
"freeTierExceedThroughputTooltip": [Function],
"id": "adddatabasepane", "id": "adddatabasepane",
"isAutoPilotSelected": [Function], "isAutoPilotSelected": [Function],
"isExecuting": [Function], "isExecuting": [Function],
@@ -4789,7 +4776,6 @@ exports[`SettingsComponent renders 1`] = `
"isHostedDataExplorerEnabled": [Function], "isHostedDataExplorerEnabled": [Function],
"isLeftPaneExpanded": [Function], "isLeftPaneExpanded": [Function],
"isLinkInjectionEnabled": [Function], "isLinkInjectionEnabled": [Function],
"isMongoIndexingEnabled": [Function],
"isNotebookEnabled": [Function], "isNotebookEnabled": [Function],
"isNotebooksEnabledForAccount": [Function], "isNotebooksEnabledForAccount": [Function],
"isNotificationConsoleExpanded": [Function], "isNotificationConsoleExpanded": [Function],
@@ -5015,9 +5001,11 @@ exports[`SettingsComponent renders 1`] = `
}, },
"direction": "vertical", "direction": "vertical",
"isCollapsed": [Function], "isCollapsed": [Function],
"leftSide": null,
"leftSideId": "resourcetree", "leftSideId": "resourcetree",
"onResizeStart": [Function], "onResizeStart": [Function],
"onResizeStop": [Function], "onResizeStop": [Function],
"splitter": null,
"splitterId": "h_splitter1", "splitterId": "h_splitter1",
}, },
"stringInputPane": StringInputPane { "stringInputPane": StringInputPane {

View File

@@ -159,7 +159,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -176,7 +176,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -195,7 +195,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -207,7 +207,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -219,7 +219,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -230,7 +230,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -249,7 +249,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -268,7 +268,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -286,7 +286,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -299,7 +299,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -310,7 +310,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -329,7 +329,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -371,7 +371,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -386,7 +386,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }
@@ -402,7 +402,7 @@ exports[`SettingsUtils functions render 1`] = `
styles={ styles={
Object { Object {
"root": Object { "root": Object {
"fontSize": 14, "fontSize": 12,
}, },
} }
} }

View File

@@ -129,8 +129,6 @@ export interface ThroughputInputParams {
showAutoPilot?: ko.Observable<boolean>; showAutoPilot?: ko.Observable<boolean>;
overrideWithAutoPilotSettings: ko.Observable<boolean>; overrideWithAutoPilotSettings: ko.Observable<boolean>;
overrideWithProvisionedThroughputSettings: ko.Observable<boolean>; overrideWithProvisionedThroughputSettings: ko.Observable<boolean>;
freeTierExceedThroughputTooltip?: ko.Observable<string>;
freeTierExceedThroughputWarning?: ko.Observable<string>;
} }
export class ThroughputInputViewModel extends WaitsForTemplateViewModel { export class ThroughputInputViewModel extends WaitsForTemplateViewModel {
@@ -167,10 +165,6 @@ export class ThroughputInputViewModel extends WaitsForTemplateViewModel {
public overrideWithProvisionedThroughputSettings: ko.Observable<boolean>; public overrideWithProvisionedThroughputSettings: ko.Observable<boolean>;
public isManualThroughputInputFieldRequired: ko.Computed<boolean>; public isManualThroughputInputFieldRequired: ko.Computed<boolean>;
public isAutoscaleThroughputInputFieldRequired: ko.Computed<boolean>; public isAutoscaleThroughputInputFieldRequired: ko.Computed<boolean>;
public freeTierExceedThroughputTooltip: ko.Observable<string>;
public freeTierExceedThroughputWarning: ko.Observable<string>;
public showFreeTierExceedThroughputTooltip: ko.Computed<boolean>;
public showFreeTierExceedThroughputWarning: ko.Computed<boolean>;
public constructor(options: ThroughputInputParams) { public constructor(options: ThroughputInputParams) {
super(); super();
@@ -225,16 +219,6 @@ export class ThroughputInputViewModel extends WaitsForTemplateViewModel {
this.isAutoscaleThroughputInputFieldRequired = ko.pureComputed( this.isAutoscaleThroughputInputFieldRequired = ko.pureComputed(
() => this.isEnabled() && this.isAutoPilotSelected() () => this.isEnabled() && this.isAutoPilotSelected()
); );
this.freeTierExceedThroughputTooltip = options.freeTierExceedThroughputTooltip || ko.observable<string>();
this.freeTierExceedThroughputWarning = options.freeTierExceedThroughputWarning || ko.observable<string>();
this.showFreeTierExceedThroughputTooltip = ko.pureComputed<boolean>(
() => !!this.freeTierExceedThroughputTooltip() && this.value() > 400
);
this.showFreeTierExceedThroughputWarning = ko.pureComputed<boolean>(
() => !!this.freeTierExceedThroughputWarning() && this.value() > 400
);
} }
public decreaseThroughput() { public decreaseThroughput() {

View File

@@ -132,14 +132,6 @@
<a target="_blank" href="https://cosmos.azure.com/capacitycalculator/">capacity calculator</a></span <a target="_blank" href="https://cosmos.azure.com/capacitycalculator/">capacity calculator</a></span
> >
</p> </p>
<div class="inputTooltip">
<span
data-bind="text: freeTierExceedThroughputTooltip, visible: showFreeTierExceedThroughputTooltip"
class="inputTooltipText"
></span>
</div>
<div data-bind="setTemplateReady: true"> <div data-bind="setTemplateReady: true">
<input <input
data-bind=" data-bind="
@@ -162,11 +154,6 @@
/> />
</div> </div>
<div class="freeTierInlineWarning" data-bind="visible: showFreeTierExceedThroughputWarning">
<span class="freeTierWarningIcon"><img src="/warning.svg" alt="Warning"/></span>
<span class="freeTierWarningMessage" data-bind="text: freeTierExceedThroughputWarning"></span>
</div>
<p data-bind="visible: costsVisible"> <p data-bind="visible: costsVisible">
<span data-bind="html: requestUnitsUsageCost"></span> <span data-bind="html: requestUnitsUsageCost"></span>
</p> </p>

View File

@@ -207,7 +207,6 @@ export default class Explorer {
public isCopyNotebookPaneEnabled: ko.Observable<boolean>; public isCopyNotebookPaneEnabled: ko.Observable<boolean>;
public isHostedDataExplorerEnabled: ko.Computed<boolean>; public isHostedDataExplorerEnabled: ko.Computed<boolean>;
public isRightPanelV2Enabled: ko.Computed<boolean>; public isRightPanelV2Enabled: ko.Computed<boolean>;
public isMongoIndexingEnabled: ko.Observable<boolean>;
public canExceedMaximumValue: ko.Computed<boolean>; public canExceedMaximumValue: ko.Computed<boolean>;
public shouldShowShareDialogContents: ko.Observable<boolean>; public shouldShowShareDialogContents: ko.Observable<boolean>;
@@ -403,7 +402,6 @@ export default class Explorer {
this.isFeatureEnabled(Constants.Features.enableLinkInjection) this.isFeatureEnabled(Constants.Features.enableLinkInjection)
); );
this.isGitHubPaneEnabled = ko.observable<boolean>(false); this.isGitHubPaneEnabled = ko.observable<boolean>(false);
this.isMongoIndexingEnabled = ko.observable<boolean>(false);
this.isPublishNotebookPaneEnabled = ko.observable<boolean>(false); this.isPublishNotebookPaneEnabled = ko.observable<boolean>(false);
this.isCopyNotebookPaneEnabled = ko.observable<boolean>(false); this.isCopyNotebookPaneEnabled = ko.observable<boolean>(false);
@@ -1898,9 +1896,6 @@ export default class Explorer {
if (!flights) { if (!flights) {
return; return;
} }
if (flights.indexOf(Constants.Flights.MongoIndexing) !== -1) {
this.isMongoIndexingEnabled(true);
}
} }
public findSelectedCollection(): ViewModels.Collection { public findSelectedCollection(): ViewModels.Collection {
@@ -3019,25 +3014,4 @@ export default class Explorer {
}) })
); );
} }
public isFirstResourceCreated(): boolean {
const databases: ViewModels.Database[] = this.databases();
if (!databases || databases.length === 0) {
return false;
}
return databases.some(database => {
// user has created at least one collection
if (database.collections()?.length > 0) {
return true;
}
// user has created a database with shared throughput
if (database.offer()) {
return true;
}
// use has created an empty database without shared throughput
return false;
});
}
} }

View File

@@ -1,3 +1,4 @@
import "./MeControlComponent.less";
import * as React from "react"; import * as React from "react";
import { DefaultButton, BaseButton, IButtonProps } from "office-ui-fabric-react/lib/Button"; import { DefaultButton, BaseButton, IButtonProps } from "office-ui-fabric-react/lib/Button";
import { DirectionalHint, IContextualMenuProps } from "office-ui-fabric-react/lib/ContextualMenu"; import { DirectionalHint, IContextualMenuProps } from "office-ui-fabric-react/lib/ContextualMenu";

View File

@@ -152,8 +152,7 @@
maxAutoPilotThroughputSet: sharedAutoPilotThroughput, maxAutoPilotThroughputSet: sharedAutoPilotThroughput,
autoPilotUsageCost: autoPilotUsageCost, autoPilotUsageCost: autoPilotUsageCost,
canExceedMaximumValue: canExceedMaximumValue, canExceedMaximumValue: canExceedMaximumValue,
showAutoPilot: !isFreeTierAccount(), showAutoPilot: !isFreeTierAccount()
freeTierExceedThroughputTooltip: freeTierExceedThroughputTooltip
}"> }">
</throughput-input-autopilot-v3> </throughput-input-autopilot-v3>
</div> </div>
@@ -334,8 +333,7 @@
maxAutoPilotThroughputSet: autoPilotThroughput, maxAutoPilotThroughputSet: autoPilotThroughput,
autoPilotUsageCost: autoPilotUsageCost, autoPilotUsageCost: autoPilotUsageCost,
canExceedMaximumValue: canExceedMaximumValue, canExceedMaximumValue: canExceedMaximumValue,
showAutoPilot: !isFixedStorageSelected(), showAutoPilot: !isFixedStorageSelected()
freeTierExceedThroughputTooltip: freeTierExceedThroughputTooltip
}"> }">
</throughput-input-autopilot-v3> </throughput-input-autopilot-v3>
</div> </div>

View File

@@ -74,7 +74,7 @@ describe("Add Collection Pane", () => {
explorer.databaseAccount(mockFreeTierDatabaseAccount); explorer.databaseAccount(mockFreeTierDatabaseAccount);
const addCollectionPane = explorer.addCollectionPane as AddCollectionPane; const addCollectionPane = explorer.addCollectionPane as AddCollectionPane;
expect(addCollectionPane.isFreeTierAccount()).toBe(true); expect(addCollectionPane.isFreeTierAccount()).toBe(true);
expect(addCollectionPane.upsellMessage()).toContain("With free tier"); expect(addCollectionPane.upsellMessage()).toContain("With free tier discount");
expect(addCollectionPane.upsellAnchorUrl()).toBe(Constants.Urls.freeTierInformation); expect(addCollectionPane.upsellAnchorUrl()).toBe(Constants.Urls.freeTierInformation);
expect(addCollectionPane.upsellAnchorText()).toBe("Learn more"); expect(addCollectionPane.upsellAnchorText()).toBe("Learn more");
}); });

View File

@@ -89,10 +89,9 @@ export default class AddCollectionPane extends ContextualPaneBase {
public isSynapseLinkUpdating: ko.Computed<boolean>; public isSynapseLinkUpdating: ko.Computed<boolean>;
public canExceedMaximumValue: ko.PureComputed<boolean>; public canExceedMaximumValue: ko.PureComputed<boolean>;
public ruToolTipText: ko.Computed<string>; public ruToolTipText: ko.Computed<string>;
public freeTierExceedThroughputTooltip: ko.Computed<string>;
public canConfigureThroughput: ko.PureComputed<boolean>; public canConfigureThroughput: ko.PureComputed<boolean>;
public showUpsellMessage: ko.PureComputed<boolean>; public showUpsellMessage: ko.PureComputed<boolean>;
public shouldCreateMongoWildcardIndex: ko.Computed<boolean>; public shouldCreateMongoWildcardIndex: ko.Observable<boolean>;
private _isSynapseLinkEnabled: ko.Computed<boolean>; private _isSynapseLinkEnabled: ko.Computed<boolean>;
@@ -100,6 +99,7 @@ export default class AddCollectionPane extends ContextualPaneBase {
super(options); super(options);
this.ruToolTipText = ko.pureComputed(() => PricingUtils.getRuToolTipText()); this.ruToolTipText = ko.pureComputed(() => PricingUtils.getRuToolTipText());
this.canConfigureThroughput = ko.pureComputed(() => !this.container.isServerlessEnabled()); this.canConfigureThroughput = ko.pureComputed(() => !this.container.isServerlessEnabled());
this.showUpsellMessage = ko.pureComputed(() => !this.container.isServerlessEnabled());
this.formWarnings = ko.observable<string>(); this.formWarnings = ko.observable<string>();
this.collectionId = ko.observable<string>(); this.collectionId = ko.observable<string>();
this.databaseId = ko.observable<string>(); this.databaseId = ko.observable<string>();
@@ -481,20 +481,8 @@ export default class AddCollectionPane extends ContextualPaneBase {
this.resetData(); this.resetData();
}); });
this.freeTierExceedThroughputTooltip = ko.pureComputed<string>(() =>
this.isFreeTierAccount() && !this.container.isFirstResourceCreated()
? "The first 400 RU/s in this account are free. Billing will apply to any throughput beyond 400 RU/s."
: ""
);
this.upsellMessage = ko.pureComputed<string>(() => { this.upsellMessage = ko.pureComputed<string>(() => {
return PricingUtils.getUpsellMessage( return PricingUtils.getUpsellMessage(this.container.serverId(), this.isFreeTierAccount());
this.container.serverId(),
this.isFreeTierAccount(),
this.container.isFirstResourceCreated(),
this.container.defaultExperience(),
true
);
}); });
this.upsellMessageAriaLabel = ko.pureComputed<string>(() => { this.upsellMessageAriaLabel = ko.pureComputed<string>(() => {
@@ -546,23 +534,6 @@ export default class AddCollectionPane extends ContextualPaneBase {
return isFreeTierAccount; return isFreeTierAccount;
}); });
this.showUpsellMessage = ko.pureComputed(() => {
if (this.container.isServerlessEnabled()) {
return false;
}
if (
this.isFreeTierAccount() &&
!this.databaseCreateNew() &&
this.databaseHasSharedOffer() &&
!this.collectionWithThroughputInShared()
) {
return false;
}
return true;
});
this.showIndexingOptionsForSharedThroughput = ko.computed<boolean>(() => { this.showIndexingOptionsForSharedThroughput = ko.computed<boolean>(() => {
const newDatabaseWithSharedOffer = this.databaseCreateNew() && this.databaseCreateNewShared(); const newDatabaseWithSharedOffer = this.databaseCreateNew() && this.databaseCreateNewShared();
const existingDatabaseWithSharedOffer = !this.databaseCreateNew() && this.databaseHasSharedOffer(); const existingDatabaseWithSharedOffer = !this.databaseCreateNew() && this.databaseHasSharedOffer();
@@ -654,9 +625,7 @@ export default class AddCollectionPane extends ContextualPaneBase {
}); });
}); });
this.shouldCreateMongoWildcardIndex = ko.computed(function() { this.shouldCreateMongoWildcardIndex = ko.observable(false);
return this.container.isMongoIndexingEnabled();
}, this);
} }
public getSharedThroughputDefault(): boolean { public getSharedThroughputDefault(): boolean {

View File

@@ -114,8 +114,7 @@
maxAutoPilotThroughputSet: maxAutoPilotThroughputSet, maxAutoPilotThroughputSet: maxAutoPilotThroughputSet,
autoPilotUsageCost: autoPilotUsageCost, autoPilotUsageCost: autoPilotUsageCost,
canExceedMaximumValue: canExceedMaximumValue, canExceedMaximumValue: canExceedMaximumValue,
showAutoPilot: !isFreeTierAccount(), showAutoPilot: !isFreeTierAccount()
freeTierExceedThroughputTooltip: freeTierExceedThroughputTooltip
}"> }">
</throughput-input-autopilot-v3> </throughput-input-autopilot-v3>
<p data-bind="visible: canRequestSupport"> <p data-bind="visible: canRequestSupport">

View File

@@ -77,7 +77,7 @@ describe("Add Database Pane", () => {
explorer.databaseAccount(mockFreeTierDatabaseAccount); explorer.databaseAccount(mockFreeTierDatabaseAccount);
const addDatabasePane = explorer.addDatabasePane as AddDatabasePane; const addDatabasePane = explorer.addDatabasePane as AddDatabasePane;
expect(addDatabasePane.isFreeTierAccount()).toBe(true); expect(addDatabasePane.isFreeTierAccount()).toBe(true);
expect(addDatabasePane.upsellMessage()).toContain("With free tier"); expect(addDatabasePane.upsellMessage()).toContain("With free tier discount");
expect(addDatabasePane.upsellAnchorUrl()).toBe(Constants.Urls.freeTierInformation); expect(addDatabasePane.upsellAnchorUrl()).toBe(Constants.Urls.freeTierInformation);
expect(addDatabasePane.upsellAnchorText()).toBe("Learn more"); expect(addDatabasePane.upsellAnchorText()).toBe("Learn more");
}); });

View File

@@ -44,7 +44,6 @@ export default class AddDatabasePane extends ContextualPaneBase {
public autoPilotUsageCost: ko.Computed<string>; public autoPilotUsageCost: ko.Computed<string>;
public canExceedMaximumValue: ko.PureComputed<boolean>; public canExceedMaximumValue: ko.PureComputed<boolean>;
public ruToolTipText: ko.Computed<string>; public ruToolTipText: ko.Computed<string>;
public freeTierExceedThroughputTooltip: ko.Computed<string>;
public isFreeTierAccount: ko.Computed<boolean>; public isFreeTierAccount: ko.Computed<boolean>;
public canConfigureThroughput: ko.PureComputed<boolean>; public canConfigureThroughput: ko.PureComputed<boolean>;
public showUpsellMessage: ko.PureComputed<boolean>; public showUpsellMessage: ko.PureComputed<boolean>;
@@ -55,6 +54,7 @@ export default class AddDatabasePane extends ContextualPaneBase {
this.databaseId = ko.observable<string>(); this.databaseId = ko.observable<string>();
this.ruToolTipText = ko.pureComputed(() => PricingUtils.getRuToolTipText()); this.ruToolTipText = ko.pureComputed(() => PricingUtils.getRuToolTipText());
this.canConfigureThroughput = ko.pureComputed(() => !this.container.isServerlessEnabled()); this.canConfigureThroughput = ko.pureComputed(() => !this.container.isServerlessEnabled());
this.showUpsellMessage = ko.pureComputed(() => !this.container.isServerlessEnabled());
this.canExceedMaximumValue = ko.pureComputed(() => this.container.canExceedMaximumValue()); this.canExceedMaximumValue = ko.pureComputed(() => this.container.canExceedMaximumValue());
@@ -182,18 +182,6 @@ export default class AddDatabasePane extends ContextualPaneBase {
return isFreeTierAccount; return isFreeTierAccount;
}); });
this.showUpsellMessage = ko.pureComputed(() => {
if (this.container.isServerlessEnabled()) {
return false;
}
if (this.isFreeTierAccount()) {
return this.databaseCreateNewShared();
}
return true;
});
this.maxThroughputRUText = ko.pureComputed(() => { this.maxThroughputRUText = ko.pureComputed(() => {
return this.maxThroughputRU().toLocaleString(); return this.maxThroughputRU().toLocaleString();
}); });
@@ -231,20 +219,8 @@ export default class AddDatabasePane extends ContextualPaneBase {
this.resetData(); this.resetData();
}); });
this.freeTierExceedThroughputTooltip = ko.pureComputed<string>(() =>
this.isFreeTierAccount() && !this.container.isFirstResourceCreated()
? "The first 400 RU/s in this account are free. Billing will apply to any throughput beyond 400 RU/s."
: ""
);
this.upsellMessage = ko.pureComputed<string>(() => { this.upsellMessage = ko.pureComputed<string>(() => {
return PricingUtils.getUpsellMessage( return PricingUtils.getUpsellMessage(this.container.serverId(), this.isFreeTierAccount());
this.container.serverId(),
this.isFreeTierAccount(),
this.container.isFirstResourceCreated(),
this.container.defaultExperience(),
false
);
}); });
this.upsellMessageAriaLabel = ko.pureComputed<string>(() => { this.upsellMessageAriaLabel = ko.pureComputed<string>(() => {

View File

@@ -23,19 +23,6 @@
<div class="scaleDivison" aria-label="Scale" aria-controls="scaleRegion"> <div class="scaleDivison" aria-label="Scale" aria-controls="scaleRegion">
<span class="scaleSettingTitle">Scale</span> <span class="scaleSettingTitle">Scale</span>
</div> </div>
<div class="freeTierInfoBanner" data-bind="visible: isFreeTierAccount">
<span class="freeTierInfoIcon"><img src="/info_color.svg" alt="Info"/></span>
<span class="freeTierInfoMessage"
>With free tier, you'll get the first 400 RU/s and 5 GB of storage in this account for free. To keep your
account free, keep the total RU/s across all resources in the account to 400 RU/s.
<a
href="https://docs.microsoft.com/en-us/azure/cosmos-db/understand-your-bill#billing-examples-with-free-tier-accounts"
target="_blank"
>
Learn more.</a
>
</span>
</div>
<div class="ssTextAllignment" id="scaleRegion"> <div class="ssTextAllignment" id="scaleRegion">
<throughput-input-autopilot-v3 <throughput-input-autopilot-v3
params="{ params="{
@@ -59,8 +46,7 @@
autoPilotUsageCost: autoPilotUsageCost, autoPilotUsageCost: autoPilotUsageCost,
canExceedMaximumValue: canExceedMaximumValue, canExceedMaximumValue: canExceedMaximumValue,
overrideWithAutoPilotSettings: overrideWithAutoPilotSettings, overrideWithAutoPilotSettings: overrideWithAutoPilotSettings,
overrideWithProvisionedThroughputSettings: overrideWithProvisionedThroughputSettings, overrideWithProvisionedThroughputSettings: overrideWithProvisionedThroughputSettings
freeTierExceedThroughputWarning: freeTierExceedThroughputWarning
}" }"
> >
</throughput-input-autopilot-v3> </throughput-input-autopilot-v3>

View File

@@ -57,7 +57,6 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
public canThroughputExceedMaximumValue: ko.Computed<boolean>; public canThroughputExceedMaximumValue: ko.Computed<boolean>;
public costsVisible: ko.Computed<boolean>; public costsVisible: ko.Computed<boolean>;
public displayedError: ko.Observable<string>; public displayedError: ko.Observable<string>;
public isFreeTierAccount: ko.Computed<boolean>;
public isTemplateReady: ko.Observable<boolean>; public isTemplateReady: ko.Observable<boolean>;
public minRUAnotationVisible: ko.Computed<boolean>; public minRUAnotationVisible: ko.Computed<boolean>;
public minRUs: ko.Observable<number>; public minRUs: ko.Observable<number>;
@@ -83,7 +82,6 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
public throughputAutoPilotRadioId: string; public throughputAutoPilotRadioId: string;
public throughputProvisionedRadioId: string; public throughputProvisionedRadioId: string;
public throughputModeRadioName: string; public throughputModeRadioName: string;
public freeTierExceedThroughputWarning: ko.Computed<string>;
private _hasProvisioningTypeChanged: ko.Computed<boolean>; private _hasProvisioningTypeChanged: ko.Computed<boolean>;
private _wasAutopilotOriginallySet: ko.Observable<boolean>; private _wasAutopilotOriginallySet: ko.Observable<boolean>;
@@ -361,17 +359,6 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
this.isTemplateReady = ko.observable<boolean>(false); this.isTemplateReady = ko.observable<boolean>(false);
this.isFreeTierAccount = ko.computed<boolean>(() => {
const databaseAccount = this.container?.databaseAccount();
return databaseAccount?.properties?.enableFreeTier;
});
this.freeTierExceedThroughputWarning = ko.computed<string>(() =>
this.isFreeTierAccount()
? "Billing will apply if you provision more than 400 RU/s of manual throughput, or if the resource scales beyond 400 RU/s with autoscale."
: ""
);
this._buildCommandBarOptions(); this._buildCommandBarOptions();
} }

View File

@@ -324,6 +324,21 @@ export default class QueryTab extends TabsBase implements ViewModels.WaitsForTem
queryResults.itemCount > 0 ? `${queryResults.firstItemIndex} - ${queryResults.lastItemIndex}` : `0 - 0`; queryResults.itemCount > 0 ? `${queryResults.firstItemIndex} - ${queryResults.lastItemIndex}` : `0 - 0`;
this.showingDocumentsDisplayText(resultsDisplay); this.showingDocumentsDisplayText(resultsDisplay);
this.requestChargeDisplayText(`${queryResults.requestCharge} RUs`); this.requestChargeDisplayText(`${queryResults.requestCharge} RUs`);
if (!this.queryResults() && !results) {
const errorMessage: string = JSON.stringify({
error: `Returned no results after query execution`,
accountName: this.collection && this.collection.container.databaseAccount(),
databaseName: this.collection && this.collection.databaseId,
collectionName: this.collection && this.collection.id(),
sqlQuery: this.sqlStatementToExecute(),
hasMoreResults: resultsMetadata.hasMoreResults,
itemCount: resultsMetadata.itemCount,
responseHeaders: queryResults && queryResults.headers
});
Logger.logError(errorMessage, "QueryTab");
}
this.queryResults(results); this.queryResults(results);
TelemetryProcessor.traceSuccess( TelemetryProcessor.traceSuccess(

242
src/HostedExplorer.tsx Normal file
View File

@@ -0,0 +1,242 @@
import { Configuration, PublicClientApplication } from "@azure/msal-browser";
import { AuthenticatedTemplate, MsalProvider, UnauthenticatedTemplate } from "@azure/msal-react";
import { useBoolean } from "@uifabric/react-hooks";
import {
DefaultButton,
DirectionalHint,
FocusZone,
initializeIcons,
Panel,
Persona,
PersonaInitialsColor,
PersonaSize
} from "office-ui-fabric-react";
import * as React from "react";
import { render } from "react-dom";
import FeedbackIcon from "../images/Feedback.svg";
import ConnectIcon from "../images/HostedConnectwhite.svg";
import "../less/hostedexplorer.less";
import { CommandButtonComponent } from "./Explorer/Controls/CommandButton/CommandButtonComponent";
import { DefaultDirectoryDropdownComponent } from "./Explorer/Controls/Directory/DefaultDirectoryDropdownComponent";
import { DirectoryListComponent } from "./Explorer/Controls/Directory/DirectoryListComponent";
import "./Explorer/Menus/NavBar/MeControlComponent.less";
import { useGraphProfile } from "./hooks/useGraphProfile";
import "./Shared/appInsights";
initializeIcons();
// MSAL configuration
const configuration: Configuration = {
auth: {
clientId: "e8ae3d28-de2a-4dc8-8fa3-2d2998b1c38f",
redirectUri: "https://localhost:1234/hostedExplorer.html",
authority: "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47"
}
};
const application = new PublicClientApplication(configuration);
const App: React.FunctionComponent = () => {
const [isOpen, { setTrue: openPanel, setFalse: dismissPanel }] = useBoolean(false);
const { graphData, photo } = useGraphProfile();
const menuProps = {
className: "mecontrolContextualMenu",
isBeakVisible: false,
directionalHintFixed: true,
directionalHint: DirectionalHint.bottomRightEdge,
calloutProps: {
minPagePadding: 0
},
items: [
{
key: "Persona",
onRender: () => <Persona />
},
{
key: "SwitchDirectory",
onRender: () => (
<div className="switchDirectoryLink" onClick={() => openPanel}>
Switch Directory
</div>
)
},
{
key: "SignOut",
onRender: () => (
<div
className="signOutLink"
onClick={() => {
instance.logout();
}}
>
Sign out
</div>
)
}
]
};
const personaProps = {};
// {
// id: "commandbutton-settings",
// iconSrc: SettingsIcon,
// iconAlt: "setting button",
// onCommandClick: () => {},
// commandButtonLabel: undefined,
// ariaLabel: "setting button",
// tooltipText: "Global settings",
// hasPopup: true,
// disabled: false
// },
// {
// id: "commandbutton-feedback",
// iconSrc: FeedbackIcon,
// iconAlt: "feeback button",
// onCommandClick: () =>
// window.open(
// "https://aka.ms/cosmosdbfeedback?subject=Cosmos%20DB%20Hosted%20Data%20Explorer%20Feedback"
// ),
// commandButtonLabel: undefined,
// ariaLabel: "feeback button",
// tooltipText: "Send feedback",
// hasPopup: true,
// disabled: false
// }
const buttonProps = {
id: "mecontrolHeader",
className: "mecontrolHeaderButton",
menuProps: menuProps,
onRenderMenuIcon: () => <span />,
styles: {
rootHovered: { backgroundColor: "#393939" },
rootFocused: { backgroundColor: "#393939" },
rootPressed: { backgroundColor: "#393939" },
rootExpanded: { backgroundColor: "#393939" }
}
};
return (
<div>
<header>
<div className="items" role="menubar">
<div className="cosmosDBTitle">
<span
className="title"
data-bind="click: openAzurePortal, event: { keypress: onOpenAzurePortalKeyPress }"
tabIndex={0}
title="Go to Azure Portal"
>
Microsoft Azure
</span>
<span className="accontSplitter" /> <span className="serviceTitle">Cosmos DB</span>
<img
className="chevronRight"
src="/chevron-right.svg"
alt="account separator"
data-bind="visible: isAccountActive"
/>
<span
className="accountSwitchComponentContainer"
data-bind="react: accountSwitchComponentAdapter, visible: isAccountActive"
/>
</div>
<div className="feedbackConnectSettingIcons">
<AuthenticatedTemplate>
<CommandButtonComponent
id="commandbutton-connect"
iconSrc={ConnectIcon}
iconAlt="connect button"
onCommandClick={() => {}}
ariaLabel="connect button"
tooltipText="Connect to a Cosmos DB account"
hasPopup={true}
disabled={false}
/>
</AuthenticatedTemplate>
<UnauthenticatedTemplate>
<CommandButtonComponent
id="commandbutton-feedback"
iconSrc={FeedbackIcon}
iconAlt="feeback button"
onCommandClick={() =>
window.open(
"https://aka.ms/cosmosdbfeedback?subject=Cosmos%20DB%20Hosted%20Data%20Explorer%20Feedback"
)
}
ariaLabel="feeback button"
tooltipText="Send feedback"
hasPopup={true}
disabled={false}
/>
</UnauthenticatedTemplate>
</div>
<div className="meControl">
<AuthenticatedTemplate>
<FocusZone>
<DefaultButton {...buttonProps}>
<Persona
imageUrl={photo}
text={graphData?.displayName}
secondaryText={graphData?.displayName}
showSecondaryText={true}
showInitialsUntilImageLoads={true}
initialsColor={PersonaInitialsColor.teal}
size={PersonaSize.size28}
className="mecontrolHeaderPersona"
/>
</DefaultButton>
</FocusZone>
</AuthenticatedTemplate>
<UnauthenticatedTemplate>
<DefaultButton
className="mecontrolSigninButton"
text="Sign In"
onClick={() => {
instance.loginPopup();
}}
styles={{
rootHovered: { backgroundColor: "#393939", color: "#fff" },
rootFocused: { backgroundColor: "#393939", color: "#fff" },
rootPressed: { backgroundColor: "#393939", color: "#fff" }
}}
/>
</UnauthenticatedTemplate>
</div>
</div>
</header>
{/* <iframe
id="explorerMenu"
name="explorer"
className="iframe"
title="explorer"
src="explorer.html?v=1.0.1&platform=Hosted"
data-bind="visible: navigationSelection() === 'explorer'"
></iframe> */}
<div data-bind="react: firewallWarningComponentAdapter" />
<div data-bind="react: dialogComponentAdapter" />
<Panel
headerText="Select Directory"
isOpen={!isOpen}
onDismiss={dismissPanel}
// You MUST provide this prop! Otherwise screen readers will just say "button" with no label.
closeButtonAriaLabel="Close"
>
<div className="directoryDropdownContainer">
<DefaultDirectoryDropdownComponent />
</div>
<div className="directoryDivider" />
<div className="directoryListContainer">
<DirectoryListComponent />
</div>
</Panel>
</div>
);
};
render(
<MsalProvider instance={application}>
<App />
</MsalProvider>,
document.body
);

View File

@@ -44,7 +44,6 @@ import "./Libs/jquery";
import "bootstrap/dist/js/npm"; import "bootstrap/dist/js/npm";
import "../externals/jquery.typeahead.min.js"; import "../externals/jquery.typeahead.min.js";
import "../externals/jquery-ui.min.js"; import "../externals/jquery-ui.min.js";
import "../externals/adal.js";
import "promise-polyfill/src/polyfill"; import "promise-polyfill/src/polyfill";
import "abort-controller/polyfill"; import "abort-controller/polyfill";
import "whatwg-fetch"; import "whatwg-fetch";

View File

@@ -1,5 +1,3 @@
import "expose-loader?AuthenticationContext!../../../externals/adal";
import Q from "q"; import Q from "q";
import * as Constants from "../../Common/Constants"; import * as Constants from "../../Common/Constants";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";

View File

@@ -2,42 +2,33 @@ import * as Constants from "../../../Common/Constants";
import * as DataModels from "../../../Contracts/DataModels"; import * as DataModels from "../../../Contracts/DataModels";
export class ConnectionStringParser { export class ConnectionStringParser {
public static parseConnectionString(connectionString: string): DataModels.AccessInputMetadata | undefined { public static parseConnectionString(connectionString: string): DataModels.AccessInputMetadata {
if (!!connectionString) { if (!!connectionString) {
try { try {
const accessInput: DataModels.AccessInputMetadata = {} as DataModels.AccessInputMetadata; const accessInput: DataModels.AccessInputMetadata = {} as DataModels.AccessInputMetadata;
const connectionStringParts = connectionString.split(";"); const connectionStringParts = connectionString.split(";");
connectionStringParts.forEach((connectionStringPart: string) => { connectionStringParts.forEach((connectionStringPart: string) => {
const sqlMatchResult = connectionStringPart.match(Constants.EndpointsRegex.sql); if (RegExp(Constants.EndpointsRegex.sql).test(connectionStringPart)) {
const mongoMatchResult = connectionStringPart.match(Constants.EndpointsRegex.mongo); accessInput.accountName = connectionStringPart.match(Constants.EndpointsRegex.sql)[1];
const mongoComputeMatchResult = connectionStringPart.match(Constants.EndpointsRegex.mongoCompute);
const tableMatchResult = connectionStringPart.match(Constants.EndpointsRegex.table);
if (sqlMatchResult && sqlMatchResult.length > 1) {
accessInput.accountName = sqlMatchResult[1];
accessInput.apiKind = DataModels.ApiKind.SQL; accessInput.apiKind = DataModels.ApiKind.SQL;
} else if (mongoMatchResult && mongoMatchResult.length > 2) { } else if (RegExp(Constants.EndpointsRegex.mongo).test(connectionStringPart)) {
accessInput.accountName = mongoMatchResult[2]; const matches: string[] = connectionStringPart.match(Constants.EndpointsRegex.mongo);
accessInput.accountName = matches && matches.length > 1 && matches[2];
accessInput.apiKind = DataModels.ApiKind.MongoDB; accessInput.apiKind = DataModels.ApiKind.MongoDB;
} else if (mongoComputeMatchResult && mongoComputeMatchResult.length > 2) { } else if (RegExp(Constants.EndpointsRegex.mongoCompute).test(connectionStringPart)) {
accessInput.accountName = mongoComputeMatchResult[2]; const matches: string[] = connectionStringPart.match(Constants.EndpointsRegex.mongoCompute);
accessInput.accountName = matches && matches.length > 1 && matches[2];
accessInput.apiKind = DataModels.ApiKind.MongoDBCompute; accessInput.apiKind = DataModels.ApiKind.MongoDBCompute;
} else if ( } else if (Constants.EndpointsRegex.cassandra.some(regex => RegExp(regex).test(connectionStringPart))) {
Constants.EndpointsRegex.cassandra &&
Constants.EndpointsRegex.cassandra.some(regex => RegExp(regex).test(connectionStringPart))
) {
Constants.EndpointsRegex.cassandra.forEach(regex => { Constants.EndpointsRegex.cassandra.forEach(regex => {
if (RegExp(regex).test(connectionStringPart)) { if (RegExp(regex).test(connectionStringPart)) {
const connectionMatch = connectionStringPart.match(regex); accessInput.accountName = connectionStringPart.match(regex)[1];
if (connectionMatch && connectionMatch.length > 1) { accessInput.apiKind = DataModels.ApiKind.Cassandra;
accessInput.accountName = connectionMatch[1];
accessInput.apiKind = DataModels.ApiKind.Cassandra;
}
} }
}); });
} else if (tableMatchResult && tableMatchResult.length > 1) { } else if (RegExp(Constants.EndpointsRegex.table).test(connectionStringPart)) {
accessInput.accountName = tableMatchResult[1]; accessInput.accountName = connectionStringPart.match(Constants.EndpointsRegex.table)[1];
accessInput.apiKind = DataModels.ApiKind.Table; accessInput.apiKind = DataModels.ApiKind.Table;
} else if (connectionStringPart.indexOf("ApiKind=Gremlin") >= 0) { } else if (connectionStringPart.indexOf("ApiKind=Gremlin") >= 0) {
accessInput.apiKind = DataModels.ApiKind.Graph; accessInput.apiKind = DataModels.ApiKind.Graph;

View File

@@ -4,7 +4,7 @@ import * as DataModels from "../Contracts/DataModels";
import { DefaultAccountExperienceType } from "../DefaultAccountExperienceType"; import { DefaultAccountExperienceType } from "../DefaultAccountExperienceType";
export class DefaultExperienceUtility { export class DefaultExperienceUtility {
public static getDefaultExperienceFromDatabaseAccount(databaseAccount: DataModels.DatabaseAccount): string | null { public static getDefaultExperienceFromDatabaseAccount(databaseAccount: DataModels.DatabaseAccount): string {
if (!databaseAccount) { if (!databaseAccount) {
return null; return null;
} }
@@ -81,9 +81,11 @@ export class DefaultExperienceUtility {
private static _getDefaultExperience(kind: string, capabilities: DataModels.Capability[]): string { private static _getDefaultExperience(kind: string, capabilities: DataModels.Capability[]): string {
const defaultDefaultExperience: string = Constants.DefaultAccountExperience.DocumentDB; const defaultDefaultExperience: string = Constants.DefaultAccountExperience.DocumentDB;
const defaultExperienceFromKind: string = DefaultExperienceUtility._getDefaultExperienceFromAccountKind(kind) || ""; const defaultExperienceFromKind: string = DefaultExperienceUtility._getDefaultExperienceFromAccountKind(kind);
const defaultExperienceFromCapabilities: string = const defaultExperienceFromCapabilities: string = DefaultExperienceUtility._getDefaultExperienceFromAccountCapabilities(
DefaultExperienceUtility._getDefaultExperienceFromAccountCapabilities(capabilities) || ""; capabilities
);
if (!!defaultExperienceFromKind) { if (!!defaultExperienceFromKind) {
return defaultExperienceFromKind; return defaultExperienceFromKind;
} }
@@ -95,7 +97,7 @@ export class DefaultExperienceUtility {
return defaultDefaultExperience; return defaultDefaultExperience;
} }
private static _getDefaultExperienceFromAccountKind(kind: string): string | null { private static _getDefaultExperienceFromAccountKind(kind: string): string {
if (!kind) { if (!kind) {
return null; return null;
} }
@@ -111,7 +113,7 @@ export class DefaultExperienceUtility {
return null; return null;
} }
private static _getDefaultExperienceFromAccountCapabilities(capabilities: DataModels.Capability[]): string | null { private static _getDefaultExperienceFromAccountCapabilities(capabilities: DataModels.Capability[]): string {
if (!capabilities) { if (!capabilities) {
return null; return null;
} }

View File

@@ -1,6 +1,5 @@
import * as AutoPilotUtils from "../Utils/AutoPilotUtils"; import * as AutoPilotUtils from "../Utils/AutoPilotUtils";
import * as Constants from "../Shared/Constants"; import * as Constants from "../Shared/Constants";
import { DefaultAccountExperienceType } from "../DefaultAccountExperienceType";
interface ComputeRUUsagePriceHourlyArgs { interface ComputeRUUsagePriceHourlyArgs {
serverId: string; serverId: string;
@@ -257,19 +256,9 @@ export function getEstimatedSpendAcknowledgeString(
)} - ${currencySign}${calculateEstimateNumber(monthlyPrice)} monthly cost for the throughput above.`; )} - ${currencySign}${calculateEstimateNumber(monthlyPrice)} monthly cost for the throughput above.`;
} }
export function getUpsellMessage( export function getUpsellMessage(serverId = "default", isFreeTier = false): string {
serverId = "default",
isFreeTier = false,
isFirstResourceCreated = false,
defaultExperience: string,
isCollection: boolean
): string {
if (isFreeTier) { if (isFreeTier) {
const collectionName = getCollectionName(defaultExperience); return "With free tier discount, you'll get the first 400 RU/s and 5 GB of storage in this account for free. Charges will apply if your resource throughput exceeds 400 RU/s.";
const resourceType = isCollection ? collectionName : "database";
return isFirstResourceCreated
? `The free tier discount of 400 RU/s has already been applied to a database or ${collectionName} in this account. Billing will apply to this ${resourceType} after it is created.`
: `With free tier, you'll get the first 400 RU/s and 5 GB of storage in this account for free. Billing will apply if you provision more than 400 RU/s of manual throughput, or if the ${resourceType} scales beyond 400 RU/s with autoscale.`;
} else { } else {
let price: number = Constants.OfferPricing.MonthlyPricing.default.Standard.StartingPrice; let price: number = Constants.OfferPricing.MonthlyPricing.default.Standard.StartingPrice;
@@ -280,19 +269,3 @@ export function getUpsellMessage(
return `Start at ${getCurrencySign(serverId)}${price}/mo per database, multiple containers included`; return `Start at ${getCurrencySign(serverId)}${price}/mo per database, multiple containers included`;
} }
} }
function getCollectionName(defaultExperience: string): string {
switch (defaultExperience) {
case DefaultAccountExperienceType.DocumentDB:
return "container";
case DefaultAccountExperienceType.MongoDB:
return "collection";
case DefaultAccountExperienceType.Table:
case DefaultAccountExperienceType.Cassandra:
return "table";
case DefaultAccountExperienceType.Graph:
return "graph";
default:
throw Error("unknown API type");
}
}

View File

@@ -0,0 +1,74 @@
import { useAccount, useMsal } from "@azure/msal-react";
import { useEffect, useState } from "react";
export async function fetchMe(accessToken: string): Promise<GraphMeResponse> {
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
const options = {
method: "GET",
headers: headers
};
console.log("EXECUTING REQUEST");
return fetch("https://graph.microsoft.com/v1.0/me", options)
.then(response => response.json())
.catch(error => console.log(error));
}
export async function fetchPhoto(accessToken: string): Promise<Blob | void> {
const headers = new Headers();
const bearer = `Bearer ${accessToken}`;
headers.append("Authorization", bearer);
headers.append("Content-Type", "image/jpg");
const options = {
method: "GET",
headers: headers
};
console.log("EXECUTING REQUEST");
return fetch("https://graph.microsoft.com/v1.0/me/photo/$value", options)
.then(response => response.blob())
.catch(error => console.log(error));
}
interface GraphMeResponse {
businessPhones: any[];
displayName: string;
givenName: string;
jobTitle: string;
mail: string;
mobilePhone: null;
officeLocation: string;
preferredLanguage: null;
surname: string;
userPrincipalName: string;
id: string;
}
export function useGraphProfile(): { graphData: GraphMeResponse; photo: string } {
const { instance, accounts } = useMsal();
const account = useAccount(accounts[0] || {});
const [graphData, setGraphData] = useState<GraphMeResponse>();
const [photo, setPhoto] = useState<string>();
useEffect(() => {
console.log("account", account);
if (account) {
instance
.acquireTokenSilent({
scopes: ["User.Read"],
account
})
.then(response => {
fetchMe(response.accessToken).then(response => setGraphData(response));
fetchPhoto(response.accessToken).then(response => setPhoto(URL.createObjectURL(response)));
});
}
}, [account]);
return { graphData, photo };
}

View File

@@ -7,59 +7,5 @@
</head> </head>
<body> <body>
<header>
<div class="items" role="menubar">
<div class="cosmosDBTitle">
<span
class="title"
data-bind="click: openAzurePortal, event: { keypress: onOpenAzurePortalKeyPress }"
tabindex="0"
title="Go to Azure Portal"
>Microsoft Azure</span
>
<span class="accontSplitter"></span> <span class="serviceTitle">Cosmos DB</span>
<img
class="chevronRight"
src="/chevron-right.svg"
alt="account separator"
data-bind="visible: isAccountActive"
/>
<span
class="accountSwitchComponentContainer"
data-bind="react: accountSwitchComponentAdapter, visible: isAccountActive"
></span>
</div>
<div class="feedbackConnectSettingIcons" data-bind="react: controlBarComponentAdapter"></div>
<div class="meControl" data-bind="react: meControlComponentAdapter"></div>
</div>
</header>
<!-- TODO display after introducing multiple account access -->
<nav class="fixedleftpane" style="display: none;">
<div class="fixedLeftPaneIcons"><img src="/Hamburger.svg" alt="Expand" /></div>
<div class="fixedLeftPaneIcons"><img src="/Connect.svg" alt="Connect to an account" /></div>
<div
class="fixedLeftPaneIcons"
data-bind="click: explorer_click, css:{ topSelected: navigationSelection() === 'explorer' }"
>
<img src="/HostedExplorer.svg" alt="Open Data Explorer" />
</div>
</nav>
<switch-directory-pane params="{data: switchDirectoryPane}"></switch-directory-pane>
<!-- TODO generate version number dynamically -->
<iframe
id="explorerMenu"
name="explorer"
class="iframe"
title="explorer"
src="explorer.html?v=1.0.1&platform=Hosted"
data-bind="visible: navigationSelection() === 'explorer'"
>
</iframe>
<div data-bind="react: firewallWarningComponentAdapter"></div>
<div data-bind="react: dialogComponentAdapter"></div>
</body> </body>
</html> </html>

View File

@@ -12,8 +12,7 @@
"./src/Bindings/ReactBindingHandler.ts", "./src/Bindings/ReactBindingHandler.ts",
"./src/Common/ArrayHashMap.ts", "./src/Common/ArrayHashMap.ts",
"./src/Common/Constants.ts", "./src/Common/Constants.ts",
"./src/Common/DeleteFeedback.ts", "./src/Common/DeleteFeedback.ts",
"./src/Common/DocumentUtility.ts",
"./src/Common/EnvironmentUtility.ts", "./src/Common/EnvironmentUtility.ts",
"./src/Common/HashMap.ts", "./src/Common/HashMap.ts",
"./src/Common/HeadersUtility.ts", "./src/Common/HeadersUtility.ts",
@@ -22,8 +21,7 @@
"./src/Common/MongoUtility.ts", "./src/Common/MongoUtility.ts",
"./src/Common/ObjectCache.ts", "./src/Common/ObjectCache.ts",
"./src/Common/ThemeUtility.ts", "./src/Common/ThemeUtility.ts",
"./src/Common/UrlUtility.ts", "./src/Common/UrlUtility.ts",
"./src/Common/Splitter.ts",
"./src/ConfigContext.ts", "./src/ConfigContext.ts",
"./src/Contracts/ActionContracts.ts", "./src/Contracts/ActionContracts.ts",
"./src/Contracts/DataModels.ts", "./src/Contracts/DataModels.ts",
@@ -62,8 +60,6 @@
"./src/GitHub/GitHubConnector.ts", "./src/GitHub/GitHubConnector.ts",
"./src/Index.ts", "./src/Index.ts",
"./src/NotebookWorkspaceManager/NotebookWorkspaceResourceProviderMockClients.ts", "./src/NotebookWorkspaceManager/NotebookWorkspaceResourceProviderMockClients.ts",
"./src/Platform/Hosted/Helpers/ConnectionStringParser.ts",
"./src/Platform/Hosted/HostedUtils.ts",
"./src/ReactDevTools.ts", "./src/ReactDevTools.ts",
"./src/ResourceProvider/IResourceProviderClient.ts", "./src/ResourceProvider/IResourceProviderClient.ts",
"./src/Shared/Constants.ts", "./src/Shared/Constants.ts",

View File

@@ -182,7 +182,7 @@ module.exports = function(env = {}, argv = {}) {
main: "./src/Main.tsx", main: "./src/Main.tsx",
index: "./src/Index.ts", index: "./src/Index.ts",
quickstart: "./src/quickstart.ts", quickstart: "./src/quickstart.ts",
hostedExplorer: "./src/HostedExplorer.ts", hostedExplorer: "./src/HostedExplorer.tsx",
testExplorer: "./test/notebooks/testExplorer/TestExplorer.ts", testExplorer: "./test/notebooks/testExplorer/TestExplorer.ts",
heatmap: "./src/Controls/Heatmap/Heatmap.ts", heatmap: "./src/Controls/Heatmap/Heatmap.ts",
terminal: "./src/Terminal/index.ts", terminal: "./src/Terminal/index.ts",