Added index refresh to SQL API indexing policy editor (#306)
* Index refresh component introduced - Made all notifications in Mongo Index editor have 12 font size - Added indexing policy refresh to sql indexing policy editor - Added "you have unsaved changes" message, replace old message for lazy indexing policy changes * formatting changes * addressed PR comments
This commit is contained in:
parent
473f722dcc
commit
e6ca1d25c9
|
@ -0,0 +1,28 @@
|
|||
import { client } from "../CosmosClient";
|
||||
import { handleError } from "../ErrorHandlingUtils";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import * as Constants from "../Constants";
|
||||
import { AuthType } from "../../AuthType";
|
||||
|
||||
export async function getIndexTransformationProgress(databaseId: string, collectionId: string): Promise<number> {
|
||||
if (window.authType !== AuthType.AAD) {
|
||||
return undefined;
|
||||
}
|
||||
let indexTransformationPercentage: number;
|
||||
const clearMessage = logConsoleProgress(`Reading container ${collectionId}`);
|
||||
try {
|
||||
const response = await client()
|
||||
.database(databaseId)
|
||||
.container(collectionId)
|
||||
.read({ populateQuotaInfo: true });
|
||||
|
||||
indexTransformationPercentage = parseInt(
|
||||
response.headers[Constants.HttpHeaders.collectionIndexTransformationProgress] as string
|
||||
);
|
||||
} catch (error) {
|
||||
handleError(error, `Error while reading container ${collectionId}`, "ReadMongoDBCollection");
|
||||
throw error;
|
||||
}
|
||||
clearMessage();
|
||||
return indexTransformationPercentage;
|
||||
}
|
|
@ -2,8 +2,6 @@ import { userContext } from "../../UserContext";
|
|||
import { getMongoDBCollection } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
|
||||
import { MongoDBCollectionResource } from "../../Utils/arm/generatedClients/2020-04-01/types";
|
||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||
import * as Constants from "../Constants";
|
||||
import { client } from "../CosmosClient";
|
||||
import { handleError } from "../ErrorHandlingUtils";
|
||||
import { AuthType } from "../../AuthType";
|
||||
|
||||
|
@ -30,29 +28,3 @@ export async function readMongoDBCollectionThroughRP(
|
|||
clearMessage();
|
||||
return collection;
|
||||
}
|
||||
|
||||
export async function getMongoDBCollectionIndexTransformationProgress(
|
||||
databaseId: string,
|
||||
collectionId: string
|
||||
): Promise<number> {
|
||||
if (window.authType !== AuthType.AAD) {
|
||||
return undefined;
|
||||
}
|
||||
let indexTransformationPercentage: number;
|
||||
const clearMessage = logConsoleProgress(`Reading container ${collectionId}`);
|
||||
try {
|
||||
const response = await client()
|
||||
.database(databaseId)
|
||||
.container(collectionId)
|
||||
.read({ populateQuotaInfo: true });
|
||||
|
||||
indexTransformationPercentage = parseInt(
|
||||
response.headers[Constants.HttpHeaders.collectionIndexTransformationProgress] as string
|
||||
);
|
||||
} catch (error) {
|
||||
handleError(error, `Error while reading container ${collectionId}`, "ReadMongoDBCollection");
|
||||
throw error;
|
||||
}
|
||||
clearMessage();
|
||||
return indexTransformationPercentage;
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ import * as DataModels from "../../../Contracts/DataModels";
|
|||
import ko from "knockout";
|
||||
import { TtlType, isDirty } from "./SettingsUtils";
|
||||
import Explorer from "../../Explorer";
|
||||
jest.mock("../../../Common/dataAccess/readMongoDBCollection", () => ({
|
||||
getMongoDBCollectionIndexTransformationProgress: jest.fn().mockReturnValue(undefined)
|
||||
jest.mock("../../../Common/dataAccess/getIndexTransformationProgress", () => ({
|
||||
getIndexTransformationProgress: jest.fn().mockReturnValue(undefined)
|
||||
}));
|
||||
import { updateCollection, updateMongoDBCollectionThroughRP } from "../../../Common/dataAccess/updateCollection";
|
||||
jest.mock("../../../Common/dataAccess/updateCollection", () => ({
|
||||
|
|
|
@ -46,10 +46,8 @@ import { Pivot, PivotItem, IPivotProps, IPivotItemProps } from "office-ui-fabric
|
|||
import "./SettingsComponent.less";
|
||||
import { IndexingPolicyComponent, IndexingPolicyComponentProps } from "./SettingsSubComponents/IndexingPolicyComponent";
|
||||
import { MongoDBCollectionResource, MongoIndex } from "../../../Utils/arm/generatedClients/2020-04-01/types";
|
||||
import {
|
||||
getMongoDBCollectionIndexTransformationProgress,
|
||||
readMongoDBCollectionThroughRP
|
||||
} from "../../../Common/dataAccess/readMongoDBCollection";
|
||||
import { readMongoDBCollectionThroughRP } from "../../../Common/dataAccess/readMongoDBCollection";
|
||||
import { getIndexTransformationProgress } from "../../../Common/dataAccess/getIndexTransformationProgress";
|
||||
import { getErrorMessage } from "../../../Common/ErrorHandlingUtils";
|
||||
|
||||
interface SettingsV2TabInfo {
|
||||
|
@ -212,6 +210,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
|||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
this.refreshIndexTransformationProgress();
|
||||
this.loadMongoIndexes();
|
||||
this.setAutoPilotStates();
|
||||
this.setBaseline();
|
||||
|
@ -233,8 +232,6 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
|||
this.container.isEnableMongoCapabilityPresent() &&
|
||||
this.container.databaseAccount()
|
||||
) {
|
||||
await this.refreshIndexTransformationProgress();
|
||||
|
||||
this.mongoDBCollectionResource = await readMongoDBCollectionThroughRP(
|
||||
this.collection.databaseId,
|
||||
this.collection.id()
|
||||
|
@ -249,10 +246,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
|||
};
|
||||
|
||||
public refreshIndexTransformationProgress = async (): Promise<void> => {
|
||||
const currentProgress = await getMongoDBCollectionIndexTransformationProgress(
|
||||
this.collection.databaseId,
|
||||
this.collection.id()
|
||||
);
|
||||
const currentProgress = await getIndexTransformationProgress(this.collection.databaseId, this.collection.id());
|
||||
this.setState({ indexTransformationProgress: currentProgress });
|
||||
};
|
||||
|
||||
|
@ -352,6 +346,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
|||
break;
|
||||
}
|
||||
|
||||
const wasIndexingPolicyModified = this.state.isIndexingPolicyDirty;
|
||||
newCollection.defaultTtl = defaultTtl;
|
||||
|
||||
newCollection.indexingPolicy = this.state.indexingPolicyContent;
|
||||
|
@ -387,6 +382,11 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
|||
this.collection.conflictResolutionPolicy(updatedCollection.conflictResolutionPolicy);
|
||||
this.collection.changeFeedPolicy(updatedCollection.changeFeedPolicy);
|
||||
this.collection.geospatialConfig(updatedCollection.geospatialConfig);
|
||||
|
||||
if (wasIndexingPolicyModified) {
|
||||
await this.refreshIndexTransformationProgress();
|
||||
}
|
||||
|
||||
this.setState({
|
||||
isSubSettingsSaveable: false,
|
||||
isSubSettingsDiscardable: false,
|
||||
|
@ -946,6 +946,8 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
|||
indexingPolicyContentBaseline: this.state.indexingPolicyContentBaseline,
|
||||
onIndexingPolicyContentChange: this.onIndexingPolicyContentChange,
|
||||
logIndexingPolicySuccessMessage: this.logIndexingPolicySuccessMessage,
|
||||
indexTransformationProgress: this.state.indexTransformationProgress,
|
||||
refreshIndexTransformationProgress: this.refreshIndexTransformationProgress,
|
||||
onIndexingPolicyDirtyChange: this.onIndexingPolicyDirtyChange
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
getEstimatedAutoscaleSpendElement,
|
||||
manualToAutoscaleDisclaimerElement,
|
||||
ttlWarning,
|
||||
indexingPolicyTTLWarningMessage,
|
||||
indexingPolicynUnsavedWarningMessage,
|
||||
updateThroughputBeyondLimitWarningMessage,
|
||||
updateThroughputDelayedApplyWarningMessage,
|
||||
getThroughputApplyDelayedMessage,
|
||||
|
@ -37,7 +37,7 @@ class SettingsRenderUtilsTestComponent extends React.Component {
|
|||
|
||||
{manualToAutoscaleDisclaimerElement}
|
||||
{ttlWarning}
|
||||
{indexingPolicyTTLWarningMessage}
|
||||
{indexingPolicynUnsavedWarningMessage}
|
||||
{updateThroughputBeyondLimitWarningMessage}
|
||||
{updateThroughputDelayedApplyWarningMessage}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ import {
|
|||
} from "office-ui-fabric-react";
|
||||
import { isDirtyTypes, isDirty } from "./SettingsUtils";
|
||||
|
||||
const infoAndToolTipTextStyle: ITextStyles = { root: { fontSize: 12 } };
|
||||
export const infoAndToolTipTextStyle: ITextStyles = { root: { fontSize: 12 } };
|
||||
|
||||
export const noLeftPaddingCheckBoxStyle: ICheckboxStyles = {
|
||||
label: {
|
||||
|
@ -245,15 +245,9 @@ export const ttlWarning: JSX.Element = (
|
|||
</Text>
|
||||
);
|
||||
|
||||
export const indexingPolicyTTLWarningMessage: JSX.Element = (
|
||||
export const indexingPolicynUnsavedWarningMessage: JSX.Element = (
|
||||
<Text styles={infoAndToolTipTextStyle}>
|
||||
Changing the Indexing Policy impacts query results while the index transformation occurs. When a change is made and
|
||||
the indexing mode is set to consistent or lazy, queries return eventual results until the operation completes. For
|
||||
more information see,{" "}
|
||||
<Link target="_blank" href="https://aka.ms/cosmosdb/modify-index-policy">
|
||||
Modifying Indexing Policies
|
||||
</Link>
|
||||
.
|
||||
You have not saved the latest changes made to your indexing policy. Please click save to confirm the changes.
|
||||
</Text>
|
||||
);
|
||||
|
||||
|
@ -410,8 +404,8 @@ export const mongoIndexingPolicyAADError: JSX.Element = (
|
|||
|
||||
export const mongoIndexTransformationRefreshingMessage: JSX.Element = (
|
||||
<Stack horizontal {...mongoWarningStackProps}>
|
||||
<Text>Refreshing index transformation progress</Text>
|
||||
<Spinner size={SpinnerSize.medium} />
|
||||
<Text styles={infoAndToolTipTextStyle}>Refreshing index transformation progress</Text>
|
||||
<Spinner size={SpinnerSize.small} />
|
||||
</Stack>
|
||||
);
|
||||
|
||||
|
@ -421,14 +415,14 @@ export const renderMongoIndexTransformationRefreshMessage = (
|
|||
): JSX.Element => {
|
||||
if (progress === 0) {
|
||||
return (
|
||||
<Text>
|
||||
<Text styles={infoAndToolTipTextStyle}>
|
||||
{"You can make more indexing changes once the current index transformation is complete. "}
|
||||
<Link onClick={performRefresh}>{"Refresh to check if it has completed."}</Link>
|
||||
</Text>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Text>
|
||||
<Text styles={infoAndToolTipTextStyle}>
|
||||
{`You can make more indexing changes once the current index transformation has completed. It is ${progress}% complete. `}
|
||||
<Link onClick={performRefresh}>{"Refresh to check the progress."}</Link>
|
||||
</Text>
|
||||
|
|
|
@ -25,7 +25,9 @@ describe("IndexingPolicyComponent", () => {
|
|||
},
|
||||
onIndexingPolicyDirtyChange: () => {
|
||||
return;
|
||||
}
|
||||
},
|
||||
indexTransformationProgress: undefined,
|
||||
refreshIndexTransformationProgress: () => new Promise(jest.fn())
|
||||
};
|
||||
|
||||
it("renders", () => {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import * as React from "react";
|
||||
import * as DataModels from "../../../../Contracts/DataModels";
|
||||
import * as monaco from "monaco-editor";
|
||||
import { isDirty } from "../SettingsUtils";
|
||||
import { isDirty, isIndexTransforming } from "../SettingsUtils";
|
||||
import { MessageBar, MessageBarType, Stack } from "office-ui-fabric-react";
|
||||
import { indexingPolicyTTLWarningMessage, titleAndInputStackProps } from "../SettingsRenderUtils";
|
||||
import { indexingPolicynUnsavedWarningMessage, titleAndInputStackProps } from "../SettingsRenderUtils";
|
||||
import { IndexingPolicyRefreshComponent } from "./IndexingPolicyRefresh/IndexingPolicyRefreshComponent";
|
||||
|
||||
export interface IndexingPolicyComponentProps {
|
||||
shouldDiscardIndexingPolicy: boolean;
|
||||
|
@ -12,6 +13,8 @@ export interface IndexingPolicyComponentProps {
|
|||
indexingPolicyContentBaseline: DataModels.IndexingPolicy;
|
||||
onIndexingPolicyContentChange: (newIndexingPolicy: DataModels.IndexingPolicy) => void;
|
||||
logIndexingPolicySuccessMessage: () => void;
|
||||
indexTransformationProgress: number;
|
||||
refreshIndexTransformationProgress: () => Promise<void>;
|
||||
onIndexingPolicyDirtyChange: (isIndexingPolicyDirty: boolean) => void;
|
||||
}
|
||||
|
||||
|
@ -51,6 +54,9 @@ export class IndexingPolicyComponent extends React.Component<
|
|||
if (!this.indexingPolicyEditor) {
|
||||
this.createIndexingPolicyEditor();
|
||||
} else {
|
||||
this.indexingPolicyEditor.updateOptions({
|
||||
readOnly: isIndexTransforming(this.props.indexTransformationProgress)
|
||||
});
|
||||
const indexingPolicyEditorModel = this.indexingPolicyEditor.getModel();
|
||||
const value: string = JSON.stringify(this.props.indexingPolicyContent, undefined, 4);
|
||||
indexingPolicyEditorModel.setValue(value);
|
||||
|
@ -84,7 +90,7 @@ export class IndexingPolicyComponent extends React.Component<
|
|||
this.indexingPolicyEditor = monaco.editor.create(this.indexingPolicyDiv.current, {
|
||||
value: value,
|
||||
language: "json",
|
||||
readOnly: false,
|
||||
readOnly: isIndexTransforming(this.props.indexTransformationProgress),
|
||||
ariaLabel: "Indexing Policy"
|
||||
});
|
||||
if (this.indexingPolicyEditor) {
|
||||
|
@ -108,8 +114,12 @@ export class IndexingPolicyComponent extends React.Component<
|
|||
public render(): JSX.Element {
|
||||
return (
|
||||
<Stack {...titleAndInputStackProps}>
|
||||
<IndexingPolicyRefreshComponent
|
||||
indexTransformationProgress={this.props.indexTransformationProgress}
|
||||
refreshIndexTransformationProgress={this.props.refreshIndexTransformationProgress}
|
||||
/>
|
||||
{isDirty(this.props.indexingPolicyContent, this.props.indexingPolicyContentBaseline) && (
|
||||
<MessageBar messageBarType={MessageBarType.warning}>{indexingPolicyTTLWarningMessage}</MessageBar>
|
||||
<MessageBar messageBarType={MessageBarType.warning}>{indexingPolicynUnsavedWarningMessage}</MessageBar>
|
||||
)}
|
||||
<div className="settingsV2IndexingPolicyEditor" tabIndex={0} ref={this.indexingPolicyDiv}></div>
|
||||
</Stack>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
import { IndexingPolicyRefreshComponentProps, IndexingPolicyRefreshComponent } from "./IndexingPolicyRefreshComponent";
|
||||
|
||||
describe("IndexingPolicyRefreshComponent", () => {
|
||||
it("renders", () => {
|
||||
const props: IndexingPolicyRefreshComponentProps = {
|
||||
indexTransformationProgress: 90,
|
||||
refreshIndexTransformationProgress: () => new Promise(jest.fn())
|
||||
};
|
||||
|
||||
const wrapper = shallow(<IndexingPolicyRefreshComponent {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,62 @@
|
|||
import * as React from "react";
|
||||
import { MessageBar, MessageBarType } from "office-ui-fabric-react";
|
||||
import {
|
||||
mongoIndexTransformationRefreshingMessage,
|
||||
renderMongoIndexTransformationRefreshMessage
|
||||
} from "../../SettingsRenderUtils";
|
||||
import { handleError } from "../../../../../Common/ErrorHandlingUtils";
|
||||
import { isIndexTransforming } from "../../SettingsUtils";
|
||||
|
||||
export interface IndexingPolicyRefreshComponentProps {
|
||||
indexTransformationProgress: number;
|
||||
refreshIndexTransformationProgress: () => Promise<void>;
|
||||
}
|
||||
|
||||
interface IndexingPolicyRefreshComponentState {
|
||||
isRefreshing: boolean;
|
||||
}
|
||||
|
||||
export class IndexingPolicyRefreshComponent extends React.Component<
|
||||
IndexingPolicyRefreshComponentProps,
|
||||
IndexingPolicyRefreshComponentState
|
||||
> {
|
||||
constructor(props: IndexingPolicyRefreshComponentProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isRefreshing: false
|
||||
};
|
||||
}
|
||||
|
||||
private onClickRefreshIndexingTransformationLink = async () => await this.refreshIndexTransformationProgress();
|
||||
|
||||
private renderIndexTransformationWarning = (): JSX.Element => {
|
||||
if (this.state.isRefreshing) {
|
||||
return mongoIndexTransformationRefreshingMessage;
|
||||
} else if (isIndexTransforming(this.props.indexTransformationProgress)) {
|
||||
return renderMongoIndexTransformationRefreshMessage(
|
||||
this.props.indexTransformationProgress,
|
||||
this.onClickRefreshIndexingTransformationLink
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
private refreshIndexTransformationProgress = async () => {
|
||||
this.setState({ isRefreshing: true });
|
||||
try {
|
||||
await this.props.refreshIndexTransformationProgress();
|
||||
} catch (error) {
|
||||
handleError(error, "Refreshing index transformation progress failed.", "RefreshIndexTransformationProgress");
|
||||
} finally {
|
||||
this.setState({ isRefreshing: false });
|
||||
}
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
return this.renderIndexTransformationWarning() ? (
|
||||
<MessageBar messageBarType={MessageBarType.warning}>{this.renderIndexTransformationWarning()}</MessageBar>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`IndexingPolicyRefreshComponent renders 1`] = `
|
||||
<StyledMessageBarBase
|
||||
messageBarType={5}
|
||||
>
|
||||
<Text
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
You can make more indexing changes once the current index transformation has completed. It is 90% complete.
|
||||
<StyledLinkBase
|
||||
onClick={[Function]}
|
||||
>
|
||||
Refresh to check the progress.
|
||||
</StyledLinkBase>
|
||||
</Text>
|
||||
</StyledMessageBarBase>
|
||||
`;
|
|
@ -2,6 +2,7 @@ import { shallow } from "enzyme";
|
|||
import React from "react";
|
||||
import { MongoIndexTypes, MongoNotificationMessage, MongoNotificationType } from "../../SettingsUtils";
|
||||
import { MongoIndexingPolicyComponent, MongoIndexingPolicyComponentProps } from "./MongoIndexingPolicyComponent";
|
||||
import { renderToString } from "react-dom/server";
|
||||
|
||||
describe("MongoIndexingPolicyComponent", () => {
|
||||
const baseProps: MongoIndexingPolicyComponentProps = {
|
||||
|
@ -21,10 +22,7 @@ describe("MongoIndexingPolicyComponent", () => {
|
|||
return;
|
||||
},
|
||||
indexTransformationProgress: undefined,
|
||||
refreshIndexTransformationProgress: () =>
|
||||
new Promise(() => {
|
||||
return;
|
||||
}),
|
||||
refreshIndexTransformationProgress: () => new Promise(jest.fn()),
|
||||
onMongoIndexingPolicySaveableChange: () => {
|
||||
return;
|
||||
},
|
||||
|
@ -38,16 +36,6 @@ describe("MongoIndexingPolicyComponent", () => {
|
|||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("isIndexingTransforming", () => {
|
||||
const wrapper = shallow(<MongoIndexingPolicyComponent {...baseProps} />);
|
||||
const mongoIndexingPolicyComponent = wrapper.instance() as MongoIndexingPolicyComponent;
|
||||
expect(mongoIndexingPolicyComponent.isIndexingTransforming()).toEqual(false);
|
||||
wrapper.setProps({ indexTransformationProgress: 50 });
|
||||
expect(mongoIndexingPolicyComponent.isIndexingTransforming()).toEqual(true);
|
||||
wrapper.setProps({ indexTransformationProgress: 100 });
|
||||
expect(mongoIndexingPolicyComponent.isIndexingTransforming()).toEqual(false);
|
||||
});
|
||||
|
||||
describe("AddMongoIndexProps test", () => {
|
||||
const wrapper = shallow(<MongoIndexingPolicyComponent {...baseProps} />);
|
||||
const mongoIndexingPolicyComponent = wrapper.instance() as MongoIndexingPolicyComponent;
|
||||
|
@ -55,7 +43,7 @@ describe("MongoIndexingPolicyComponent", () => {
|
|||
it("defaults", () => {
|
||||
expect(mongoIndexingPolicyComponent.isMongoIndexingPolicySaveable()).toEqual(false);
|
||||
expect(mongoIndexingPolicyComponent.isMongoIndexingPolicyDiscardable()).toEqual(false);
|
||||
expect(mongoIndexingPolicyComponent.getMongoWarningNotificationMessage()).toEqual(undefined);
|
||||
expect(mongoIndexingPolicyComponent.getMongoWarningNotificationMessage()).toBeUndefined();
|
||||
});
|
||||
|
||||
const sampleWarning = "sampleWarning";
|
||||
|
@ -113,9 +101,12 @@ describe("MongoIndexingPolicyComponent", () => {
|
|||
expect(mongoIndexingPolicyComponent.isMongoIndexingPolicyDiscardable()).toEqual(
|
||||
isMongoIndexingPolicyDiscardable
|
||||
);
|
||||
expect(mongoIndexingPolicyComponent.getMongoWarningNotificationMessage()).toEqual(
|
||||
mongoWarningNotificationMessage
|
||||
);
|
||||
if (mongoWarningNotificationMessage) {
|
||||
const elementAsString = renderToString(mongoIndexingPolicyComponent.getMongoWarningNotificationMessage());
|
||||
expect(elementAsString).toContain(mongoWarningNotificationMessage);
|
||||
} else {
|
||||
expect(mongoIndexingPolicyComponent.getMongoWarningNotificationMessage()).toBeUndefined();
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -25,8 +25,8 @@ import {
|
|||
createAndAddMongoIndexStackProps,
|
||||
separatorStyles,
|
||||
mongoIndexingPolicyAADError,
|
||||
mongoIndexTransformationRefreshingMessage,
|
||||
renderMongoIndexTransformationRefreshMessage
|
||||
indexingPolicynUnsavedWarningMessage,
|
||||
infoAndToolTipTextStyle
|
||||
} from "../../SettingsRenderUtils";
|
||||
import { MongoIndex } from "../../../../../Utils/arm/generatedClients/2020-04-01/types";
|
||||
import {
|
||||
|
@ -35,12 +35,13 @@ import {
|
|||
MongoIndexIdField,
|
||||
MongoNotificationType,
|
||||
getMongoIndexType,
|
||||
getMongoIndexTypeText
|
||||
getMongoIndexTypeText,
|
||||
isIndexTransforming
|
||||
} from "../../SettingsUtils";
|
||||
import { AddMongoIndexComponent } from "./AddMongoIndexComponent";
|
||||
import { CollapsibleSectionComponent } from "../../../CollapsiblePanel/CollapsibleSectionComponent";
|
||||
import { handleError } from "../../../../../Common/ErrorHandlingUtils";
|
||||
import { AuthType } from "../../../../../AuthType";
|
||||
import { IndexingPolicyRefreshComponent } from "../IndexingPolicyRefresh/IndexingPolicyRefreshComponent";
|
||||
|
||||
export interface MongoIndexingPolicyComponentProps {
|
||||
mongoIndexes: MongoIndex[];
|
||||
|
@ -56,20 +57,13 @@ export interface MongoIndexingPolicyComponentProps {
|
|||
onMongoIndexingPolicyDiscardableChange: (isMongoIndexingPolicyDiscardable: boolean) => void;
|
||||
}
|
||||
|
||||
interface MongoIndexingPolicyComponentState {
|
||||
isRefreshingIndexTransformationProgress: boolean;
|
||||
}
|
||||
|
||||
interface MongoIndexDisplayProps {
|
||||
definition: JSX.Element;
|
||||
type: JSX.Element;
|
||||
actionButton: JSX.Element;
|
||||
}
|
||||
|
||||
export class MongoIndexingPolicyComponent extends React.Component<
|
||||
MongoIndexingPolicyComponentProps,
|
||||
MongoIndexingPolicyComponentState
|
||||
> {
|
||||
export class MongoIndexingPolicyComponent extends React.Component<MongoIndexingPolicyComponentProps> {
|
||||
private shouldCheckComponentIsDirty = true;
|
||||
private addMongoIndexComponentRefs: React.RefObject<AddMongoIndexComponent>[] = [];
|
||||
private initialIndexesColumns: IColumn[] = [
|
||||
|
@ -98,13 +92,6 @@ export class MongoIndexingPolicyComponent extends React.Component<
|
|||
}
|
||||
];
|
||||
|
||||
constructor(props: MongoIndexingPolicyComponentProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isRefreshingIndexTransformationProgress: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: MongoIndexingPolicyComponentProps): void {
|
||||
if (this.props.indexesToAdd.length > prevProps.indexesToAdd.length) {
|
||||
this.addMongoIndexComponentRefs[prevProps.indexesToAdd.length]?.current?.focus();
|
||||
|
@ -144,10 +131,15 @@ export class MongoIndexingPolicyComponent extends React.Component<
|
|||
return this.props.indexesToAdd.length > 0 || this.props.indexesToDrop.length > 0;
|
||||
};
|
||||
|
||||
public getMongoWarningNotificationMessage = (): string => {
|
||||
return this.props.indexesToAdd.find(
|
||||
public getMongoWarningNotificationMessage = (): JSX.Element => {
|
||||
const warningMessage = this.props.indexesToAdd.find(
|
||||
addMongoIndexProps => addMongoIndexProps.notification?.type === MongoNotificationType.Warning
|
||||
)?.notification.message;
|
||||
|
||||
if (warningMessage) {
|
||||
return <Text styles={infoAndToolTipTextStyle}>{warningMessage}</Text>;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
private onRenderRow = (props: IDetailsRowProps): JSX.Element => {
|
||||
|
@ -159,7 +151,7 @@ export class MongoIndexingPolicyComponent extends React.Component<
|
|||
<IconButton
|
||||
ariaLabel="Delete index Button"
|
||||
iconProps={{ iconName: "Delete" }}
|
||||
disabled={this.isIndexingTransforming()}
|
||||
disabled={isIndexTransforming(this.props.indexTransformationProgress)}
|
||||
onClick={() => {
|
||||
this.props.onIndexDrop(arrayPosition);
|
||||
}}
|
||||
|
@ -230,7 +222,7 @@ export class MongoIndexingPolicyComponent extends React.Component<
|
|||
|
||||
<AddMongoIndexComponent
|
||||
ref={this.addMongoIndexComponentRefs[indexesToAddLength]}
|
||||
disabled={this.isIndexingTransforming()}
|
||||
disabled={isIndexTransforming(this.props.indexTransformationProgress)}
|
||||
position={indexesToAddLength}
|
||||
key={indexesToAddLength}
|
||||
description={undefined}
|
||||
|
@ -298,55 +290,21 @@ export class MongoIndexingPolicyComponent extends React.Component<
|
|||
);
|
||||
};
|
||||
|
||||
private refreshIndexTransformationProgress = async () => {
|
||||
this.setState({ isRefreshingIndexTransformationProgress: true });
|
||||
try {
|
||||
await this.props.refreshIndexTransformationProgress();
|
||||
} catch (error) {
|
||||
handleError(error, "Refreshing index transformation progress failed.", "RefreshIndexTransformationProgress");
|
||||
} finally {
|
||||
this.setState({ isRefreshingIndexTransformationProgress: false });
|
||||
}
|
||||
};
|
||||
|
||||
public isIndexingTransforming = (): boolean =>
|
||||
// index transformation progress can be 0
|
||||
this.props.indexTransformationProgress !== undefined && this.props.indexTransformationProgress !== 100;
|
||||
|
||||
private onClickRefreshIndexingTransformationLink = async () => await this.refreshIndexTransformationProgress();
|
||||
|
||||
private renderIndexTransformationWarning = (): JSX.Element => {
|
||||
if (this.state.isRefreshingIndexTransformationProgress) {
|
||||
return mongoIndexTransformationRefreshingMessage;
|
||||
} else if (this.isIndexingTransforming()) {
|
||||
return renderMongoIndexTransformationRefreshMessage(
|
||||
this.props.indexTransformationProgress,
|
||||
this.onClickRefreshIndexingTransformationLink
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
private renderWarningMessage = (): JSX.Element => {
|
||||
let warningMessage: string;
|
||||
let warningMessage: JSX.Element;
|
||||
if (this.getMongoWarningNotificationMessage()) {
|
||||
warningMessage = this.getMongoWarningNotificationMessage();
|
||||
} else if (this.isMongoIndexingPolicySaveable()) {
|
||||
warningMessage =
|
||||
"You have not saved the latest changes made to your indexing policy. Please click save to confirm the changes.";
|
||||
warningMessage = indexingPolicynUnsavedWarningMessage;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{this.renderIndexTransformationWarning() && (
|
||||
<MessageBar messageBarType={MessageBarType.warning}>{this.renderIndexTransformationWarning()}</MessageBar>
|
||||
)}
|
||||
|
||||
{warningMessage && (
|
||||
<MessageBar messageBarType={MessageBarType.warning}>
|
||||
<Text>{warningMessage}</Text>
|
||||
</MessageBar>
|
||||
)}
|
||||
<IndexingPolicyRefreshComponent
|
||||
indexTransformationProgress={this.props.indexTransformationProgress}
|
||||
refreshIndexTransformationProgress={this.props.refreshIndexTransformationProgress}
|
||||
/>
|
||||
{warningMessage && <MessageBar messageBarType={MessageBarType.warning}>{warningMessage}</MessageBar>}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -8,6 +8,9 @@ exports[`MongoIndexingPolicyComponent renders 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<IndexingPolicyRefreshComponent
|
||||
refreshIndexTransformationProgress={[Function]}
|
||||
/>
|
||||
<Text>
|
||||
For queries that filter on multiple properties, create multiple single field indexes instead of a compound index.
|
||||
<StyledLinkBase
|
||||
|
|
|
@ -8,6 +8,9 @@ exports[`IndexingPolicyComponent renders 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<IndexingPolicyRefreshComponent
|
||||
refreshIndexTransformationProgress={[Function]}
|
||||
/>
|
||||
<div
|
||||
className="settingsV2IndexingPolicyEditor"
|
||||
tabIndex={0}
|
||||
|
|
|
@ -15,7 +15,8 @@ import {
|
|||
MongoWildcardPlaceHolder,
|
||||
getMongoIndexTypeText,
|
||||
SingleFieldText,
|
||||
WildcardText
|
||||
WildcardText,
|
||||
isIndexTransforming
|
||||
} from "./SettingsUtils";
|
||||
import * as DataModels from "../../../Contracts/DataModels";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
|
@ -139,3 +140,10 @@ describe("SettingsUtils", () => {
|
|||
expect(notification.type).toEqual(MongoNotificationType.Error);
|
||||
});
|
||||
});
|
||||
|
||||
it("isIndexingTransforming", () => {
|
||||
expect(isIndexTransforming(undefined)).toBeFalsy();
|
||||
expect(isIndexTransforming(0)).toBeTruthy();
|
||||
expect(isIndexTransforming(90)).toBeTruthy();
|
||||
expect(isIndexTransforming(100)).toBeFalsy();
|
||||
});
|
||||
|
|
|
@ -250,3 +250,7 @@ export const getMongoIndexTypeText = (index: MongoIndexTypes): string => {
|
|||
}
|
||||
return WildcardText;
|
||||
};
|
||||
|
||||
export const isIndexTransforming = (indexTransformationProgress: number): boolean =>
|
||||
// index transformation progress can be 0
|
||||
indexTransformationProgress !== undefined && indexTransformationProgress !== 100;
|
||||
|
|
|
@ -5189,6 +5189,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
logIndexingPolicySuccessMessage={[Function]}
|
||||
onIndexingPolicyContentChange={[Function]}
|
||||
onIndexingPolicyDirtyChange={[Function]}
|
||||
refreshIndexTransformationProgress={[Function]}
|
||||
resetShouldDiscardIndexingPolicy={[Function]}
|
||||
shouldDiscardIndexingPolicy={false}
|
||||
/>
|
||||
|
|
|
@ -166,15 +166,7 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
Changing the Indexing Policy impacts query results while the index transformation occurs. When a change is made and the indexing mode is set to consistent or lazy, queries return eventual results until the operation completes. For more information see,
|
||||
|
||||
<StyledLinkBase
|
||||
href="https://aka.ms/cosmosdb/modify-index-policy"
|
||||
target="_blank"
|
||||
>
|
||||
Modifying Indexing Policies
|
||||
</StyledLinkBase>
|
||||
.
|
||||
You have not saved the latest changes made to your indexing policy. Please click save to confirm the changes.
|
||||
</Text>
|
||||
<Text
|
||||
id="updateThroughputBeyondLimitWarningMessage"
|
||||
|
@ -341,14 +333,30 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
}
|
||||
}
|
||||
>
|
||||
<Text>
|
||||
<Text
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
Refreshing index transformation progress
|
||||
</Text>
|
||||
<StyledSpinnerBase
|
||||
size={2}
|
||||
size={1}
|
||||
/>
|
||||
</Stack>
|
||||
<Text>
|
||||
<Text
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
You can make more indexing changes once the current index transformation is complete.
|
||||
<StyledLinkBase
|
||||
onClick={[Function]}
|
||||
|
@ -356,7 +364,15 @@ exports[`SettingsUtils functions render 1`] = `
|
|||
Refresh to check if it has completed.
|
||||
</StyledLinkBase>
|
||||
</Text>
|
||||
<Text>
|
||||
<Text
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"fontSize": 12,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
You can make more indexing changes once the current index transformation has completed. It is 90% complete.
|
||||
<StyledLinkBase
|
||||
onClick={[Function]}
|
||||
|
|
Loading…
Reference in New Issue