mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-29 22:02:01 +00:00
marge master
This commit is contained in:
@@ -25,7 +25,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { userContext } from "../../UserContext";
|
||||
import { getCollectionName } from "../../Utils/APITypeUtils";
|
||||
import { isCapabilityEnabled } from "../../Utils/CapabilityUtils";
|
||||
import { isCapabilityEnabled, isServerlessAccount } from "../../Utils/CapabilityUtils";
|
||||
import { getUpsellMessage } from "../../Utils/PricingUtils";
|
||||
import { CollapsibleSectionComponent } from "../Controls/CollapsiblePanel/CollapsibleSectionComponent";
|
||||
import { ThroughputInput } from "../Controls/ThroughputInput/ThroughputInput";
|
||||
@@ -182,7 +182,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
}
|
||||
/>
|
||||
|
||||
{!this.isServerlessAccount() && (
|
||||
{!isServerlessAccount() && (
|
||||
<Stack horizontal>
|
||||
<Checkbox
|
||||
label={`Share throughput across ${getCollectionName(true).toLocaleLowerCase()}`}
|
||||
@@ -207,14 +207,12 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
{!this.isServerlessAccount() && this.state.isSharedThroughputChecked && (
|
||||
{!isServerlessAccount() && this.state.isSharedThroughputChecked && (
|
||||
<ThroughputInput
|
||||
showFreeTierExceedThroughputTooltip={
|
||||
this.isFreeTierAccount() && !this.props.explorer.isFirstResourceCreated()
|
||||
}
|
||||
isDatabase={true}
|
||||
isAutoscaleSelected={this.isNewDatabaseAutoscale}
|
||||
throughput={this.newDatabaseThroughput}
|
||||
isSharded={this.state.isSharded}
|
||||
setThroughputValue={(throughput: number) => (this.newDatabaseThroughput = throughput)}
|
||||
setIsAutoscale={(isAutoscale: boolean) => (this.isNewDatabaseAutoscale = isAutoscale)}
|
||||
@@ -398,7 +396,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (
|
||||
userContext.apiType !== "Mongo" &&
|
||||
this.state.partitionKey === "" &&
|
||||
!this.state.partitionKey &&
|
||||
!event.target.value.startsWith("/")
|
||||
) {
|
||||
this.setState({ partitionKey: "/" + event.target.value });
|
||||
@@ -410,7 +408,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
{!this.isServerlessAccount() && !this.state.createNewDatabase && this.isSelectedDatabaseSharedThroughput() && (
|
||||
{!isServerlessAccount() && !this.state.createNewDatabase && this.isSelectedDatabaseSharedThroughput() && (
|
||||
<Stack horizontal verticalAlign="center">
|
||||
<Checkbox
|
||||
label={`Provision dedicated throughput for this ${getCollectionName().toLocaleLowerCase()}`}
|
||||
@@ -444,8 +442,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
this.isFreeTierAccount() && !this.props.explorer.isFirstResourceCreated()
|
||||
}
|
||||
isDatabase={false}
|
||||
isAutoscaleSelected={this.isCollectionAutoscale}
|
||||
throughput={this.collectionThroughput}
|
||||
isSharded={this.state.isSharded}
|
||||
setThroughputValue={(throughput: number) => (this.collectionThroughput = throughput)}
|
||||
setIsAutoscale={(isAutoscale: boolean) => (this.isCollectionAutoscale = isAutoscale)}
|
||||
@@ -753,14 +749,8 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
return userContext.databaseAccount?.properties?.enableFreeTier;
|
||||
}
|
||||
|
||||
private isServerlessAccount(): boolean {
|
||||
return userContext.databaseAccount.properties?.capabilities?.some(
|
||||
(capability) => capability.name === Constants.CapabilityNames.EnableServerless
|
||||
);
|
||||
}
|
||||
|
||||
private getSharedThroughputDefault(): boolean {
|
||||
return userContext.subscriptionType !== SubscriptionType.EA && !this.isServerlessAccount();
|
||||
return userContext.subscriptionType !== SubscriptionType.EA && !isServerlessAccount();
|
||||
}
|
||||
|
||||
private getFreeTierIndexingText(): string {
|
||||
@@ -798,7 +788,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
}
|
||||
|
||||
private shouldShowCollectionThroughputInput(): boolean {
|
||||
if (this.isServerlessAccount()) {
|
||||
if (isServerlessAccount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -828,7 +818,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isServerlessAccount()) {
|
||||
if (isServerlessAccount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -919,6 +909,10 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
}
|
||||
|
||||
private getAnalyticalStorageTtl(): number {
|
||||
if (!this.isSynapseLinkEnabled()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!this.shouldShowAnalyticalStoreOptions()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Checkbox, Text, TextField } from "@fluentui/react";
|
||||
import { Checkbox, Stack, Text, TextField } from "@fluentui/react";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import * as Constants from "../../../Common/Constants";
|
||||
import { createDatabase } from "../../../Common/dataAccess/createDatabase";
|
||||
import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils";
|
||||
import { InfoTooltip } from "../../../Common/Tooltip/InfoTooltip";
|
||||
import { configContext, Platform } from "../../../ConfigContext";
|
||||
import * as DataModels from "../../../Contracts/DataModels";
|
||||
import { SubscriptionType } from "../../../Contracts/SubscriptionType";
|
||||
import * as SharedConstants from "../../../Shared/Constants";
|
||||
@@ -12,7 +11,8 @@ import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryCons
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { userContext } from "../../../UserContext";
|
||||
import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils";
|
||||
import * as PricingUtils from "../../../Utils/PricingUtils";
|
||||
import { isServerlessAccount } from "../../../Utils/CapabilityUtils";
|
||||
import { getUpsellMessage } from "../../../Utils/PricingUtils";
|
||||
import { ThroughputInput } from "../../Controls/ThroughputInput/ThroughputInput";
|
||||
import Explorer from "../../Explorer";
|
||||
import { PanelInfoErrorComponent } from "../PanelInfoErrorComponent";
|
||||
@@ -29,17 +29,10 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
closePanel,
|
||||
openNotificationConsole,
|
||||
}: AddDatabasePaneProps) => {
|
||||
let throughput: number;
|
||||
let isAutoscaleSelected: boolean;
|
||||
let isCostAcknowledged: boolean;
|
||||
const { subscriptionType } = userContext;
|
||||
const getSharedThroughputDefault = !(subscriptionType === SubscriptionType.EA || container.isServerlessEnabled());
|
||||
const _isAutoPilotSelectedAndWhatTier = (): DataModels.AutoPilotCreationSettings => {
|
||||
if (isAutoPilotSelected && maxAutoPilotThroughputSet) {
|
||||
return {
|
||||
maxThroughput: maxAutoPilotThroughputSet * 1,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const isCassandraAccount: boolean = userContext.apiType === "Cassandra";
|
||||
const databaseLabel: string = isCassandraAccount ? "keyspace" : "database";
|
||||
const collectionsLabel: string = isCassandraAccount ? "tables" : "collections";
|
||||
@@ -52,61 +45,13 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
} is a logical container of one or more ${isCassandraAccount ? "tables" : "collections"}`;
|
||||
|
||||
const databaseLevelThroughputTooltipText = `Provisioned throughput at the ${databaseLabel} level will be shared across all ${collectionsLabel} within the ${databaseLabel}.`;
|
||||
const [databaseCreateNewShared, setDatabaseCreateNewShared] = useState<boolean>(getSharedThroughputDefault);
|
||||
const [formErrorsDetails, setFormErrorsDetails] = useState<string>();
|
||||
const [databaseCreateNewShared, setDatabaseCreateNewShared] = useState<boolean>(
|
||||
subscriptionType !== SubscriptionType.EA && !isServerlessAccount()
|
||||
);
|
||||
const [formErrors, setFormErrors] = useState<string>("");
|
||||
|
||||
const [isAutoPilotSelected, setIsAutoPilotSelected] = useState<boolean>(container.isAutoscaleDefaultEnabled());
|
||||
|
||||
const throughputDefaults = container.collectionCreationDefaults.throughput;
|
||||
const [throughput, setThroughput] = useState<number>(
|
||||
isAutoPilotSelected ? AutoPilotUtils.minAutoPilotThroughput : throughputDefaults.shared
|
||||
);
|
||||
|
||||
const [throughputSpendAck, setThroughputSpendAck] = useState<boolean>(false);
|
||||
|
||||
const canRequestSupport = () => {
|
||||
if (
|
||||
configContext.platform !== Platform.Emulator &&
|
||||
!userContext.isTryCosmosDBSubscription &&
|
||||
configContext.platform !== Platform.Portal
|
||||
) {
|
||||
const offerThroughput: number = throughput;
|
||||
return offerThroughput <= 100000;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
const isFreeTierAccount: boolean = userContext.databaseAccount?.properties?.enableFreeTier;
|
||||
const upsellMessage: string = PricingUtils.getUpsellMessage(
|
||||
userContext.portalEnv,
|
||||
isFreeTierAccount,
|
||||
container.isFirstResourceCreated(),
|
||||
false
|
||||
);
|
||||
|
||||
const upsellAnchorUrl: string = isFreeTierAccount ? Constants.Urls.freeTierInformation : Constants.Urls.cosmosPricing;
|
||||
|
||||
const upsellAnchorText: string = isFreeTierAccount ? "Learn more" : "More details";
|
||||
const maxAutoPilotThroughputSet = AutoPilotUtils.minAutoPilotThroughput;
|
||||
|
||||
const canConfigureThroughput = !container.isServerlessEnabled();
|
||||
const showUpsellMessage = () => {
|
||||
if (container.isServerlessEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isFreeTierAccount) {
|
||||
return databaseCreateNewShared;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
const [isExecuting, setIsExecuting] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
setDatabaseCreateNewShared(getSharedThroughputDefault);
|
||||
}, [subscriptionType]);
|
||||
const isFreeTierAccount: boolean = userContext.databaseAccount?.properties?.enableFreeTier;
|
||||
|
||||
const addDatabasePaneMessage = {
|
||||
database: {
|
||||
@@ -126,7 +71,7 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
subscriptionType: SubscriptionType[subscriptionType],
|
||||
subscriptionQuotaId: userContext.quotaId,
|
||||
defaultsCheck: {
|
||||
throughput: throughput,
|
||||
throughput,
|
||||
flight: userContext.addCollectionFlight,
|
||||
},
|
||||
dataExplorerArea: Constants.Areas.ContextualPane,
|
||||
@@ -139,11 +84,9 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
const offerThroughput: number = _computeOfferThroughput();
|
||||
|
||||
const addDatabasePaneStartMessage = {
|
||||
...addDatabasePaneMessage,
|
||||
offerThroughput,
|
||||
throughput,
|
||||
};
|
||||
const startKey: number = TelemetryProcessor.traceStart(Action.CreateDatabase, addDatabasePaneStartMessage);
|
||||
setFormErrors("");
|
||||
@@ -153,18 +96,18 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
databaseId: addDatabasePaneStartMessage.database.id,
|
||||
databaseLevelThroughput: addDatabasePaneStartMessage.database.shared,
|
||||
};
|
||||
if (isAutoPilotSelected) {
|
||||
createDatabaseParams.autoPilotMaxThroughput = addDatabasePaneStartMessage.offerThroughput;
|
||||
if (isAutoscaleSelected) {
|
||||
createDatabaseParams.autoPilotMaxThroughput = addDatabasePaneStartMessage.throughput;
|
||||
} else {
|
||||
createDatabaseParams.offerThroughput = addDatabasePaneStartMessage.offerThroughput;
|
||||
createDatabaseParams.offerThroughput = addDatabasePaneStartMessage.throughput;
|
||||
}
|
||||
|
||||
createDatabase(createDatabaseParams).then(
|
||||
() => {
|
||||
_onCreateDatabaseSuccess(offerThroughput, startKey);
|
||||
_onCreateDatabaseSuccess(throughput, startKey);
|
||||
},
|
||||
(error: string) => {
|
||||
_onCreateDatabaseFailure(error, offerThroughput, startKey);
|
||||
_onCreateDatabaseFailure(error, throughput, startKey);
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -184,7 +127,6 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
setIsExecuting(false);
|
||||
const errorMessage = getErrorMessage(error);
|
||||
setFormErrors(errorMessage);
|
||||
setFormErrorsDetails(errorMessage);
|
||||
const addDatabasePaneFailedMessage = {
|
||||
...addDatabasePaneMessage,
|
||||
offerThroughput,
|
||||
@@ -194,48 +136,19 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
TelemetryProcessor.traceFailure(Action.CreateDatabase, addDatabasePaneFailedMessage, startKey);
|
||||
};
|
||||
|
||||
const _getThroughput = (): number => {
|
||||
return isNaN(throughput) ? 0 : Number(throughput);
|
||||
};
|
||||
|
||||
const _computeOfferThroughput = (): number => {
|
||||
if (!canConfigureThroughput) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return _getThroughput();
|
||||
};
|
||||
|
||||
const _isValid = (): boolean => {
|
||||
// TODO add feature flag that disables validation for customers with custom accounts
|
||||
if (isAutoPilotSelected) {
|
||||
const autoPilot = _isAutoPilotSelectedAndWhatTier();
|
||||
if (
|
||||
!autoPilot ||
|
||||
!autoPilot.maxThroughput ||
|
||||
!AutoPilotUtils.isValidAutoPilotThroughput(autoPilot.maxThroughput)
|
||||
) {
|
||||
if (isAutoscaleSelected) {
|
||||
if (!AutoPilotUtils.isValidAutoPilotThroughput(throughput)) {
|
||||
setFormErrors(
|
||||
`Please enter a value greater than ${AutoPilotUtils.minAutoPilotThroughput} for autopilot throughput`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const throughput = _getThroughput();
|
||||
|
||||
if (throughput > SharedConstants.CollectionCreation.DefaultCollectionRUs100K && !throughputSpendAck) {
|
||||
setFormErrors(`Please acknowledge the estimated daily spend.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const autoscaleThroughput = maxAutoPilotThroughputSet * 1;
|
||||
|
||||
if (
|
||||
isAutoPilotSelected &&
|
||||
autoscaleThroughput > SharedConstants.CollectionCreation.DefaultCollectionRUs100K &&
|
||||
!throughputSpendAck
|
||||
) {
|
||||
setFormErrors(`Please acknowledge the estimated monthly spend.`);
|
||||
if (throughput > SharedConstants.CollectionCreation.DefaultCollectionRUs100K && !isCostAcknowledged) {
|
||||
setFormErrors(`Please acknowledge the estimated ${isAutoscaleSelected ? "monthly" : "daily"} spend.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -250,9 +163,8 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
);
|
||||
|
||||
const props: RightPaneFormProps = {
|
||||
expandConsole: container.expandConsole,
|
||||
expandConsole: openNotificationConsole,
|
||||
formError: formErrors,
|
||||
formErrorDetail: formErrorsDetails,
|
||||
isExecuting,
|
||||
submitButtonText: "OK",
|
||||
onSubmit,
|
||||
@@ -260,81 +172,66 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
|
||||
return (
|
||||
<RightPaneForm {...props}>
|
||||
<div className="paneContentContainer" role="dialog" aria-labelledby="databaseTitle">
|
||||
{showUpsellMessage && formErrors === "" && (
|
||||
<PanelInfoErrorComponent
|
||||
message={upsellMessage}
|
||||
messageType="info"
|
||||
showErrorDetails={false}
|
||||
openNotificationConsole={openNotificationConsole}
|
||||
link={upsellAnchorUrl}
|
||||
linkText={upsellAnchorText}
|
||||
{!formErrors && isFreeTierAccount && (
|
||||
<PanelInfoErrorComponent
|
||||
message={getUpsellMessage(userContext.portalEnv, true, container.isFirstResourceCreated(), true)}
|
||||
messageType="info"
|
||||
showErrorDetails={false}
|
||||
openNotificationConsole={openNotificationConsole}
|
||||
link={Constants.Urls.freeTierInformation}
|
||||
linkText="Learn more"
|
||||
/>
|
||||
)}
|
||||
<div className="panelMainContent">
|
||||
<div>
|
||||
<Stack horizontal>
|
||||
<span className="mandatoryStar">*</span>
|
||||
<Text variant="small">{databaseIdLabel}</Text>
|
||||
<InfoTooltip>{databaseIdTooltipText}</InfoTooltip>
|
||||
</Stack>
|
||||
|
||||
<TextField
|
||||
id="database-id"
|
||||
type="text"
|
||||
aria-required="true"
|
||||
autoComplete="off"
|
||||
pattern="[^/?#\\]*[^/?# \\]"
|
||||
title="May not end with space nor contain characters '\' '/' '#' '?'"
|
||||
size={40}
|
||||
aria-label={databaseIdLabel}
|
||||
placeholder={databaseIdPlaceHolder}
|
||||
value={databaseId}
|
||||
onChange={handleonChangeDBId}
|
||||
autoFocus
|
||||
style={{ fontSize: 12 }}
|
||||
styles={{ root: { width: 300 } }}
|
||||
/>
|
||||
)}
|
||||
<div className="paneMainContent">
|
||||
<div>
|
||||
<p>
|
||||
<span className="mandatoryStar">*</span>
|
||||
<Text variant="small">{databaseIdLabel}</Text>
|
||||
<InfoTooltip>{databaseIdTooltipText}</InfoTooltip>
|
||||
</p>
|
||||
|
||||
<TextField
|
||||
id="database-id"
|
||||
type="text"
|
||||
aria-required="true"
|
||||
autoComplete="off"
|
||||
pattern="[^/?#\\]*[^/?# \\]"
|
||||
title="May not end with space nor contain characters '\' '/' '#' '?'"
|
||||
size={40}
|
||||
aria-label={databaseIdLabel}
|
||||
placeholder={databaseIdPlaceHolder}
|
||||
value={databaseId}
|
||||
onChange={handleonChangeDBId}
|
||||
autoFocus
|
||||
<Stack horizontal>
|
||||
<Checkbox
|
||||
title="Provision shared throughput"
|
||||
styles={{
|
||||
text: { fontSize: 12 },
|
||||
checkbox: { width: 12, height: 12 },
|
||||
label: { padding: 0, alignItems: "center" },
|
||||
}}
|
||||
label="Provision throughput"
|
||||
checked={databaseCreateNewShared}
|
||||
onChange={() => setDatabaseCreateNewShared(!databaseCreateNewShared)}
|
||||
/>
|
||||
<InfoTooltip>{databaseLevelThroughputTooltipText}</InfoTooltip>
|
||||
</Stack>
|
||||
|
||||
<div
|
||||
className="databaseProvision"
|
||||
aria-label="New database provision support"
|
||||
style={{ display: "block ruby" }}
|
||||
>
|
||||
<Checkbox
|
||||
title="Provision shared throughput"
|
||||
styles={{
|
||||
checkbox: { width: 12, height: 12 },
|
||||
label: { padding: 0, alignItems: "center" },
|
||||
}}
|
||||
label="Provision throughput"
|
||||
checked={databaseCreateNewShared}
|
||||
onChange={() => setDatabaseCreateNewShared(!databaseCreateNewShared)}
|
||||
/>{" "}
|
||||
<InfoTooltip>{databaseLevelThroughputTooltipText}</InfoTooltip>
|
||||
</div>
|
||||
{databaseCreateNewShared && (
|
||||
<div>
|
||||
<ThroughputInput
|
||||
showFreeTierExceedThroughputTooltip={isFreeTierAccount && !container?.isFirstResourceCreated()}
|
||||
isDatabase={true}
|
||||
isSharded={databaseCreateNewShared}
|
||||
isAutoscaleSelected={isAutoPilotSelected}
|
||||
throughput={throughput}
|
||||
setThroughputValue={(throughput: number) => setThroughput(throughput)}
|
||||
setIsAutoscale={(isAutoscale: boolean) => setIsAutoPilotSelected(isAutoscale)}
|
||||
onCostAcknowledgeChange={(isAcknowledged: boolean) => setThroughputSpendAck(isAcknowledged)}
|
||||
/>
|
||||
|
||||
{canRequestSupport() && (
|
||||
<p>
|
||||
<a href="https://aka.ms/cosmosdbfeedback?subject=Cosmos%20DB%20More%20Throughput%20Request">
|
||||
Contact support{" "}
|
||||
</a>
|
||||
for more than <span>{throughputDefaults.unlimitedmax?.toLocaleString()} </span> RU/s.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!isServerlessAccount() && databaseCreateNewShared && (
|
||||
<ThroughputInput
|
||||
showFreeTierExceedThroughputTooltip={isFreeTierAccount && !container?.isFirstResourceCreated()}
|
||||
isDatabase={true}
|
||||
isSharded={databaseCreateNewShared}
|
||||
setThroughputValue={(newThroughput: number) => (throughput = newThroughput)}
|
||||
setIsAutoscale={(isAutoscale: boolean) => (isAutoscaleSelected = isAutoscale)}
|
||||
onCostAcknowledgeChange={(isAcknowledged: boolean) => (isCostAcknowledged = isAcknowledged)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</RightPaneForm>
|
||||
|
||||
@@ -9,95 +9,87 @@ exports[`AddDatabasePane Pane should render Default properly 1`] = `
|
||||
submitButtonText="OK"
|
||||
>
|
||||
<div
|
||||
aria-labelledby="databaseTitle"
|
||||
className="paneContentContainer"
|
||||
role="dialog"
|
||||
className="panelMainContent"
|
||||
>
|
||||
<PanelInfoErrorComponent
|
||||
link="https://aka.ms/azure-cosmos-db-pricing"
|
||||
linkText="More details"
|
||||
message="Start at $24/mo per database, multiple containers included"
|
||||
messageType="info"
|
||||
openNotificationConsole={[Function]}
|
||||
showErrorDetails={false}
|
||||
/>
|
||||
<div
|
||||
className="paneMainContent"
|
||||
>
|
||||
<div>
|
||||
<p>
|
||||
<span
|
||||
className="mandatoryStar"
|
||||
>
|
||||
*
|
||||
</span>
|
||||
<Text
|
||||
variant="small"
|
||||
>
|
||||
Database id
|
||||
</Text>
|
||||
<InfoTooltip>
|
||||
A database is a logical container of one or more collections
|
||||
</InfoTooltip>
|
||||
</p>
|
||||
<StyledTextFieldBase
|
||||
aria-label="Database id"
|
||||
aria-required="true"
|
||||
autoComplete="off"
|
||||
autoFocus={true}
|
||||
id="database-id"
|
||||
<div>
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<span
|
||||
className="mandatoryStar"
|
||||
>
|
||||
*
|
||||
</span>
|
||||
<Text
|
||||
variant="small"
|
||||
>
|
||||
Database id
|
||||
</Text>
|
||||
<InfoTooltip>
|
||||
A database is a logical container of one or more collections
|
||||
</InfoTooltip>
|
||||
</Stack>
|
||||
<StyledTextFieldBase
|
||||
aria-label="Database id"
|
||||
aria-required="true"
|
||||
autoComplete="off"
|
||||
autoFocus={true}
|
||||
id="database-id"
|
||||
onChange={[Function]}
|
||||
pattern="[^/?#\\\\\\\\]*[^/?# \\\\\\\\]"
|
||||
placeholder="Type a new database id"
|
||||
size={40}
|
||||
style={
|
||||
Object {
|
||||
"fontSize": 12,
|
||||
}
|
||||
}
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"width": 300,
|
||||
},
|
||||
}
|
||||
}
|
||||
title="May not end with space nor contain characters '\\\\' '/' '#' '?'"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<StyledCheckboxBase
|
||||
checked={true}
|
||||
label="Provision throughput"
|
||||
onChange={[Function]}
|
||||
pattern="[^/?#\\\\\\\\]*[^/?# \\\\\\\\]"
|
||||
placeholder="Type a new database id"
|
||||
size={40}
|
||||
title="May not end with space nor contain characters '\\\\' '/' '#' '?'"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
aria-label="New database provision support"
|
||||
className="databaseProvision"
|
||||
style={
|
||||
styles={
|
||||
Object {
|
||||
"display": "block ruby",
|
||||
"checkbox": Object {
|
||||
"height": 12,
|
||||
"width": 12,
|
||||
},
|
||||
"label": Object {
|
||||
"alignItems": "center",
|
||||
"padding": 0,
|
||||
},
|
||||
"text": Object {
|
||||
"fontSize": 12,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<StyledCheckboxBase
|
||||
checked={true}
|
||||
label="Provision throughput"
|
||||
onChange={[Function]}
|
||||
styles={
|
||||
Object {
|
||||
"checkbox": Object {
|
||||
"height": 12,
|
||||
"width": 12,
|
||||
},
|
||||
"label": Object {
|
||||
"alignItems": "center",
|
||||
"padding": 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
title="Provision shared throughput"
|
||||
/>
|
||||
|
||||
<InfoTooltip>
|
||||
Provisioned throughput at the database level will be shared across all collections within the database.
|
||||
</InfoTooltip>
|
||||
</div>
|
||||
<div>
|
||||
<ThroughputInput
|
||||
isAutoscaleSelected={false}
|
||||
isDatabase={true}
|
||||
isSharded={true}
|
||||
onCostAcknowledgeChange={[Function]}
|
||||
setIsAutoscale={[Function]}
|
||||
setThroughputValue={[Function]}
|
||||
throughput={400}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
title="Provision shared throughput"
|
||||
/>
|
||||
<InfoTooltip>
|
||||
Provisioned throughput at the database level will be shared across all collections within the database.
|
||||
</InfoTooltip>
|
||||
</Stack>
|
||||
<ThroughputInput
|
||||
isDatabase={true}
|
||||
isSharded={true}
|
||||
onCostAcknowledgeChange={[Function]}
|
||||
setIsAutoscale={[Function]}
|
||||
setThroughputValue={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</RightPaneForm>
|
||||
|
||||
@@ -21,115 +21,6 @@ exports[`GitHub Repos Panel should render Default properly 1`] = `
|
||||
"_closeSynapseLinkModalDialog": [Function],
|
||||
"_isAfecFeatureRegistered": [Function],
|
||||
"_isInitializingNotebooks": false,
|
||||
"_panes": Array [
|
||||
AddDatabasePane {
|
||||
"autoPilotUsageCost": [Function],
|
||||
"canConfigureThroughput": [Function],
|
||||
"canExceedMaximumValue": [Function],
|
||||
"canRequestSupport": [Function],
|
||||
"container": [Circular],
|
||||
"costsVisible": [Function],
|
||||
"databaseCreateNewShared": [Function],
|
||||
"databaseId": [Function],
|
||||
"databaseIdLabel": [Function],
|
||||
"databaseIdPlaceHolder": [Function],
|
||||
"databaseIdTooltipText": [Function],
|
||||
"databaseLevelThroughputTooltipText": [Function],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isFreeTierAccount": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"maxAutoPilotThroughputSet": [Function],
|
||||
"maxThroughputRU": [Function],
|
||||
"maxThroughputRUText": [Function],
|
||||
"minThroughputRU": [Function],
|
||||
"onMoreDetailsKeyPress": [Function],
|
||||
"requestUnitsUsageCost": [Function],
|
||||
"ruToolTipText": [Function],
|
||||
"showUpsellMessage": [Function],
|
||||
"throughput": [Function],
|
||||
"throughputRangeText": [Function],
|
||||
"throughputSpendAck": [Function],
|
||||
"throughputSpendAckText": [Function],
|
||||
"throughputSpendAckVisible": [Function],
|
||||
"title": [Function],
|
||||
"upsellAnchorText": [Function],
|
||||
"upsellAnchorUrl": [Function],
|
||||
"upsellMessage": [Function],
|
||||
"upsellMessageAriaLabel": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
GraphStylingPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"graphConfigUIData": Object {
|
||||
"nodeCaptionChoice": [Function],
|
||||
"nodeColorKeyChoice": [Function],
|
||||
"nodeIconChoice": [Function],
|
||||
"nodeIconSet": [Function],
|
||||
"nodeProperties": [Function],
|
||||
"nodePropertiesWithNone": [Function],
|
||||
"showNeighborType": [Function],
|
||||
},
|
||||
"id": "graphstylingpane",
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
CassandraAddCollectionPane {
|
||||
"autoPilotUsageCost": [Function],
|
||||
"canConfigureThroughput": [Function],
|
||||
"canExceedMaximumValue": [Function],
|
||||
"canRequestSupport": [Function],
|
||||
"container": [Circular],
|
||||
"costsVisible": [Function],
|
||||
"createTableQuery": [Function],
|
||||
"dedicateTableThroughput": [Function],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "cassandraaddcollectionpane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isFreeTierAccount": [Function],
|
||||
"isSharedAutoPilotSelected": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"keyspaceCreateNew": [Function],
|
||||
"keyspaceHasSharedOffer": [Function],
|
||||
"keyspaceId": [Function],
|
||||
"keyspaceIds": [Function],
|
||||
"keyspaceOffers": Map {},
|
||||
"keyspaceThroughput": [Function],
|
||||
"maxThroughputRU": [Function],
|
||||
"minThroughputRU": [Function],
|
||||
"requestUnitsUsageCostDedicated": [Function],
|
||||
"requestUnitsUsageCostShared": [Function],
|
||||
"ruToolTipText": [Function],
|
||||
"selectedAutoPilotThroughput": [Function],
|
||||
"sharedAutoPilotThroughput": [Function],
|
||||
"sharedThroughputRangeText": [Function],
|
||||
"sharedThroughputSpendAck": [Function],
|
||||
"sharedThroughputSpendAckText": [Function],
|
||||
"sharedThroughputSpendAckVisible": [Function],
|
||||
"tableId": [Function],
|
||||
"throughput": [Function],
|
||||
"throughputRangeText": [Function],
|
||||
"throughputSpendAck": [Function],
|
||||
"throughputSpendAckText": [Function],
|
||||
"throughputSpendAckVisible": [Function],
|
||||
"title": [Function],
|
||||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
"addCollectionText": [Function],
|
||||
@@ -1015,32 +906,11 @@ exports[`GitHub Repos Panel should render Default properly 1`] = `
|
||||
},
|
||||
},
|
||||
},
|
||||
"graphStylingPane": GraphStylingPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"graphConfigUIData": Object {
|
||||
"nodeCaptionChoice": [Function],
|
||||
"nodeColorKeyChoice": [Function],
|
||||
"nodeIconChoice": [Function],
|
||||
"nodeIconSet": [Function],
|
||||
"nodeProperties": [Function],
|
||||
"nodePropertiesWithNone": [Function],
|
||||
"showNeighborType": [Function],
|
||||
},
|
||||
"id": "graphstylingpane",
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"hasStorageAnalyticsAfecFeature": [Function],
|
||||
"isAccountReady": [Function],
|
||||
"isAutoscaleDefaultEnabled": [Function],
|
||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||
"isHostedDataExplorerEnabled": [Function],
|
||||
"isLeftPaneExpanded": [Function],
|
||||
"isMongoIndexingEnabled": [Function],
|
||||
"isNotebookEnabled": [Function],
|
||||
"isNotebooksEnabledForAccount": [Function],
|
||||
@@ -1107,7 +977,6 @@ exports[`GitHub Repos Panel should render Default properly 1`] = `
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
},
|
||||
"toggleLeftPaneExpandedKeyPress": [Function],
|
||||
},
|
||||
"getRepo": [Function],
|
||||
"pinRepo": [Function],
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
import * as ko from "knockout";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
|
||||
export default class GraphStylingPane extends ContextualPaneBase {
|
||||
public graphConfigUIData: ViewModels.GraphConfigUiData;
|
||||
private remoteConfig: ViewModels.GraphConfigUiData;
|
||||
|
||||
constructor(options: ViewModels.PaneOptions) {
|
||||
super(options);
|
||||
|
||||
this.graphConfigUIData = {
|
||||
showNeighborType: ko.observable(ViewModels.NeighborType.TARGETS_ONLY),
|
||||
nodeProperties: ko.observableArray([]),
|
||||
nodePropertiesWithNone: ko.observableArray([]),
|
||||
nodeCaptionChoice: ko.observable(null),
|
||||
nodeColorKeyChoice: ko.observable(null),
|
||||
nodeIconChoice: ko.observable(null),
|
||||
nodeIconSet: ko.observable(null),
|
||||
};
|
||||
|
||||
this.graphConfigUIData.nodeCaptionChoice.subscribe((val) => {
|
||||
if (this.remoteConfig) {
|
||||
this.remoteConfig.nodeCaptionChoice(val);
|
||||
}
|
||||
});
|
||||
this.graphConfigUIData.nodeColorKeyChoice.subscribe((val) => {
|
||||
if (this.remoteConfig) {
|
||||
this.remoteConfig.nodeColorKeyChoice(val);
|
||||
}
|
||||
});
|
||||
this.graphConfigUIData.nodeIconChoice.subscribe((val) => {
|
||||
if (this.remoteConfig) {
|
||||
this.remoteConfig.nodeIconChoice(val);
|
||||
}
|
||||
});
|
||||
this.graphConfigUIData.nodeIconSet.subscribe((val) => {
|
||||
if (this.remoteConfig) {
|
||||
this.remoteConfig.nodeIconSet(val);
|
||||
}
|
||||
});
|
||||
this.graphConfigUIData.showNeighborType.subscribe((val) => {
|
||||
if (this.remoteConfig) {
|
||||
this.remoteConfig.showNeighborType(val);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public setData(config: ViewModels.GraphConfigUiData): void {
|
||||
// Update pane ko's with config's ko
|
||||
this.graphConfigUIData.nodeIconChoice(config.nodeIconChoice());
|
||||
this.graphConfigUIData.nodeIconSet(config.nodeIconSet());
|
||||
this.graphConfigUIData.nodeProperties(config.nodeProperties());
|
||||
this.graphConfigUIData.nodePropertiesWithNone(config.nodePropertiesWithNone());
|
||||
this.graphConfigUIData.showNeighborType(config.showNeighborType());
|
||||
// Make sure these two happen *after* setting the options of the dropdown,
|
||||
// otherwise, the ko will not get set if the choice is not part of the options
|
||||
this.graphConfigUIData.nodeCaptionChoice(config.nodeCaptionChoice());
|
||||
this.graphConfigUIData.nodeColorKeyChoice(config.nodeColorKeyChoice());
|
||||
|
||||
this.remoteConfig = config;
|
||||
}
|
||||
|
||||
public close() {
|
||||
this.remoteConfig = null;
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
37
src/Explorer/Panes/GraphStylingPanel/GraphStylingPanel.tsx
Normal file
37
src/Explorer/Panes/GraphStylingPanel/GraphStylingPanel.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import { GraphStyleComponent } from "../../Graph/GraphStyleComponent/GraphStyleComponent";
|
||||
import { IGraphConfig } from "../../Tabs/GraphTab";
|
||||
import { PanelFooterComponent } from "../PanelFooterComponent";
|
||||
interface GraphStylingProps {
|
||||
closePanel: () => void;
|
||||
igraphConfigUiData: ViewModels.IGraphConfigUiData;
|
||||
igraphConfig: IGraphConfig;
|
||||
getValues: (igraphConfig?: IGraphConfig) => void;
|
||||
}
|
||||
|
||||
export const GraphStylingPanel: FunctionComponent<GraphStylingProps> = ({
|
||||
closePanel,
|
||||
igraphConfigUiData,
|
||||
igraphConfig,
|
||||
getValues,
|
||||
}: GraphStylingProps): JSX.Element => {
|
||||
const buttonLabel = "Ok";
|
||||
|
||||
const submit = () => {
|
||||
closePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<form className="panelFormWrapper" onSubmit={submit}>
|
||||
<div className="panelMainContent">
|
||||
<GraphStyleComponent
|
||||
igraphConfigUiData={igraphConfigUiData}
|
||||
igraphConfig={igraphConfig}
|
||||
getValues={getValues}
|
||||
></GraphStyleComponent>
|
||||
</div>
|
||||
<PanelFooterComponent buttonLabel={buttonLabel} />
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,5 @@
|
||||
import AddDatabasePaneTemplate from "./AddDatabasePane.html";
|
||||
import CassandraAddCollectionPaneTemplate from "./CassandraAddCollectionPane.html";
|
||||
import GraphStylingPaneTemplate from "./GraphStylingPane.html";
|
||||
|
||||
export class PaneComponent {
|
||||
constructor(data: any) {
|
||||
return data.data;
|
||||
@@ -17,15 +15,6 @@ export class AddDatabasePaneComponent {
|
||||
}
|
||||
}
|
||||
|
||||
export class GraphStylingPaneComponent {
|
||||
constructor() {
|
||||
return {
|
||||
viewModel: PaneComponent,
|
||||
template: GraphStylingPaneTemplate,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CassandraAddCollectionPaneComponent {
|
||||
constructor() {
|
||||
return {
|
||||
|
||||
@@ -8,7 +8,6 @@ export interface PanelInfoErrorProps {
|
||||
link?: string;
|
||||
linkText?: string;
|
||||
openNotificationConsole?: () => void;
|
||||
formError?: boolean;
|
||||
}
|
||||
|
||||
export const PanelInfoErrorComponent: React.FunctionComponent<PanelInfoErrorProps> = ({
|
||||
@@ -18,9 +17,8 @@ export const PanelInfoErrorComponent: React.FunctionComponent<PanelInfoErrorProp
|
||||
link,
|
||||
linkText,
|
||||
openNotificationConsole,
|
||||
formError = true,
|
||||
}: PanelInfoErrorProps): JSX.Element => {
|
||||
let icon: JSX.Element;
|
||||
let icon: JSX.Element = <Icon iconName="InfoSolid" className="panelLargeInfoIcon" aria-label="Infomation" />;
|
||||
if (messageType === "error") {
|
||||
icon = <Icon iconName="StatusErrorFull" className="panelErrorIcon" aria-label="error" />;
|
||||
} else if (messageType === "warning") {
|
||||
@@ -30,25 +28,23 @@ export const PanelInfoErrorComponent: React.FunctionComponent<PanelInfoErrorProp
|
||||
}
|
||||
|
||||
return (
|
||||
formError && (
|
||||
<Stack className="panelInfoErrorContainer" horizontal verticalAlign="center">
|
||||
{icon}
|
||||
<span className="panelWarningErrorDetailsLinkContainer">
|
||||
<Text className="panelWarningErrorMessage" variant="small" aria-label="message">
|
||||
{message}
|
||||
{link && linkText && (
|
||||
<Link target="_blank" href={link}>
|
||||
{linkText}
|
||||
</Link>
|
||||
)}
|
||||
</Text>
|
||||
{showErrorDetails && (
|
||||
<a className="paneErrorLink" role="link" onClick={openNotificationConsole}>
|
||||
More details
|
||||
</a>
|
||||
<Stack className="panelInfoErrorContainer" horizontal verticalAlign="center">
|
||||
{icon}
|
||||
<span className="panelWarningErrorDetailsLinkContainer">
|
||||
<Text className="panelWarningErrorMessage" variant="small" aria-label="message">
|
||||
{message}
|
||||
{link && linkText && (
|
||||
<Link target="_blank" href={link}>
|
||||
{linkText}
|
||||
</Link>
|
||||
)}
|
||||
</span>
|
||||
</Stack>
|
||||
)
|
||||
</Text>
|
||||
{showErrorDetails && (
|
||||
<a className="paneErrorLink" role="link" onClick={openNotificationConsole}>
|
||||
More details
|
||||
</a>
|
||||
)}
|
||||
</span>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@ const expandConsole = jest.fn();
|
||||
const props = {
|
||||
expandConsole,
|
||||
formError: "",
|
||||
formErrorDetail: "",
|
||||
isExecuting: false,
|
||||
submitButtonText: "Load",
|
||||
onSubmit,
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import React, { FunctionComponent, ReactNode } from "react";
|
||||
import { PanelFooterComponent } from "../PanelFooterComponent";
|
||||
import { PanelInfoErrorComponent, PanelInfoErrorProps } from "../PanelInfoErrorComponent";
|
||||
import { PanelInfoErrorComponent } from "../PanelInfoErrorComponent";
|
||||
import { PanelLoadingScreen } from "../PanelLoadingScreen";
|
||||
|
||||
export interface RightPaneFormProps {
|
||||
expandConsole: () => void;
|
||||
formError: string;
|
||||
formErrorDetail: string;
|
||||
isExecuting: boolean;
|
||||
onSubmit: () => void;
|
||||
submitButtonText: string;
|
||||
@@ -17,7 +16,6 @@ export interface RightPaneFormProps {
|
||||
export const RightPaneForm: FunctionComponent<RightPaneFormProps> = ({
|
||||
expandConsole,
|
||||
formError,
|
||||
formErrorDetail,
|
||||
isExecuting,
|
||||
onSubmit,
|
||||
submitButtonText,
|
||||
@@ -29,18 +27,17 @@ export const RightPaneForm: FunctionComponent<RightPaneFormProps> = ({
|
||||
onSubmit();
|
||||
};
|
||||
|
||||
const panelInfoErrorProps: PanelInfoErrorProps = {
|
||||
messageType: "error",
|
||||
message: formError,
|
||||
formError: formError !== "",
|
||||
showErrorDetails: formErrorDetail !== "",
|
||||
openNotificationConsole: expandConsole,
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<PanelInfoErrorComponent {...panelInfoErrorProps} />
|
||||
<form className="panelFormWrapper" onSubmit={handleOnSubmit}>
|
||||
{formError && (
|
||||
<PanelInfoErrorComponent
|
||||
messageType="error"
|
||||
message={formError}
|
||||
showErrorDetails={true}
|
||||
openNotificationConsole={expandConsole}
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
{!isSubmitButtonHidden && <PanelFooterComponent buttonLabel={submitButtonText} />}
|
||||
</form>
|
||||
|
||||
@@ -4,18 +4,10 @@ exports[`Right Pane Form should render Default properly 1`] = `
|
||||
<RightPaneForm
|
||||
expandConsole={[MockFunction]}
|
||||
formError=""
|
||||
formErrorDetail=""
|
||||
isExecuting={false}
|
||||
onSubmit={[MockFunction]}
|
||||
submitButtonText="Load"
|
||||
>
|
||||
<PanelInfoErrorComponent
|
||||
formError={false}
|
||||
message=""
|
||||
messageType="error"
|
||||
openNotificationConsole={[MockFunction]}
|
||||
showErrorDetails={false}
|
||||
/>
|
||||
<form
|
||||
className="panelFormWrapper"
|
||||
onSubmit={[Function]}
|
||||
|
||||
@@ -18,7 +18,6 @@ export const SettingsPane: FunctionComponent<SettingsPaneProps> = ({
|
||||
expandConsole,
|
||||
closePanel,
|
||||
}: SettingsPaneProps) => {
|
||||
const [formErrors, setFormErrors] = useState<string>("");
|
||||
const [isExecuting, setIsExecuting] = useState<boolean>(false);
|
||||
const [pageOption, setPageOption] = useState<string>(
|
||||
LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage) === Constants.Queries.unlimitedItemsPerPage
|
||||
@@ -50,7 +49,6 @@ export const SettingsPane: FunctionComponent<SettingsPaneProps> = ({
|
||||
const shouldShowParallelismOption = userContext.apiType !== "Gremlin";
|
||||
|
||||
const handlerOnSubmit = (e: MouseEvent<HTMLButtonElement>) => {
|
||||
setFormErrors("");
|
||||
setIsExecuting(true);
|
||||
|
||||
LocalStorageUtility.setEntryNumber(
|
||||
@@ -104,8 +102,7 @@ export const SettingsPane: FunctionComponent<SettingsPaneProps> = ({
|
||||
|
||||
const genericPaneProps: RightPaneFormProps = {
|
||||
expandConsole,
|
||||
formError: formErrors,
|
||||
formErrorDetail: "",
|
||||
formError: "",
|
||||
isExecuting,
|
||||
submitButtonText: "Apply",
|
||||
onSubmit: () => handlerOnSubmit(undefined),
|
||||
|
||||
@@ -4,7 +4,6 @@ exports[`Settings Pane should render Default properly 1`] = `
|
||||
<RightPaneForm
|
||||
expandConsole={[Function]}
|
||||
formError=""
|
||||
formErrorDetail=""
|
||||
isExecuting={false}
|
||||
onSubmit={[Function]}
|
||||
submitButtonText="Apply"
|
||||
@@ -152,7 +151,6 @@ exports[`Settings Pane should render Gremlin properly 1`] = `
|
||||
<RightPaneForm
|
||||
expandConsole={[Function]}
|
||||
formError=""
|
||||
formErrorDetail=""
|
||||
isExecuting={false}
|
||||
onSubmit={[Function]}
|
||||
submitButtonText="Apply"
|
||||
|
||||
@@ -11,115 +11,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
|
||||
"_closeSynapseLinkModalDialog": [Function],
|
||||
"_isAfecFeatureRegistered": [Function],
|
||||
"_isInitializingNotebooks": false,
|
||||
"_panes": Array [
|
||||
AddDatabasePane {
|
||||
"autoPilotUsageCost": [Function],
|
||||
"canConfigureThroughput": [Function],
|
||||
"canExceedMaximumValue": [Function],
|
||||
"canRequestSupport": [Function],
|
||||
"container": [Circular],
|
||||
"costsVisible": [Function],
|
||||
"databaseCreateNewShared": [Function],
|
||||
"databaseId": [Function],
|
||||
"databaseIdLabel": [Function],
|
||||
"databaseIdPlaceHolder": [Function],
|
||||
"databaseIdTooltipText": [Function],
|
||||
"databaseLevelThroughputTooltipText": [Function],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isFreeTierAccount": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"maxAutoPilotThroughputSet": [Function],
|
||||
"maxThroughputRU": [Function],
|
||||
"maxThroughputRUText": [Function],
|
||||
"minThroughputRU": [Function],
|
||||
"onMoreDetailsKeyPress": [Function],
|
||||
"requestUnitsUsageCost": [Function],
|
||||
"ruToolTipText": [Function],
|
||||
"showUpsellMessage": [Function],
|
||||
"throughput": [Function],
|
||||
"throughputRangeText": [Function],
|
||||
"throughputSpendAck": [Function],
|
||||
"throughputSpendAckText": [Function],
|
||||
"throughputSpendAckVisible": [Function],
|
||||
"title": [Function],
|
||||
"upsellAnchorText": [Function],
|
||||
"upsellAnchorUrl": [Function],
|
||||
"upsellMessage": [Function],
|
||||
"upsellMessageAriaLabel": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
GraphStylingPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"graphConfigUIData": Object {
|
||||
"nodeCaptionChoice": [Function],
|
||||
"nodeColorKeyChoice": [Function],
|
||||
"nodeIconChoice": [Function],
|
||||
"nodeIconSet": [Function],
|
||||
"nodeProperties": [Function],
|
||||
"nodePropertiesWithNone": [Function],
|
||||
"showNeighborType": [Function],
|
||||
},
|
||||
"id": "graphstylingpane",
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
CassandraAddCollectionPane {
|
||||
"autoPilotUsageCost": [Function],
|
||||
"canConfigureThroughput": [Function],
|
||||
"canExceedMaximumValue": [Function],
|
||||
"canRequestSupport": [Function],
|
||||
"container": [Circular],
|
||||
"costsVisible": [Function],
|
||||
"createTableQuery": [Function],
|
||||
"dedicateTableThroughput": [Function],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "cassandraaddcollectionpane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isFreeTierAccount": [Function],
|
||||
"isSharedAutoPilotSelected": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"keyspaceCreateNew": [Function],
|
||||
"keyspaceHasSharedOffer": [Function],
|
||||
"keyspaceId": [Function],
|
||||
"keyspaceIds": [Function],
|
||||
"keyspaceOffers": Map {},
|
||||
"keyspaceThroughput": [Function],
|
||||
"maxThroughputRU": [Function],
|
||||
"minThroughputRU": [Function],
|
||||
"requestUnitsUsageCostDedicated": [Function],
|
||||
"requestUnitsUsageCostShared": [Function],
|
||||
"ruToolTipText": [Function],
|
||||
"selectedAutoPilotThroughput": [Function],
|
||||
"sharedAutoPilotThroughput": [Function],
|
||||
"sharedThroughputRangeText": [Function],
|
||||
"sharedThroughputSpendAck": [Function],
|
||||
"sharedThroughputSpendAckText": [Function],
|
||||
"sharedThroughputSpendAckVisible": [Function],
|
||||
"tableId": [Function],
|
||||
"throughput": [Function],
|
||||
"throughputRangeText": [Function],
|
||||
"throughputSpendAck": [Function],
|
||||
"throughputSpendAckText": [Function],
|
||||
"throughputSpendAckVisible": [Function],
|
||||
"title": [Function],
|
||||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
"addCollectionText": [Function],
|
||||
@@ -1005,32 +896,11 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
|
||||
},
|
||||
},
|
||||
},
|
||||
"graphStylingPane": GraphStylingPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"graphConfigUIData": Object {
|
||||
"nodeCaptionChoice": [Function],
|
||||
"nodeColorKeyChoice": [Function],
|
||||
"nodeIconChoice": [Function],
|
||||
"nodeIconSet": [Function],
|
||||
"nodeProperties": [Function],
|
||||
"nodePropertiesWithNone": [Function],
|
||||
"showNeighborType": [Function],
|
||||
},
|
||||
"id": "graphstylingpane",
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"hasStorageAnalyticsAfecFeature": [Function],
|
||||
"isAccountReady": [Function],
|
||||
"isAutoscaleDefaultEnabled": [Function],
|
||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||
"isHostedDataExplorerEnabled": [Function],
|
||||
"isLeftPaneExpanded": [Function],
|
||||
"isMongoIndexingEnabled": [Function],
|
||||
"isNotebookEnabled": [Function],
|
||||
"isNotebooksEnabledForAccount": [Function],
|
||||
@@ -1097,7 +967,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
},
|
||||
"toggleLeftPaneExpandedKeyPress": [Function],
|
||||
}
|
||||
}
|
||||
inProgressMessage="Creating directory "
|
||||
|
||||
@@ -22,15 +22,12 @@ export const UploadFilePane: FunctionComponent<UploadFilePanelProps> = ({
|
||||
|
||||
const [files, setFiles] = useState<FileList>();
|
||||
const [formErrors, setFormErrors] = useState<string>("");
|
||||
const [formErrorsDetails, setFormErrorsDetails] = useState<string>("");
|
||||
const [isExecuting, setIsExecuting] = useState<boolean>(false);
|
||||
|
||||
const submit = () => {
|
||||
setFormErrors("");
|
||||
setFormErrorsDetails("");
|
||||
if (!files || files.length === 0) {
|
||||
setFormErrors("No file specified");
|
||||
setFormErrorsDetails("No file specified. Please input a file.");
|
||||
setFormErrors("No file specified. Please input a file.");
|
||||
logConsoleError(`${errorMessage} -- No file specified. Please input a file.`);
|
||||
return;
|
||||
}
|
||||
@@ -49,7 +46,6 @@ export const UploadFilePane: FunctionComponent<UploadFilePanelProps> = ({
|
||||
},
|
||||
(error: string) => {
|
||||
setFormErrors(errorMessage);
|
||||
setFormErrorsDetails(`${errorMessage}: ${error}`);
|
||||
logConsoleError(`${errorMessage} ${file.name}: ${error}`);
|
||||
}
|
||||
)
|
||||
@@ -85,7 +81,6 @@ export const UploadFilePane: FunctionComponent<UploadFilePanelProps> = ({
|
||||
const genericPaneProps: RightPaneFormProps = {
|
||||
expandConsole,
|
||||
formError: formErrors,
|
||||
formErrorDetail: formErrorsDetails,
|
||||
isExecuting: isExecuting,
|
||||
submitButtonText: "Upload",
|
||||
onSubmit: submit,
|
||||
|
||||
@@ -15,15 +15,14 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ explo
|
||||
const [files, setFiles] = useState<FileList>();
|
||||
const [uploadFileData, setUploadFileData] = useState<UploadDetailsRecord[]>([]);
|
||||
const [formError, setFormError] = useState<string>("");
|
||||
const [formErrorDetail, setFormErrorDetail] = useState<string>("");
|
||||
const [isExecuting, setIsExecuting] = useState<boolean>();
|
||||
|
||||
const onSubmit = () => {
|
||||
setFormError("");
|
||||
if (!files || files.length === 0) {
|
||||
setFormError("No files specified");
|
||||
setFormErrorDetail("No files were specified. Please input at least one file.");
|
||||
setFormError("No files were specified. Please input at least one file.");
|
||||
logConsoleError("Could not upload items -- No files were specified. Please input at least one file.");
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedCollection = explorer.findSelectedCollection();
|
||||
@@ -40,7 +39,6 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ explo
|
||||
(error: Error) => {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
setFormError(errorMessage);
|
||||
setFormErrorDetail(errorMessage);
|
||||
}
|
||||
)
|
||||
.finally(() => {
|
||||
@@ -55,7 +53,6 @@ export const UploadItemsPane: FunctionComponent<UploadItemsPaneProps> = ({ explo
|
||||
const genericPaneProps: RightPaneFormProps = {
|
||||
expandConsole: () => explorer.expandConsole(),
|
||||
formError,
|
||||
formErrorDetail,
|
||||
isExecuting: isExecuting,
|
||||
submitButtonText: "Upload",
|
||||
onSubmit,
|
||||
|
||||
@@ -4,7 +4,6 @@ exports[`Upload Items Pane should render Default properly 1`] = `
|
||||
<RightPaneForm
|
||||
expandConsole={[Function]}
|
||||
formError=""
|
||||
formErrorDetail=""
|
||||
onSubmit={[Function]}
|
||||
submitButtonText="Upload"
|
||||
>
|
||||
|
||||
@@ -9,115 +9,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
"_closeSynapseLinkModalDialog": [Function],
|
||||
"_isAfecFeatureRegistered": [Function],
|
||||
"_isInitializingNotebooks": false,
|
||||
"_panes": Array [
|
||||
AddDatabasePane {
|
||||
"autoPilotUsageCost": [Function],
|
||||
"canConfigureThroughput": [Function],
|
||||
"canExceedMaximumValue": [Function],
|
||||
"canRequestSupport": [Function],
|
||||
"container": [Circular],
|
||||
"costsVisible": [Function],
|
||||
"databaseCreateNewShared": [Function],
|
||||
"databaseId": [Function],
|
||||
"databaseIdLabel": [Function],
|
||||
"databaseIdPlaceHolder": [Function],
|
||||
"databaseIdTooltipText": [Function],
|
||||
"databaseLevelThroughputTooltipText": [Function],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"freeTierExceedThroughputTooltip": [Function],
|
||||
"id": "adddatabasepane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isFreeTierAccount": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"maxAutoPilotThroughputSet": [Function],
|
||||
"maxThroughputRU": [Function],
|
||||
"maxThroughputRUText": [Function],
|
||||
"minThroughputRU": [Function],
|
||||
"onMoreDetailsKeyPress": [Function],
|
||||
"requestUnitsUsageCost": [Function],
|
||||
"ruToolTipText": [Function],
|
||||
"showUpsellMessage": [Function],
|
||||
"throughput": [Function],
|
||||
"throughputRangeText": [Function],
|
||||
"throughputSpendAck": [Function],
|
||||
"throughputSpendAckText": [Function],
|
||||
"throughputSpendAckVisible": [Function],
|
||||
"title": [Function],
|
||||
"upsellAnchorText": [Function],
|
||||
"upsellAnchorUrl": [Function],
|
||||
"upsellMessage": [Function],
|
||||
"upsellMessageAriaLabel": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
GraphStylingPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"graphConfigUIData": Object {
|
||||
"nodeCaptionChoice": [Function],
|
||||
"nodeColorKeyChoice": [Function],
|
||||
"nodeIconChoice": [Function],
|
||||
"nodeIconSet": [Function],
|
||||
"nodeProperties": [Function],
|
||||
"nodePropertiesWithNone": [Function],
|
||||
"showNeighborType": [Function],
|
||||
},
|
||||
"id": "graphstylingpane",
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
CassandraAddCollectionPane {
|
||||
"autoPilotUsageCost": [Function],
|
||||
"canConfigureThroughput": [Function],
|
||||
"canExceedMaximumValue": [Function],
|
||||
"canRequestSupport": [Function],
|
||||
"container": [Circular],
|
||||
"costsVisible": [Function],
|
||||
"createTableQuery": [Function],
|
||||
"dedicateTableThroughput": [Function],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"id": "cassandraaddcollectionpane",
|
||||
"isAutoPilotSelected": [Function],
|
||||
"isExecuting": [Function],
|
||||
"isFreeTierAccount": [Function],
|
||||
"isSharedAutoPilotSelected": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"keyspaceCreateNew": [Function],
|
||||
"keyspaceHasSharedOffer": [Function],
|
||||
"keyspaceId": [Function],
|
||||
"keyspaceIds": [Function],
|
||||
"keyspaceOffers": Map {},
|
||||
"keyspaceThroughput": [Function],
|
||||
"maxThroughputRU": [Function],
|
||||
"minThroughputRU": [Function],
|
||||
"requestUnitsUsageCostDedicated": [Function],
|
||||
"requestUnitsUsageCostShared": [Function],
|
||||
"ruToolTipText": [Function],
|
||||
"selectedAutoPilotThroughput": [Function],
|
||||
"sharedAutoPilotThroughput": [Function],
|
||||
"sharedThroughputRangeText": [Function],
|
||||
"sharedThroughputSpendAck": [Function],
|
||||
"sharedThroughputSpendAckText": [Function],
|
||||
"sharedThroughputSpendAckVisible": [Function],
|
||||
"tableId": [Function],
|
||||
"throughput": [Function],
|
||||
"throughputRangeText": [Function],
|
||||
"throughputSpendAck": [Function],
|
||||
"throughputSpendAckText": [Function],
|
||||
"throughputSpendAckVisible": [Function],
|
||||
"title": [Function],
|
||||
"userTableQuery": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
],
|
||||
"_refreshSparkEnabledStateForAccount": [Function],
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
"addCollectionText": [Function],
|
||||
@@ -1003,26 +894,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
},
|
||||
},
|
||||
},
|
||||
"graphStylingPane": GraphStylingPane {
|
||||
"container": [Circular],
|
||||
"firstFieldHasFocus": [Function],
|
||||
"formErrors": [Function],
|
||||
"formErrorsDetails": [Function],
|
||||
"graphConfigUIData": Object {
|
||||
"nodeCaptionChoice": [Function],
|
||||
"nodeColorKeyChoice": [Function],
|
||||
"nodeIconChoice": [Function],
|
||||
"nodeIconSet": [Function],
|
||||
"nodeProperties": [Function],
|
||||
"nodePropertiesWithNone": [Function],
|
||||
"showNeighborType": [Function],
|
||||
},
|
||||
"id": "graphstylingpane",
|
||||
"isExecuting": [Function],
|
||||
"isTemplateReady": [Function],
|
||||
"title": [Function],
|
||||
"visible": [Function],
|
||||
},
|
||||
"hasStorageAnalyticsAfecFeature": [Function],
|
||||
"isAccountReady": [Function],
|
||||
"isAutoscaleDefaultEnabled": [Function],
|
||||
@@ -1030,7 +901,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
"isHostedDataExplorerEnabled": [Function],
|
||||
"isLastCollection": [Function],
|
||||
"isLastNonEmptyDatabase": [Function],
|
||||
"isLeftPaneExpanded": [Function],
|
||||
"isMongoIndexingEnabled": [Function],
|
||||
"isNotebookEnabled": [Function],
|
||||
"isNotebooksEnabledForAccount": [Function],
|
||||
@@ -1099,7 +969,6 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
},
|
||||
"toggleLeftPaneExpandedKeyPress": [Function],
|
||||
}
|
||||
}
|
||||
openNotificationConsole={[Function]}
|
||||
|
||||
Reference in New Issue
Block a user