From f0e32491d7a740c0f50370abc34a02515eda5c3a Mon Sep 17 00:00:00 2001 From: Asier Isayas Date: Wed, 19 Feb 2025 15:16:32 -0500 Subject: [PATCH] Partition Key, Throughput, Unique Keys --- .../AddCollectionPanel/AddCollectionPanel.tsx | 40 ++------ ...ility.ts => AddCollectionPanelUtility.tsx} | 22 +++++ ...Key.tsx => AddMVPartitionKeyComponent.tsx} | 6 +- .../AddMVThroughput.tsx | 10 -- .../AddMVThroughputComponent.tsx | 91 +++++++++++++++++++ .../AddMVUniqueKeysComponent.tsx | 78 ++++++++++++++++ .../AddMaterializedViewPanel.tsx | 41 ++++++++- 7 files changed, 241 insertions(+), 47 deletions(-) rename src/Explorer/Panes/AddCollectionPanel/{AddCollectionPanelUtility.ts => AddCollectionPanelUtility.tsx} (67%) rename src/Explorer/Panes/AddMaterializedViewPanel/{AddMVPartitionKey.tsx => AddMVPartitionKeyComponent.tsx} (93%) delete mode 100644 src/Explorer/Panes/AddMaterializedViewPanel/AddMVThroughput.tsx create mode 100644 src/Explorer/Panes/AddMaterializedViewPanel/AddMVThroughputComponent.tsx create mode 100644 src/Explorer/Panes/AddMaterializedViewPanel/AddMVUniqueKeysComponent.tsx diff --git a/src/Explorer/Panes/AddCollectionPanel/AddCollectionPanel.tsx b/src/Explorer/Panes/AddCollectionPanel/AddCollectionPanel.tsx index 897427d02..541254d6e 100644 --- a/src/Explorer/Panes/AddCollectionPanel/AddCollectionPanel.tsx +++ b/src/Explorer/Panes/AddCollectionPanel/AddCollectionPanel.tsx @@ -31,6 +31,8 @@ import { getPartitionKeyName, getPartitionKeyPlaceHolder, getPartitionKeyTooltipText, + isFreeTierAccount, + UniqueKeysHeader, } from "Explorer/Panes/AddCollectionPanel/AddCollectionPanelUtility"; import { useSidePanel } from "hooks/useSidePanel"; import { useTeachingBubble } from "hooks/useTeachingBubble"; @@ -196,7 +198,7 @@ export class AddCollectionPanel extends React.Component )} - {!this.state.errorMessage && this.isFreeTierAccount() && ( + {!this.state.errorMessage && isFreeTierAccount() && ( (this.newDatabaseThroughput = throughput)} setIsAutoscale={(isAutoscale: boolean) => (this.isNewDatabaseAutoscale = isAutoscale)} @@ -734,10 +736,10 @@ export class AddCollectionPanel extends React.Component (this.collectionThroughput = throughput)} setIsAutoscale={(isAutoscale: boolean) => (this.isCollectionAutoscale = isAutoscale)} @@ -752,27 +754,7 @@ export class AddCollectionPanel extends React.Component - - - Unique keys - - - - - - + {UniqueKeysHeader()} {this.state.uniqueKeys.map((uniqueKey: string, i: number): JSX.Element => { return ( @@ -1143,10 +1125,6 @@ export class AddCollectionPanel extends React.Component + + Unique keys + + + + + + ); +} diff --git a/src/Explorer/Panes/AddMaterializedViewPanel/AddMVPartitionKey.tsx b/src/Explorer/Panes/AddMaterializedViewPanel/AddMVPartitionKeyComponent.tsx similarity index 93% rename from src/Explorer/Panes/AddMaterializedViewPanel/AddMVPartitionKey.tsx rename to src/Explorer/Panes/AddMaterializedViewPanel/AddMVPartitionKeyComponent.tsx index 506619de0..bea52d9e9 100644 --- a/src/Explorer/Panes/AddMaterializedViewPanel/AddMVPartitionKey.tsx +++ b/src/Explorer/Panes/AddMaterializedViewPanel/AddMVPartitionKeyComponent.tsx @@ -7,7 +7,7 @@ import { } from "Explorer/Panes/AddCollectionPanel/AddCollectionPanelUtility"; import React from "react"; -export interface AddMVPartitionKeyProps { +export interface AddMVPartitionKeyComponentProps { partitionKey?: string; setPartitionKey: React.Dispatch>; subPartitionKeys: string[]; @@ -16,7 +16,7 @@ export interface AddMVPartitionKeyProps { setUseHashV1: React.Dispatch>; } -export const AddMVPartitionKey = (props: AddMVPartitionKeyProps): JSX.Element => { +export const AddMVPartitionKeyComponent = (props: AddMVPartitionKeyComponentProps): JSX.Element => { const { partitionKey, setPartitionKey, subPartitionKeys, setSubPartitionKeys, useHashV1, setUseHashV1 } = props; const partitionKeyValueOnChange = (value: string): void => { @@ -60,6 +60,7 @@ export const AddMVPartitionKey = (props: AddMVPartitionKeyProps): JSX.Element => aria-label={getPartitionKeyName()} pattern=".*" value={partitionKey} + style={{ marginBottom: 8 }} onChange={(event: React.ChangeEvent) => { partitionKeyValueOnChange(event.target.value); }} @@ -88,6 +89,7 @@ export const AddMVPartitionKey = (props: AddMVPartitionKeyProps): JSX.Element => placeholder={getPartitionKeyPlaceHolder(subPartitionKeyIndex)} aria-label={getPartitionKeyName()} pattern={".*"} + title={""} value={subPartitionKey} onChange={(event: React.ChangeEvent) => { subPartitionKeysValueOnChange(event.target.value, subPartitionKeyIndex); diff --git a/src/Explorer/Panes/AddMaterializedViewPanel/AddMVThroughput.tsx b/src/Explorer/Panes/AddMaterializedViewPanel/AddMVThroughput.tsx deleted file mode 100644 index 036ffdab0..000000000 --- a/src/Explorer/Panes/AddMaterializedViewPanel/AddMVThroughput.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { Stack } from "@fluentui/react"; -import React from "react"; - -export interface AddMVThroughputProps { - // isQuickstart: boolean; -} - -export const AddMVThroughput = (props: AddMVThroughputProps): JSX.Element => { - return ; -}; diff --git a/src/Explorer/Panes/AddMaterializedViewPanel/AddMVThroughputComponent.tsx b/src/Explorer/Panes/AddMaterializedViewPanel/AddMVThroughputComponent.tsx new file mode 100644 index 000000000..0dd40cf24 --- /dev/null +++ b/src/Explorer/Panes/AddMaterializedViewPanel/AddMVThroughputComponent.tsx @@ -0,0 +1,91 @@ +import { Checkbox, Stack } from "@fluentui/react"; +import { Collection } from "Contracts/ViewModels"; +import { ThroughputInput } from "Explorer/Controls/ThroughputInput/ThroughputInput"; +import { isFreeTierAccount } from "Explorer/Panes/AddCollectionPanel/AddCollectionPanelUtility"; +import { useDatabases } from "Explorer/useDatabases"; +import React from "react"; +import { getCollectionName } from "Utils/APITypeUtils"; +import { isServerlessAccount } from "Utils/CapabilityUtils"; + +export interface AddMVThroughputComponentProps { + selectedSourceContainer: Collection; + enableDedicatedThroughput: boolean; + setEnabledDedicatedThroughput: React.Dispatch>; + materializedViewThroughputOnChange: (materializedViewThroughputValue: number) => void; + isMaterializedViewAutoscaleOnChange: (isMaterializedViewAutoscaleValue: boolean) => void; + setIsThroughputCapExceeded: React.Dispatch>; + isCostAknowledgedOnChange: (isCostAknowledgedValue: boolean) => void; +} + +export const AddMVThroughputComponent = (props: AddMVThroughputComponentProps): JSX.Element => { + const { + selectedSourceContainer, + enableDedicatedThroughput, + setEnabledDedicatedThroughput, + materializedViewThroughputOnChange, + isMaterializedViewAutoscaleOnChange, + setIsThroughputCapExceeded, + isCostAknowledgedOnChange, + } = props; + + const isSelectedSourceContainerSharedThroughput = (): boolean => { + if (!selectedSourceContainer) { + return false; + } + + return !!selectedSourceContainer.getDatabase().offer(); + }; + + const showCollectionThroughputInput = (): boolean => { + if (isServerlessAccount()) { + return false; + } + + if (enableDedicatedThroughput) { + return true; + } + + return !!selectedSourceContainer && !isSelectedSourceContainerSharedThroughput(); + }; + + return ( + + {!isServerlessAccount() && isSelectedSourceContainerSharedThroughput() && ( + + setEnabledDedicatedThroughput(isChecked)} + /> + + )} + {showCollectionThroughputInput() && ( + { + materializedViewThroughputOnChange(throughput); + }} + setIsAutoscale={(isAutoscale: boolean) => { + isMaterializedViewAutoscaleOnChange(isAutoscale); + }} + setIsThroughputCapExceeded={(isThroughputCapExceeded: boolean) => { + setIsThroughputCapExceeded(isThroughputCapExceeded); + }} + onCostAcknowledgeChange={(isAcknowledged: boolean) => { + isCostAknowledgedOnChange(isAcknowledged); + }} + /> + )} + + ); +}; diff --git a/src/Explorer/Panes/AddMaterializedViewPanel/AddMVUniqueKeysComponent.tsx b/src/Explorer/Panes/AddMaterializedViewPanel/AddMVUniqueKeysComponent.tsx new file mode 100644 index 000000000..6c113b5f0 --- /dev/null +++ b/src/Explorer/Panes/AddMaterializedViewPanel/AddMVUniqueKeysComponent.tsx @@ -0,0 +1,78 @@ +import { ActionButton, IconButton, Stack } from "@fluentui/react"; +import { UniqueKeysHeader } from "Explorer/Panes/AddCollectionPanel/AddCollectionPanelUtility"; +import React from "react"; +import { userContext } from "UserContext"; + +export interface AddMVUniqueKeysComponentProps { + uniqueKeys: string[]; + setUniqueKeys: React.Dispatch>; +} + +export const AddMVUniqueKeysComponent = (props: AddMVUniqueKeysComponentProps): JSX.Element => { + const { uniqueKeys, setUniqueKeys } = props; + + const updateUniqueKeysOnChange = (value: string, uniqueKeyToReplaceIndex: number): void => { + const updatedUniqueKeys = uniqueKeys.map((uniqueKey: string, uniqueKeyIndex: number) => { + if (uniqueKeyToReplaceIndex === uniqueKeyIndex) { + return value; + } + return uniqueKey; + }); + setUniqueKeys(updatedUniqueKeys); + }; + + const deleteUniqueKeyOnClick = (uniqueKeyToDeleteIndex: number): void => { + const updatedUniqueKeys = uniqueKeys.filter((_, uniqueKeyIndex) => uniqueKeyToDeleteIndex !== uniqueKeyIndex); + setUniqueKeys(updatedUniqueKeys); + }; + + const addUniqueKeyOnClick = (): void => { + setUniqueKeys([...uniqueKeys, ""]); + }; + + return ( + + {UniqueKeysHeader()} + + {uniqueKeys.map((uniqueKey: string, uniqueKeyIndex: number): JSX.Element => { + return ( + + ) => { + updateUniqueKeysOnChange(event.target.value, uniqueKeyIndex); + }} + /> + + { + deleteUniqueKeyOnClick(uniqueKeyIndex); + }} + /> + + ); + })} + + { + addUniqueKeyOnClick(); + }} + > + Add unique key + + + ); +}; diff --git a/src/Explorer/Panes/AddMaterializedViewPanel/AddMaterializedViewPanel.tsx b/src/Explorer/Panes/AddMaterializedViewPanel/AddMaterializedViewPanel.tsx index 6e36e0c16..6a4d5daa5 100644 --- a/src/Explorer/Panes/AddMaterializedViewPanel/AddMaterializedViewPanel.tsx +++ b/src/Explorer/Panes/AddMaterializedViewPanel/AddMaterializedViewPanel.tsx @@ -13,8 +13,9 @@ import { import { Collection, Database } from "Contracts/ViewModels"; import Explorer from "Explorer/Explorer"; import { getPartitionKey } from "Explorer/Panes/AddCollectionPanel/AddCollectionPanelUtility"; -import { AddMVPartitionKey } from "Explorer/Panes/AddMaterializedViewPanel/AddMVPartitionKey"; -import { AddMVThroughput } from "Explorer/Panes/AddMaterializedViewPanel/AddMVThroughput"; +import { AddMVPartitionKeyComponent } from "Explorer/Panes/AddMaterializedViewPanel/AddMVPartitionKeyComponent"; +import { AddMVThroughputComponent } from "Explorer/Panes/AddMaterializedViewPanel/AddMVThroughputComponent"; +import { AddMVUniqueKeysComponent } from "Explorer/Panes/AddMaterializedViewPanel/AddMVUniqueKeysComponent"; import { useDatabases } from "Explorer/useDatabases"; import React, { useEffect, useState } from "react"; @@ -32,6 +33,9 @@ export const AddMaterializedViewPanel = (props: AddMaterializedViewPanelProps): const [partitionKey, setPartitionKey] = useState(getPartitionKey()); const [subPartitionKeys, setSubPartitionKeys] = useState([]); const [useHashV1, setUseHashV1] = useState(); + const [enableDedicatedThroughput, setEnabledDedicatedThroughput] = useState(); + const [isThroughputCapExceeded, setIsThroughputCapExceeded] = useState(); + const [uniqueKeys, setUniqueKeys] = useState([]); useEffect(() => { const sourceContainerOptions: IDropdownOption[] = []; @@ -59,6 +63,22 @@ export const AddMaterializedViewPanel = (props: AddMaterializedViewPanelProps): setSourceContainerOptions(sourceContainerOptions); }, []); + let materializedViewThroughput: number; + let isMaterializedViewAutoscale: boolean; + let isCostAcknowledged: boolean; + + const materializedViewThroughputOnChange = (materializedViewThroughputValue: number): void => { + materializedViewThroughput = materializedViewThroughputValue; + }; + + const isMaterializedViewAutoscaleOnChange = (isMaterializedViewAutoscaleValue: boolean): void => { + isMaterializedViewAutoscale = isMaterializedViewAutoscaleValue; + }; + + const isCostAknowledgedOnChange = (isCostAcknowledgedValue: boolean): void => { + isCostAcknowledged = isCostAcknowledgedValue; + }; + return (
@@ -129,8 +149,21 @@ export const AddMaterializedViewPanel = (props: AddMaterializedViewPanelProps): value={materializedViewDefinition} onChange={(event: React.ChangeEvent) => setMaterializedViewDefinition(event.target.value)} /> - - + + +