import { Link, MessageBar, MessageBarType, Stack, Text, TextField } from "@fluentui/react"; import { Keys, t } from "Localization"; import * as React from "react"; import * as Constants from "../../../../Common/Constants"; import { configContext, Platform } from "../../../../ConfigContext"; import * as DataModels from "../../../../Contracts/DataModels"; import * as ViewModels from "../../../../Contracts/ViewModels"; import * as SharedConstants from "../../../../Shared/Constants"; import { userContext } from "../../../../UserContext"; import * as AutoPilotUtils from "../../../../Utils/AutoPilotUtils"; import { isRunningOnNationalCloud } from "../../../../Utils/CloudUtils"; import { getTextFieldStyles, getThroughputApplyShortDelayMessage, subComponentStackProps, throughputUnit, titleAndInputStackProps, } from "../SettingsRenderUtils"; import { hasDatabaseSharedThroughput } from "../SettingsUtils"; import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component"; export interface ScaleComponentProps { collection: ViewModels.Collection; database: ViewModels.Database; isFixedContainer: boolean; isGlobalSecondaryIndex: boolean; onThroughputChange: (newThroughput: number) => void; throughput: number; throughputBaseline: number; autoPilotThroughput: number; autoPilotThroughputBaseline: number; isAutoPilotSelected: boolean; wasAutopilotOriginallySet: boolean; onAutoPilotSelected: (isAutoPilotSelected: boolean) => void; onMaxAutoPilotThroughputChange: (newThroughput: number) => void; onScaleSaveableChange: (isScaleSaveable: boolean) => void; onScaleDiscardableChange: (isScaleDiscardable: boolean) => void; throughputError?: string; hotPartitionKeyRateLimitingPolicy?: DataModels.HotPartitionKeyRateLimitingPolicy; hotPartitionKeyRateLimitingPolicyBaseline?: DataModels.HotPartitionKeyRateLimitingPolicy; onHotPartitionKeyRateLimitingPolicyChange: (newPolicy: DataModels.HotPartitionKeyRateLimitingPolicy) => void; } export class ScaleComponent extends React.Component { private isEmulator: boolean; private offer: DataModels.Offer; private databaseId: string; private collectionId: string; constructor(props: ScaleComponentProps) { super(props); this.isEmulator = configContext.platform === Platform.Emulator; this.offer = this.props.database?.offer() || this.props.collection?.offer(); this.databaseId = this.props.database?.id() || this.props.collection.databaseId; this.collectionId = this.props.collection?.id(); } public isAutoScaleEnabled = (): boolean => { const accountCapabilities: DataModels.Capability[] = userContext?.databaseAccount?.properties?.capabilities; const enableAutoScaleCapability = accountCapabilities && accountCapabilities.find((capability: DataModels.Capability) => { return ( capability && capability.name && capability.name.toLowerCase() === Constants.CapabilityNames.EnableAutoScale.toLowerCase() ); }); return !!enableAutoScaleCapability; }; public getMaxRUs = (): number => { if (userContext.isTryCosmosDBSubscription) { return Constants.TryCosmosExperience.maxRU; } if (this.props.isFixedContainer) { return SharedConstants.CollectionCreation.MaxRUPerPartition; } return SharedConstants.CollectionCreation.DefaultCollectionRUs1Million; }; public getMinRUs = (): number => { if (userContext.isTryCosmosDBSubscription) { return SharedConstants.CollectionCreation.DefaultCollectionRUs400; } return this.offer?.minimumThroughput || SharedConstants.CollectionCreation.DefaultCollectionRUs400; }; public getThroughputTitle = (): string => { if (this.props.isAutoPilotSelected) { return AutoPilotUtils.getAutoPilotHeaderText(); } const minThroughput: string = this.getMinRUs().toLocaleString(); const maxThroughput: string = !this.props.isFixedContainer ? t(Keys.controls.settings.scale.unlimited) : this.getMaxRUs().toLocaleString(); return t(Keys.controls.settings.scale.throughputRangeLabel, { min: minThroughput, max: maxThroughput }); }; public canThroughputExceedMaximumValue = (): boolean => { return !this.props.isFixedContainer && configContext.platform === Platform.Portal && !isRunningOnNationalCloud(); }; public getInitialNotificationElement = (): JSX.Element => { if (this.offer?.offerReplacePending) { const throughput = this.offer.manualThroughput || this.offer.autoscaleMaxThroughput; return getThroughputApplyShortDelayMessage( this.props.isAutoPilotSelected, throughput, throughputUnit, this.databaseId, this.collectionId, ); } return undefined; }; private getThroughputInputComponent = (): JSX.Element => ( ); private isFreeTierAccount(): boolean { return userContext?.databaseAccount?.properties?.enableFreeTier; } private getFreeTierInfoMessage(): JSX.Element { const freeTierLimits = SharedConstants.FreeTierLimits; return ( {t(Keys.controls.settings.scale.freeTierInfo, { ru: freeTierLimits.RU, storage: freeTierLimits.Storage })} {t(Keys.controls.settings.scale.freeTierLearnMore)} ); } public render(): JSX.Element { return ( {this.isFreeTierAccount() && ( {this.getFreeTierInfoMessage()} )} {this.getInitialNotificationElement() && ( {this.getInitialNotificationElement()} )} {!this.isAutoScaleEnabled() && {this.getThroughputInputComponent()}} {/* TODO: Replace link with call to the Azure Support blade */} {this.isAutoScaleEnabled() && ( {t(Keys.controls.settings.scale.throughputRuS)} {t(Keys.controls.settings.scale.autoScaleCustomSettings)} )} ); } }