Free tier improvements in DE (#348)
Co-authored-by: Steve Faulkner <southpolesteve@gmail.com>
This commit is contained in:
parent
d40b1aa9b5
commit
a55f2d0de9
|
@ -4,7 +4,7 @@
|
|||
|
||||
@font-face {
|
||||
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;
|
||||
|
@ -20,26 +20,26 @@
|
|||
COLORS
|
||||
/******************************************************************************/
|
||||
|
||||
@AccentMediumHigh: #0058AD;
|
||||
@AccentMedium: #004E87;
|
||||
@AccentHigh: #1EBAED;
|
||||
@AccentExtraHigh: #55B3FF;
|
||||
@AccentLow: #EDF6FF;
|
||||
@AccentMediumLow: #DDEEFE;
|
||||
@AccentLight: #EEF7FF;
|
||||
@AccentExtra: #DDF0FF;
|
||||
@AccentMediumHigh: #0058ad;
|
||||
@AccentMedium: #004e87;
|
||||
@AccentHigh: #1ebaed;
|
||||
@AccentExtraHigh: #55b3ff;
|
||||
@AccentLow: #edf6ff;
|
||||
@AccentMediumLow: #ddeefe;
|
||||
@AccentLight: #eef7ff;
|
||||
@AccentExtra: #ddf0ff;
|
||||
|
||||
@SelectionHigh: #B91F26;
|
||||
@BaseLight: #FFFFFF;
|
||||
@SelectionHigh: #b91f26;
|
||||
@BaseLight: #ffffff;
|
||||
@BaseDark: #000000;
|
||||
@NotificationLow: #FFF4CE;
|
||||
@NotificationHigh: #F9E9B0;
|
||||
@Purple1: #8A2DA5;
|
||||
@NotificationLow: #fff4ce;
|
||||
@NotificationHigh: #f9e9b0;
|
||||
@Purple1: #8a2da5;
|
||||
@Dirty: #9b4f96;
|
||||
|
||||
@BaseLow: #F2F2F2;
|
||||
@BaseMediumLow: #E6E6E6;
|
||||
@BaseMedium: #CCCCCC;
|
||||
@BaseLow: #f2f2f2;
|
||||
@BaseMediumLow: #e6e6e6;
|
||||
@BaseMedium: #cccccc;
|
||||
@BaseMediumHigh: #767676;
|
||||
@BaseHigh: #393939;
|
||||
|
||||
|
@ -53,7 +53,7 @@
|
|||
|
||||
@ErrorColor: @SelectionHigh;
|
||||
|
||||
@SelectionColor: #3074B0;
|
||||
@SelectionColor: #3074b0;
|
||||
|
||||
@FocusColor: #605e5c;
|
||||
|
||||
|
@ -165,8 +165,8 @@
|
|||
.selectedRadio:hover,
|
||||
.selectedRadio:active,
|
||||
.selectedRadio.dirty,
|
||||
.tab [type=radio]:checked ~ label,
|
||||
.tab [type=radio]:checked ~ label:hover {
|
||||
.tab [type="radio"]:checked ~ label,
|
||||
.tab [type="radio"]:checked ~ label:hover {
|
||||
-ms-high-contrast-adjust: none;
|
||||
-webkit-text-fill-color: HighlightText;
|
||||
color: HighlightText;
|
||||
|
@ -175,9 +175,8 @@
|
|||
}
|
||||
|
||||
.queryMetricsSummaryTuple {
|
||||
|
||||
th, td {
|
||||
|
||||
th,
|
||||
td {
|
||||
&:nth-child(2) {
|
||||
width: @IETableDataWidth;
|
||||
}
|
||||
|
@ -272,3 +271,27 @@
|
|||
.tooltipVisible() {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ body {
|
|||
height: 100%;
|
||||
|
||||
:focus {
|
||||
.focus()
|
||||
.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ body {
|
|||
right: 14px;
|
||||
border-width: 0 9px 9px;
|
||||
border-style: solid;
|
||||
border-color: #FFF rgba(0, 0, 0, 0);
|
||||
border-color: #fff rgba(0, 0, 0, 0);
|
||||
display: block;
|
||||
width: 0;
|
||||
}
|
||||
|
@ -88,7 +88,6 @@ body {
|
|||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
|
||||
.urlContainer {
|
||||
margin-left: @DefaultSpace;
|
||||
|
||||
|
@ -179,7 +178,8 @@ body {
|
|||
.active();
|
||||
}
|
||||
|
||||
&:focus .urlTokenCopyTooltiptext, &:focus .urlTokenCopyTooltiptext {
|
||||
&:focus .urlTokenCopyTooltiptext,
|
||||
&:focus .urlTokenCopyTooltiptext {
|
||||
.tooltipVisible();
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ body {
|
|||
|
||||
.shareLink {
|
||||
width: 300px;
|
||||
background-color: #FFFFFF;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid @BaseMedium;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -722,7 +722,8 @@ stored-procedure-tab {
|
|||
@ToggleHeight: 30px;
|
||||
@ToggleWidth: 180px;
|
||||
|
||||
.results-container, .errors-container {
|
||||
.results-container,
|
||||
.errors-container {
|
||||
padding: @MediumSpace 0px 0px @MediumSpace;
|
||||
height: 100%;
|
||||
.flex-display();
|
||||
|
@ -934,19 +935,19 @@ menuQuickStart {
|
|||
.content {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
transition: all .4s ease-in-out;
|
||||
-ms-transition: all .4s ease-in-out;
|
||||
-webkit-transition: all .4s ease-in-out;
|
||||
-moz-transition: all .4s ease-in-out;
|
||||
transition: all 0.4s ease-in-out;
|
||||
-ms-transition: all 0.4s ease-in-out;
|
||||
-webkit-transition: all 0.4s ease-in-out;
|
||||
-moz-transition: all 0.4s ease-in-out;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.mini {
|
||||
width: 0%;
|
||||
float: left;
|
||||
transition: all .4s ease-in-out;
|
||||
-webkit-transition: all .4s ease-in-out;
|
||||
-moz-transition: all .4s ease-in-out;
|
||||
transition: all 0.4s ease-in-out;
|
||||
-webkit-transition: all 0.4s ease-in-out;
|
||||
-moz-transition: all 0.4s ease-in-out;
|
||||
height: 100vh;
|
||||
background-color: white;
|
||||
}
|
||||
|
@ -1097,7 +1098,7 @@ menuQuickStart {
|
|||
}
|
||||
|
||||
#tbodycontent > tr > td {
|
||||
border-bottom: 1px solid #CCCCCC;
|
||||
border-bottom: 1px solid #cccccc;
|
||||
border-top: none;
|
||||
padding: 6px;
|
||||
}
|
||||
|
@ -1205,7 +1206,7 @@ menuQuickStart {
|
|||
|
||||
.gridRowSelected:hover {
|
||||
cursor: default;
|
||||
.hover()
|
||||
.hover();
|
||||
}
|
||||
|
||||
.gridRowHighlighted {
|
||||
|
@ -1240,7 +1241,7 @@ menuQuickStart {
|
|||
border-top: 1px solid #eee;
|
||||
margin-left: -17px;
|
||||
width: 100%;
|
||||
color: 1px solid #53575B;
|
||||
color: 1px solid #53575b;
|
||||
}
|
||||
|
||||
.partitioning-btn {
|
||||
|
@ -1308,7 +1309,7 @@ menuQuickStart {
|
|||
|
||||
.collid-white {
|
||||
width: 100%;
|
||||
border: solid 1px #DDD;
|
||||
border: solid 1px #ddd;
|
||||
}
|
||||
|
||||
.plusimg-but {
|
||||
|
@ -1526,6 +1527,21 @@ p {
|
|||
color: @AccentHigh;
|
||||
}
|
||||
|
||||
.inputTooltip {
|
||||
.inputTooltip();
|
||||
}
|
||||
|
||||
.inputTooltip .inputTooltipText {
|
||||
top: -68px;
|
||||
.inputTooltipText();
|
||||
}
|
||||
|
||||
.inputTooltip .inputTooltipText::after {
|
||||
border-width: @MediumSpace @MediumSpace 0 @MediumSpace;
|
||||
top: 55px;
|
||||
.inputTooltipTextAfter();
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -1631,7 +1647,6 @@ p {
|
|||
margin-left: -32px;
|
||||
}
|
||||
|
||||
|
||||
/* Variant of paddingspan3 without the margins */
|
||||
|
||||
.contextual-pane .paddingspan3b {
|
||||
|
@ -1644,7 +1659,7 @@ p {
|
|||
}
|
||||
|
||||
.contextual-pane hr {
|
||||
border: 1px solid #53575B;
|
||||
border: 1px solid #53575b;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
|
@ -1818,11 +1833,11 @@ label {
|
|||
|
||||
.datalist-arrow:focus:after,
|
||||
.datalist-arrow:active:after {
|
||||
background: #1EBBEE;
|
||||
background: #1ebbee;
|
||||
}
|
||||
|
||||
input::-webkit-calendar-picker-indicator::after {
|
||||
content: '\276F';
|
||||
content: "\276F";
|
||||
right: 0;
|
||||
top: -8%;
|
||||
display: block;
|
||||
|
@ -1836,7 +1851,7 @@ input::-webkit-calendar-picker-indicator::after {
|
|||
}
|
||||
|
||||
.datalist-arrow:after:hover {
|
||||
content: '\276F';
|
||||
content: "\276F";
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
top: 6%;
|
||||
|
@ -1848,7 +1863,7 @@ input::-webkit-calendar-picker-indicator::after {
|
|||
color: #fff;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
background-color: #1EBBEE;
|
||||
background-color: #1ebbee;
|
||||
}
|
||||
|
||||
.Introline3 {
|
||||
|
@ -1912,7 +1927,7 @@ input::-webkit-calendar-picker-indicator::after {
|
|||
|
||||
.nav-tabs-margin {
|
||||
padding-top: 8px;
|
||||
background-color: #F2F2F2;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.navTabHeight {
|
||||
|
@ -1978,7 +1993,7 @@ input::-webkit-calendar-picker-indicator::after {
|
|||
.atags {
|
||||
color: @AccentMediumHigh;
|
||||
font-weight: 400;
|
||||
cursor: pointer
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.qsmenuicons {
|
||||
|
@ -2218,7 +2233,7 @@ a:link {
|
|||
.documentsGridHeaderContainer {
|
||||
padding-left: 5px;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #CCCCCC;
|
||||
border-bottom: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
.documentsGridHeaderContainer > table {
|
||||
|
@ -2234,7 +2249,7 @@ a:link {
|
|||
position: sticky;
|
||||
top: 0;
|
||||
background-color: #fff !important;
|
||||
border-bottom: 1px solid #CCCCCC !important;
|
||||
border-bottom: 1px solid #cccccc !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2383,7 +2398,7 @@ a:link {
|
|||
color: #393939;
|
||||
}
|
||||
|
||||
.tab [type=radio] {
|
||||
.tab [type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -2395,40 +2410,40 @@ a:link {
|
|||
padding: @MediumSpace 0px;
|
||||
}
|
||||
|
||||
.tab [type=radio]:checked~label {
|
||||
.tab [type="radio"]:checked ~ label {
|
||||
border: 1px solid #0072c6;
|
||||
background-color: @AccentMediumHigh;
|
||||
color: white;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.tab [type=radio]:checked~label:hover {
|
||||
.tab [type="radio"]:checked ~ label:hover {
|
||||
border: 1px solid @AccentMediumHigh;
|
||||
background-color: @AccentMediumHigh;
|
||||
color: white;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.tab [type=radio]:checked~label:active {
|
||||
.tab [type="radio"]:checked ~ label:active {
|
||||
border: 1px solid #0072c6;
|
||||
background-color: #0072c6;
|
||||
color: white;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.tab [type=radio]:checked~label~.tabcontent {
|
||||
.tab [type="radio"]:checked ~ label ~ .tabcontent {
|
||||
z-index: 1;
|
||||
display: initial;
|
||||
}
|
||||
|
||||
.tab [type=radio]:not(:checked)~label:hover {
|
||||
.tab [type="radio"]:not(:checked) ~ label:hover {
|
||||
border: 1px solid #969696;
|
||||
background-color: #969696;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tab [type=radio]:not(:checked)~label~.tabcontent {
|
||||
.tab [type="radio"]:not(:checked) ~ label ~ .tabcontent {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -2732,7 +2747,7 @@ a:link {
|
|||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
flex-grow: 1
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.tabIconSection {
|
||||
|
@ -2822,17 +2837,17 @@ a:link {
|
|||
}
|
||||
|
||||
.tabCommandDisabled {
|
||||
color: #CCCCCC;
|
||||
color: #cccccc;
|
||||
cursor: default;
|
||||
background-color: #FFFFFF;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.tabCommandDisabled:active {
|
||||
border: 1px solid #FFFFFF;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
.tabCommandDisabled:hover {
|
||||
background-color: #FFFFFF;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#explorerNotificationConsole {
|
||||
|
@ -2940,13 +2955,13 @@ settings-pane {
|
|||
}
|
||||
|
||||
.linkDarkBackground {
|
||||
color: @AccentExtraHigh
|
||||
color: @AccentExtraHigh;
|
||||
}
|
||||
|
||||
.linkDarkBackground:hover,
|
||||
.linkDarkBackground:active,
|
||||
.linkDarkBackground:focus {
|
||||
color: @AccentHigh
|
||||
color: @AccentHigh;
|
||||
}
|
||||
|
||||
.library-add-button {
|
||||
|
@ -2983,7 +2998,7 @@ settings-pane {
|
|||
}
|
||||
|
||||
.enableAnalyticalStorageRadioLabel {
|
||||
padding: 0px
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2993,18 +3008,18 @@ settings-pane {
|
|||
}
|
||||
|
||||
.button.enabled {
|
||||
background: #FFF;
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
color: #323130;
|
||||
padding: 3px 20px;
|
||||
border: 1px solid #8A8886;
|
||||
border: 1px solid #8a8886;
|
||||
}
|
||||
|
||||
.button.disabled {
|
||||
background: #F3F2F1;
|
||||
border: 0px solid #8A8886;
|
||||
background: #f3f2f1;
|
||||
border: 0px solid #8a8886;
|
||||
border-radius: 2px;
|
||||
color: #A19F9D;
|
||||
color: #a19f9d;
|
||||
padding: 3px 20px;
|
||||
}
|
||||
|
||||
|
@ -3017,13 +3032,55 @@ settings-pane {
|
|||
}
|
||||
|
||||
.warningErrorContent a {
|
||||
color: @AccentMediumHigh
|
||||
color: @AccentMediumHigh;
|
||||
}
|
||||
|
||||
.infoBoxContent a {
|
||||
color: @AccentMediumHigh
|
||||
color: @AccentMediumHigh;
|
||||
}
|
||||
|
||||
.collapsibleSection :hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.messageBarInfoIcon {
|
||||
color: #0072c6;
|
||||
}
|
||||
|
||||
.messageBarWarningIcon {
|
||||
color: #db7500;
|
||||
}
|
||||
|
||||
.freeTierInfoBanner {
|
||||
background-color: @BaseLow;
|
||||
display: inline-flex;
|
||||
padding: @DefaultSpace;
|
||||
width: 100%;
|
||||
|
||||
.freeTierInfoIcon img {
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.freeTierInfoMessage {
|
||||
margin: auto 0;
|
||||
padding-left: @MediumSpace;
|
||||
}
|
||||
}
|
||||
|
||||
.freeTierInlineWarning {
|
||||
display: inline-flex;
|
||||
padding: 8px 8px 8px 0;
|
||||
width: 100%;
|
||||
|
||||
.freeTierWarningIcon img {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.freeTierWarningMessage {
|
||||
margin: auto 0;
|
||||
padding-left: @SmallSpace;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ export interface PriceBreakdown {
|
|||
currencySign: string;
|
||||
}
|
||||
|
||||
export const infoAndToolTipTextStyle: ITextStyles = { root: { fontSize: 12 } };
|
||||
export const infoAndToolTipTextStyle: ITextStyles = { root: { fontSize: 14 } };
|
||||
|
||||
export const noLeftPaddingCheckBoxStyle: ICheckboxStyles = {
|
||||
label: {
|
||||
|
@ -166,7 +166,10 @@ export const separatorStyles: Partial<ISeparatorStyles> = {
|
|||
]
|
||||
};
|
||||
|
||||
export const messageBarStyles: Partial<IMessageBarStyles> = { root: { marginTop: "5px" } };
|
||||
export const messageBarStyles: Partial<IMessageBarStyles> = {
|
||||
root: { marginTop: "5px", backgroundColor: "white" },
|
||||
text: { fontSize: 14 }
|
||||
};
|
||||
|
||||
export const throughputUnit = "RU/s";
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ exports[`IndexingPolicyRefreshComponent renders 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import {
|
|||
} from "../SettingsRenderUtils";
|
||||
import { hasDatabaseSharedThroughput } from "../SettingsUtils";
|
||||
import * as AutoPilotUtils from "../../../../Utils/AutoPilotUtils";
|
||||
import { Text, TextField, Stack, Label, MessageBar, MessageBarType } from "office-ui-fabric-react";
|
||||
import { Link, Text, TextField, Stack, Label, MessageBar, MessageBarType } from "office-ui-fabric-react";
|
||||
import { configContext, Platform } from "../../../../ConfigContext";
|
||||
|
||||
export interface ScaleComponentProps {
|
||||
|
@ -176,6 +176,7 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
|
|||
label={this.getThroughputTitle()}
|
||||
isEmulator={this.isEmulator}
|
||||
isFixed={this.props.isFixedContainer}
|
||||
isFreeTierAccount={this.isFreeTierAccount()}
|
||||
isAutoPilotSelected={this.props.isAutoPilotSelected}
|
||||
onAutoPilotSelected={this.props.onAutoPilotSelected}
|
||||
wasAutopilotOriginallySet={this.props.wasAutopilotOriginallySet}
|
||||
|
@ -190,9 +191,37 @@ 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 {
|
||||
return (
|
||||
<Stack {...subComponentStackProps}>
|
||||
{this.isFreeTierAccount() && (
|
||||
<MessageBar
|
||||
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
|
||||
styles={{ text: { fontSize: 14 } }}
|
||||
>
|
||||
{this.getFreeTierInfoMessage()}
|
||||
</MessageBar>
|
||||
)}
|
||||
{this.getInitialNotificationElement() && (
|
||||
<MessageBar messageBarType={MessageBarType.warning}>{this.getInitialNotificationElement()}</MessageBar>
|
||||
)}
|
||||
|
|
|
@ -13,16 +13,7 @@ import {
|
|||
} from "../SettingsUtils";
|
||||
import Explorer from "../../../Explorer";
|
||||
import { Int32 } from "../../../Panes/Tables/Validators/EntityPropertyValidationCommon";
|
||||
import {
|
||||
Label,
|
||||
Text,
|
||||
TextField,
|
||||
Stack,
|
||||
IChoiceGroupOption,
|
||||
ChoiceGroup,
|
||||
MessageBar,
|
||||
MessageBarType
|
||||
} from "office-ui-fabric-react";
|
||||
import { Label, Text, TextField, Stack, IChoiceGroupOption, ChoiceGroup, MessageBar } from "office-ui-fabric-react";
|
||||
import {
|
||||
getTextFieldStyles,
|
||||
changeFeedPolicyToolTip,
|
||||
|
@ -190,7 +181,10 @@ export class SubSettingsComponent extends React.Component<SubSettingsComponentPr
|
|||
styles={getChoiceGroupStyles(this.props.timeToLive, this.props.timeToLiveBaseline)}
|
||||
/>
|
||||
{isDirty(this.props.timeToLive, this.props.timeToLiveBaseline) && this.props.timeToLive === TtlType.On && (
|
||||
<MessageBar messageBarType={MessageBarType.warning} styles={messageBarStyles}>
|
||||
<MessageBar
|
||||
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
|
||||
styles={messageBarStyles}
|
||||
>
|
||||
{ttlWarning}
|
||||
</MessageBar>
|
||||
)}
|
||||
|
|
|
@ -26,6 +26,7 @@ describe("ThroughputInputAutoPilotV3Component", () => {
|
|||
spendAckVisible: false,
|
||||
showAsMandatory: true,
|
||||
isFixed: false,
|
||||
isFreeTierAccount: false,
|
||||
label: "label",
|
||||
infoBubbleText: "infoBubbleText",
|
||||
canExceedMaximumValue: true,
|
||||
|
|
|
@ -28,7 +28,6 @@ import {
|
|||
Label,
|
||||
Link,
|
||||
MessageBar,
|
||||
MessageBarType,
|
||||
FontIcon,
|
||||
IColumn
|
||||
} from "office-ui-fabric-react";
|
||||
|
@ -58,6 +57,7 @@ export interface ThroughputInputAutoPilotV3Props {
|
|||
spendAckVisible?: boolean;
|
||||
showAsMandatory?: boolean;
|
||||
isFixed: boolean;
|
||||
isFreeTierAccount: boolean;
|
||||
isEmulator: boolean;
|
||||
label: string;
|
||||
infoBubbleText?: string;
|
||||
|
@ -76,6 +76,7 @@ export interface ThroughputInputAutoPilotV3Props {
|
|||
|
||||
interface ThroughputInputAutoPilotV3State {
|
||||
spendAckChecked: boolean;
|
||||
exceedFreeTierThroughput: boolean;
|
||||
}
|
||||
|
||||
export class ThroughputInputAutoPilotV3Component extends React.Component<
|
||||
|
@ -149,7 +150,9 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
|
|||
public constructor(props: ThroughputInputAutoPilotV3Props) {
|
||||
super(props);
|
||||
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;
|
||||
|
@ -436,6 +439,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
|
|||
if (this.overrideWithAutoPilotSettings()) {
|
||||
this.props.onMaxAutoPilotThroughputChange(newThroughput);
|
||||
} else {
|
||||
this.setState({ exceedFreeTierThroughput: this.props.isFreeTierAccount && newThroughput > 400 });
|
||||
this.props.onThroughputChange(newThroughput);
|
||||
}
|
||||
};
|
||||
|
@ -479,7 +483,10 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
|
|||
/>
|
||||
</Label>
|
||||
{this.overrideWithProvisionedThroughputSettings() && (
|
||||
<MessageBar messageBarType={MessageBarType.warning} styles={messageBarStyles}>
|
||||
<MessageBar
|
||||
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
|
||||
styles={messageBarStyles}
|
||||
>
|
||||
{manualToAutoscaleDisclaimerElement}
|
||||
</MessageBar>
|
||||
)}
|
||||
|
@ -556,8 +563,21 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
|
|||
}
|
||||
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() && (
|
||||
<MessageBar messageBarType={MessageBarType.warning} styles={messageBarStyles}>
|
||||
<MessageBar
|
||||
messageBarIconProps={{ iconName: "InfoSolid", className: "messageBarInfoIcon" }}
|
||||
styles={messageBarStyles}
|
||||
>
|
||||
{this.props.getThroughputWarningMessage()}
|
||||
</MessageBar>
|
||||
)}
|
||||
|
@ -583,7 +603,15 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
|
|||
warningMessage = saveThroughputWarningMessage;
|
||||
}
|
||||
|
||||
return <>{warningMessage && <MessageBar messageBarType={MessageBarType.warning}>{warningMessage}</MessageBar>}</>;
|
||||
return (
|
||||
<>
|
||||
{warningMessage && (
|
||||
<MessageBar messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}>
|
||||
{warningMessage}
|
||||
</MessageBar>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
|
|
|
@ -9,13 +9,18 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = `
|
|||
}
|
||||
>
|
||||
<StyledMessageBarBase
|
||||
messageBarType={5}
|
||||
messageBarIconProps={
|
||||
Object {
|
||||
"className": "messageBarWarningIcon",
|
||||
"iconName": "WarningSolid",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +39,7 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -45,12 +50,21 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = `
|
|||
/>
|
||||
</StyledLabelBase>
|
||||
<StyledMessageBarBase
|
||||
messageBarType={5}
|
||||
messageBarIconProps={
|
||||
Object {
|
||||
"className": "messageBarInfoIcon",
|
||||
"iconName": "InfoSolid",
|
||||
}
|
||||
}
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"backgroundColor": "white",
|
||||
"marginTop": "5px",
|
||||
},
|
||||
"text": Object {
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
|
@ -59,7 +73,7 @@ exports[`ThroughputInputAutoPilotV3Component autopilot input visible 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +185,7 @@ exports[`ThroughputInputAutoPilotV3Component spendAck checkbox visible 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -444,7 +458,7 @@ exports[`ThroughputInputAutoPilotV3Component throughput input visible 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ exports[`ScaleComponent renders with correct initial notification 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +412,7 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -952,7 +952,7 @@ exports[`SubSettingsComponent renders 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1228,7 +1228,7 @@ exports[`SubSettingsComponent timeToLiveSeconds hidden 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
|
@ -104,6 +105,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"formWarnings": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "addcollectionpane",
|
||||
"isAnalyticalStorageOn": [Function],
|
||||
"isAutoPilotSelected": [Function],
|
||||
|
@ -591,6 +593,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"formWarnings": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "addcollectionpane",
|
||||
"isAnalyticalStorageOn": [Function],
|
||||
"isAutoPilotSelected": [Function],
|
||||
|
@ -665,6 +668,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
|
@ -1326,6 +1330,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
|
@ -1375,6 +1380,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"formWarnings": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "addcollectionpane",
|
||||
"isAnalyticalStorageOn": [Function],
|
||||
"isAutoPilotSelected": [Function],
|
||||
|
@ -1862,6 +1868,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"formWarnings": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "addcollectionpane",
|
||||
"isAnalyticalStorageOn": [Function],
|
||||
"isAutoPilotSelected": [Function],
|
||||
|
@ -1936,6 +1943,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
|
@ -2610,6 +2618,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
|
@ -2659,6 +2668,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"formWarnings": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "addcollectionpane",
|
||||
"isAnalyticalStorageOn": [Function],
|
||||
"isAutoPilotSelected": [Function],
|
||||
|
@ -3146,6 +3156,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"formWarnings": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "addcollectionpane",
|
||||
"isAnalyticalStorageOn": [Function],
|
||||
"isAutoPilotSelected": [Function],
|
||||
|
@ -3220,6 +3231,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
|
@ -3881,6 +3893,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
|
@ -3930,6 +3943,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"formWarnings": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "addcollectionpane",
|
||||
"isAnalyticalStorageOn": [Function],
|
||||
"isAutoPilotSelected": [Function],
|
||||
|
@ -4417,6 +4431,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"formWarnings": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "addcollectionpane",
|
||||
"isAnalyticalStorageOn": [Function],
|
||||
"isAutoPilotSelected": [Function],
|
||||
|
@ -4491,6 +4506,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
|
|
|
@ -159,7 +159,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +402,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
"fontSize": 14,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,8 @@ export interface ThroughputInputParams {
|
|||
showAutoPilot?: ko.Observable<boolean>;
|
||||
overrideWithAutoPilotSettings: ko.Observable<boolean>;
|
||||
overrideWithProvisionedThroughputSettings: ko.Observable<boolean>;
|
||||
freeTierExceedThroughputTooltip?: ko.Observable<string>;
|
||||
freeTierExceedThroughputWarning?: ko.Observable<string>;
|
||||
}
|
||||
|
||||
export class ThroughputInputViewModel extends WaitsForTemplateViewModel {
|
||||
|
@ -165,6 +167,10 @@ export class ThroughputInputViewModel extends WaitsForTemplateViewModel {
|
|||
public overrideWithProvisionedThroughputSettings: ko.Observable<boolean>;
|
||||
public isManualThroughputInputFieldRequired: 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) {
|
||||
super();
|
||||
|
@ -219,6 +225,16 @@ export class ThroughputInputViewModel extends WaitsForTemplateViewModel {
|
|||
this.isAutoscaleThroughputInputFieldRequired = ko.pureComputed(
|
||||
() => 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() {
|
||||
|
|
|
@ -132,6 +132,14 @@
|
|||
<a target="_blank" href="https://cosmos.azure.com/capacitycalculator/">capacity calculator</a></span
|
||||
>
|
||||
</p>
|
||||
|
||||
<div class="inputTooltip">
|
||||
<span
|
||||
data-bind="text: freeTierExceedThroughputTooltip, visible: showFreeTierExceedThroughputTooltip"
|
||||
class="inputTooltipText"
|
||||
></span>
|
||||
</div>
|
||||
|
||||
<div data-bind="setTemplateReady: true">
|
||||
<input
|
||||
data-bind="
|
||||
|
@ -154,6 +162,11 @@
|
|||
/>
|
||||
</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">
|
||||
<span data-bind="html: requestUnitsUsageCost"></span>
|
||||
</p>
|
||||
|
|
|
@ -3014,4 +3014,25 @@ 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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,7 +152,8 @@
|
|||
maxAutoPilotThroughputSet: sharedAutoPilotThroughput,
|
||||
autoPilotUsageCost: autoPilotUsageCost,
|
||||
canExceedMaximumValue: canExceedMaximumValue,
|
||||
showAutoPilot: !isFreeTierAccount()
|
||||
showAutoPilot: !isFreeTierAccount(),
|
||||
freeTierExceedThroughputTooltip: freeTierExceedThroughputTooltip
|
||||
}">
|
||||
</throughput-input-autopilot-v3>
|
||||
</div>
|
||||
|
@ -333,7 +334,8 @@
|
|||
maxAutoPilotThroughputSet: autoPilotThroughput,
|
||||
autoPilotUsageCost: autoPilotUsageCost,
|
||||
canExceedMaximumValue: canExceedMaximumValue,
|
||||
showAutoPilot: !isFixedStorageSelected()
|
||||
showAutoPilot: !isFixedStorageSelected(),
|
||||
freeTierExceedThroughputTooltip: freeTierExceedThroughputTooltip
|
||||
}">
|
||||
</throughput-input-autopilot-v3>
|
||||
</div>
|
||||
|
|
|
@ -74,7 +74,7 @@ describe("Add Collection Pane", () => {
|
|||
explorer.databaseAccount(mockFreeTierDatabaseAccount);
|
||||
const addCollectionPane = explorer.addCollectionPane as AddCollectionPane;
|
||||
expect(addCollectionPane.isFreeTierAccount()).toBe(true);
|
||||
expect(addCollectionPane.upsellMessage()).toContain("With free tier discount");
|
||||
expect(addCollectionPane.upsellMessage()).toContain("With free tier");
|
||||
expect(addCollectionPane.upsellAnchorUrl()).toBe(Constants.Urls.freeTierInformation);
|
||||
expect(addCollectionPane.upsellAnchorText()).toBe("Learn more");
|
||||
});
|
||||
|
|
|
@ -89,6 +89,7 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
|||
public isSynapseLinkUpdating: ko.Computed<boolean>;
|
||||
public canExceedMaximumValue: ko.PureComputed<boolean>;
|
||||
public ruToolTipText: ko.Computed<string>;
|
||||
public freeTierExceedThroughputTooltip: ko.Computed<string>;
|
||||
public canConfigureThroughput: ko.PureComputed<boolean>;
|
||||
public showUpsellMessage: ko.PureComputed<boolean>;
|
||||
public shouldCreateMongoWildcardIndex: ko.Observable<boolean>;
|
||||
|
@ -99,7 +100,6 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
|||
super(options);
|
||||
this.ruToolTipText = ko.pureComputed(() => PricingUtils.getRuToolTipText());
|
||||
this.canConfigureThroughput = ko.pureComputed(() => !this.container.isServerlessEnabled());
|
||||
this.showUpsellMessage = ko.pureComputed(() => !this.container.isServerlessEnabled());
|
||||
this.formWarnings = ko.observable<string>();
|
||||
this.collectionId = ko.observable<string>();
|
||||
this.databaseId = ko.observable<string>();
|
||||
|
@ -481,8 +481,20 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
|||
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>(() => {
|
||||
return PricingUtils.getUpsellMessage(this.container.serverId(), this.isFreeTierAccount());
|
||||
return PricingUtils.getUpsellMessage(
|
||||
this.container.serverId(),
|
||||
this.isFreeTierAccount(),
|
||||
this.container.isFirstResourceCreated(),
|
||||
this.container.defaultExperience(),
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
this.upsellMessageAriaLabel = ko.pureComputed<string>(() => {
|
||||
|
@ -534,6 +546,23 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
|||
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>(() => {
|
||||
const newDatabaseWithSharedOffer = this.databaseCreateNew() && this.databaseCreateNewShared();
|
||||
const existingDatabaseWithSharedOffer = !this.databaseCreateNew() && this.databaseHasSharedOffer();
|
||||
|
|
|
@ -114,7 +114,8 @@
|
|||
maxAutoPilotThroughputSet: maxAutoPilotThroughputSet,
|
||||
autoPilotUsageCost: autoPilotUsageCost,
|
||||
canExceedMaximumValue: canExceedMaximumValue,
|
||||
showAutoPilot: !isFreeTierAccount()
|
||||
showAutoPilot: !isFreeTierAccount(),
|
||||
freeTierExceedThroughputTooltip: freeTierExceedThroughputTooltip
|
||||
}">
|
||||
</throughput-input-autopilot-v3>
|
||||
<p data-bind="visible: canRequestSupport">
|
||||
|
|
|
@ -77,7 +77,7 @@ describe("Add Database Pane", () => {
|
|||
explorer.databaseAccount(mockFreeTierDatabaseAccount);
|
||||
const addDatabasePane = explorer.addDatabasePane as AddDatabasePane;
|
||||
expect(addDatabasePane.isFreeTierAccount()).toBe(true);
|
||||
expect(addDatabasePane.upsellMessage()).toContain("With free tier discount");
|
||||
expect(addDatabasePane.upsellMessage()).toContain("With free tier");
|
||||
expect(addDatabasePane.upsellAnchorUrl()).toBe(Constants.Urls.freeTierInformation);
|
||||
expect(addDatabasePane.upsellAnchorText()).toBe("Learn more");
|
||||
});
|
||||
|
|
|
@ -44,6 +44,7 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
|||
public autoPilotUsageCost: ko.Computed<string>;
|
||||
public canExceedMaximumValue: ko.PureComputed<boolean>;
|
||||
public ruToolTipText: ko.Computed<string>;
|
||||
public freeTierExceedThroughputTooltip: ko.Computed<string>;
|
||||
public isFreeTierAccount: ko.Computed<boolean>;
|
||||
public canConfigureThroughput: ko.PureComputed<boolean>;
|
||||
public showUpsellMessage: ko.PureComputed<boolean>;
|
||||
|
@ -54,7 +55,6 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
|||
this.databaseId = ko.observable<string>();
|
||||
this.ruToolTipText = ko.pureComputed(() => PricingUtils.getRuToolTipText());
|
||||
this.canConfigureThroughput = ko.pureComputed(() => !this.container.isServerlessEnabled());
|
||||
this.showUpsellMessage = ko.pureComputed(() => !this.container.isServerlessEnabled());
|
||||
|
||||
this.canExceedMaximumValue = ko.pureComputed(() => this.container.canExceedMaximumValue());
|
||||
|
||||
|
@ -182,6 +182,18 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
|||
return isFreeTierAccount;
|
||||
});
|
||||
|
||||
this.showUpsellMessage = ko.pureComputed(() => {
|
||||
if (this.container.isServerlessEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isFreeTierAccount()) {
|
||||
return this.databaseCreateNewShared();
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.maxThroughputRUText = ko.pureComputed(() => {
|
||||
return this.maxThroughputRU().toLocaleString();
|
||||
});
|
||||
|
@ -219,8 +231,20 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
|||
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>(() => {
|
||||
return PricingUtils.getUpsellMessage(this.container.serverId(), this.isFreeTierAccount());
|
||||
return PricingUtils.getUpsellMessage(
|
||||
this.container.serverId(),
|
||||
this.isFreeTierAccount(),
|
||||
this.container.isFirstResourceCreated(),
|
||||
this.container.defaultExperience(),
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
this.upsellMessageAriaLabel = ko.pureComputed<string>(() => {
|
||||
|
|
|
@ -23,6 +23,19 @@
|
|||
<div class="scaleDivison" aria-label="Scale" aria-controls="scaleRegion">
|
||||
<span class="scaleSettingTitle">Scale</span>
|
||||
</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">
|
||||
<throughput-input-autopilot-v3
|
||||
params="{
|
||||
|
@ -46,7 +59,8 @@
|
|||
autoPilotUsageCost: autoPilotUsageCost,
|
||||
canExceedMaximumValue: canExceedMaximumValue,
|
||||
overrideWithAutoPilotSettings: overrideWithAutoPilotSettings,
|
||||
overrideWithProvisionedThroughputSettings: overrideWithProvisionedThroughputSettings
|
||||
overrideWithProvisionedThroughputSettings: overrideWithProvisionedThroughputSettings,
|
||||
freeTierExceedThroughputWarning: freeTierExceedThroughputWarning
|
||||
}"
|
||||
>
|
||||
</throughput-input-autopilot-v3>
|
||||
|
|
|
@ -57,6 +57,7 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
|
|||
public canThroughputExceedMaximumValue: ko.Computed<boolean>;
|
||||
public costsVisible: ko.Computed<boolean>;
|
||||
public displayedError: ko.Observable<string>;
|
||||
public isFreeTierAccount: ko.Computed<boolean>;
|
||||
public isTemplateReady: ko.Observable<boolean>;
|
||||
public minRUAnotationVisible: ko.Computed<boolean>;
|
||||
public minRUs: ko.Observable<number>;
|
||||
|
@ -82,6 +83,7 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
|
|||
public throughputAutoPilotRadioId: string;
|
||||
public throughputProvisionedRadioId: string;
|
||||
public throughputModeRadioName: string;
|
||||
public freeTierExceedThroughputWarning: ko.Computed<string>;
|
||||
|
||||
private _hasProvisioningTypeChanged: ko.Computed<boolean>;
|
||||
private _wasAutopilotOriginallySet: ko.Observable<boolean>;
|
||||
|
@ -359,6 +361,17 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
|
|||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import * as AutoPilotUtils from "../Utils/AutoPilotUtils";
|
||||
import * as Constants from "../Shared/Constants";
|
||||
import { DefaultAccountExperienceType } from "../DefaultAccountExperienceType";
|
||||
|
||||
interface ComputeRUUsagePriceHourlyArgs {
|
||||
serverId: string;
|
||||
|
@ -256,9 +257,19 @@ export function getEstimatedSpendAcknowledgeString(
|
|||
)} - ${currencySign}${calculateEstimateNumber(monthlyPrice)} monthly cost for the throughput above.`;
|
||||
}
|
||||
|
||||
export function getUpsellMessage(serverId = "default", isFreeTier = false): string {
|
||||
export function getUpsellMessage(
|
||||
serverId = "default",
|
||||
isFreeTier = false,
|
||||
isFirstResourceCreated = false,
|
||||
defaultExperience: string,
|
||||
isCollection: boolean
|
||||
): string {
|
||||
if (isFreeTier) {
|
||||
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 collectionName = getCollectionName(defaultExperience);
|
||||
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 {
|
||||
let price: number = Constants.OfferPricing.MonthlyPricing.default.Standard.StartingPrice;
|
||||
|
||||
|
@ -269,3 +280,19 @@ export function getUpsellMessage(serverId = "default", isFreeTier = false): stri
|
|||
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");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue