mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-19 17:01:13 +00:00
Added Support for editing Mongo Indexing Policy from Settings tab (#284)
* added SettingsV2 Tab * lint changes * foxed failing test * Addressed PR comments - removed dangerouslySetInnerHtml - removed underscore dependency - added AccessibleElement - removed unnecesary exceptions to linting * split render into separate functions - removed sinon in test - Added some enums to replace constant strings - removed dangerously set inner html - made autopilot input as StatefulValue * add settingscomponent snapshot * fixed linting errors * fixed errors * addressed PR comments - Moved StatefulValue to new class - Split render to more functions for throughputInputComponents * Added sub components - Added tests for SettingsRenderUtls - Added empty test files for adding tests later * Moved all inputs to fluent UI - removed rupm - added reusable styles * Added Tabs - Added ToolTipLabel component - Removed toggleables for individual components - Removed accessible elements - Added IndexingPolicyComponent * Added more tests * Addressed PR comments * Moved Label radio buttons to choicegroup * fixed lint errors * Removed StatefulValue - Moved conflict res tab to the end - Added styling for autpilot radiobuttons * fixed linting errors * fix bugs from merge to master * fixed formatting issue * Addressed PR comments - Added unit tests for smaller methods within each component * fixed linting errors * removed redundant snapshots * removed empty line * made separate props objects for subcomponents * Moved dirty checks to sub components * Made indesing policy component height = 80% of view port - modified auto pilot v3 messages - Added Fluent UI tolltip - * Moved warning messages inline * moved conflict res helpers out * fixed bugs * added stack style for message * fixed tests * Added tests * fixed linting and format errors * undid changes * more edits * fixed compile errors * fixed compile errors * fixed errors * fixed bug with save and discard buttons * fixed compile errors * added MongoIndexingPolicy component * addressed PR comments * moved read indexes to scale context * added add index feature * added AddMongoIndexComponent * Added collapsible portions and focus changes * removed unnecessary imports * finetuned UI * more edits * Added mongoindexeditor flight - Moved add index UI to within current index pane * minro edits * Added separate warning messages for index refresh * aligned items * Fixed tests * minor edits * resolved PR comments * modified refs usage * compile errors fixed * moved fetch of notifications and offer to within the tab activation * fixed PR comments * added error handling * added AAD verification * removed l empty line * added back line * deleted file * added file * addressed PR comments * addressed PR comments * fixed format error * updated package.json * updated package-lock.json
This commit is contained in:
committed by
GitHub
parent
294270b6aa
commit
b4219e2994
@@ -0,0 +1,24 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
import { MongoIndexTypes, MongoNotificationType } from "../../SettingsUtils";
|
||||
import { AddMongoIndexComponent, AddMongoIndexComponentProps } from "./AddMongoIndexComponent";
|
||||
|
||||
describe("AddMongoIndexComponent", () => {
|
||||
it("renders", () => {
|
||||
const props: AddMongoIndexComponentProps = {
|
||||
position: 1,
|
||||
description: "sample_key",
|
||||
type: MongoIndexTypes.Single,
|
||||
notification: { type: MongoNotificationType.Error, message: "sample error" },
|
||||
onIndexAddOrChange: () => {
|
||||
return;
|
||||
},
|
||||
onDiscard: () => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const wrapper = shallow(<AddMongoIndexComponent {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
MessageBar,
|
||||
MessageBarType,
|
||||
Stack,
|
||||
IconButton,
|
||||
TextField,
|
||||
Dropdown,
|
||||
IDropdownOption,
|
||||
ITextField
|
||||
} from "office-ui-fabric-react";
|
||||
import {
|
||||
addMongoIndexSubElementsTokens,
|
||||
mongoErrorMessageStyles,
|
||||
mongoWarningStackProps,
|
||||
shortWidthDropDownStyles,
|
||||
shortWidthTextFieldStyles
|
||||
} from "../../SettingsRenderUtils";
|
||||
import {
|
||||
getMongoIndexTypeText,
|
||||
MongoIndexTypes,
|
||||
MongoNotificationMessage,
|
||||
MongoNotificationType,
|
||||
MongoWildcardPlaceHolder
|
||||
} from "../../SettingsUtils";
|
||||
|
||||
export interface AddMongoIndexComponentProps {
|
||||
position: number;
|
||||
description: string;
|
||||
type: MongoIndexTypes;
|
||||
notification: MongoNotificationMessage;
|
||||
onIndexAddOrChange: (description: string, type: MongoIndexTypes) => void;
|
||||
onDiscard: () => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export class AddMongoIndexComponent extends React.Component<AddMongoIndexComponentProps> {
|
||||
private descriptionTextField: ITextField;
|
||||
private indexTypes: IDropdownOption[] = [MongoIndexTypes.Single, MongoIndexTypes.Wildcard].map(
|
||||
(value: MongoIndexTypes) => ({
|
||||
text: getMongoIndexTypeText(value),
|
||||
key: value
|
||||
})
|
||||
);
|
||||
|
||||
private onDescriptionChange = (
|
||||
event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||
newValue?: string
|
||||
): void => {
|
||||
this.props.onIndexAddOrChange(newValue, this.props.type);
|
||||
};
|
||||
|
||||
private onTypeChange = (event: React.FormEvent<HTMLDivElement>, option?: IDropdownOption): void => {
|
||||
const newType = MongoIndexTypes[option.key as keyof typeof MongoIndexTypes];
|
||||
this.props.onIndexAddOrChange(this.props.description, newType);
|
||||
};
|
||||
|
||||
private setRef = (textField: ITextField) => (this.descriptionTextField = textField);
|
||||
|
||||
public focus = (): void => {
|
||||
this.descriptionTextField.focus();
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
return (
|
||||
<Stack {...mongoWarningStackProps}>
|
||||
<Stack horizontal tokens={addMongoIndexSubElementsTokens}>
|
||||
<TextField
|
||||
ariaLabel={"Index Field Name " + this.props.position}
|
||||
disabled={this.props.disabled}
|
||||
styles={shortWidthTextFieldStyles}
|
||||
componentRef={this.setRef}
|
||||
value={this.props.description}
|
||||
placeholder={this.props.type === MongoIndexTypes.Wildcard ? MongoWildcardPlaceHolder : undefined}
|
||||
onChange={this.onDescriptionChange}
|
||||
/>
|
||||
|
||||
<Dropdown
|
||||
ariaLabel={"Index Type " + this.props.position}
|
||||
disabled={this.props.disabled}
|
||||
styles={shortWidthDropDownStyles}
|
||||
placeholder="Select an index type"
|
||||
selectedKey={this.props.type}
|
||||
options={this.indexTypes}
|
||||
onChange={this.onTypeChange}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
ariaLabel={"Undo Button " + this.props.position}
|
||||
iconProps={{ iconName: "Undo" }}
|
||||
disabled={!this.props.description && !this.props.type}
|
||||
onClick={() => this.props.onDiscard()}
|
||||
/>
|
||||
</Stack>
|
||||
{this.props.notification?.type === MongoNotificationType.Error && (
|
||||
<MessageBar styles={mongoErrorMessageStyles} messageBarType={MessageBarType.error}>
|
||||
{this.props.notification.message}
|
||||
</MessageBar>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
import { MongoIndexTypes, MongoNotificationMessage, MongoNotificationType } from "../../SettingsUtils";
|
||||
import { MongoIndexingPolicyComponent, MongoIndexingPolicyComponentProps } from "./MongoIndexingPolicyComponent";
|
||||
|
||||
describe("MongoIndexingPolicyComponent", () => {
|
||||
const baseProps: MongoIndexingPolicyComponentProps = {
|
||||
mongoIndexes: [],
|
||||
onIndexDrop: () => {
|
||||
return;
|
||||
},
|
||||
indexesToDrop: [],
|
||||
onRevertIndexDrop: () => {
|
||||
return;
|
||||
},
|
||||
indexesToAdd: [],
|
||||
onRevertIndexAdd: () => {
|
||||
return;
|
||||
},
|
||||
onIndexAddOrChange: () => {
|
||||
return;
|
||||
},
|
||||
indexTransformationProgress: undefined,
|
||||
refreshIndexTransformationProgress: () =>
|
||||
new Promise(() => {
|
||||
return;
|
||||
}),
|
||||
onMongoIndexingPolicySaveableChange: () => {
|
||||
return;
|
||||
},
|
||||
onMongoIndexingPolicyDiscardableChange: () => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
it("renders", () => {
|
||||
const wrapper = shallow(<MongoIndexingPolicyComponent {...baseProps} />);
|
||||
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;
|
||||
|
||||
it("defaults", () => {
|
||||
expect(mongoIndexingPolicyComponent.isMongoIndexingPolicySaveable()).toEqual(false);
|
||||
expect(mongoIndexingPolicyComponent.isMongoIndexingPolicyDiscardable()).toEqual(false);
|
||||
expect(mongoIndexingPolicyComponent.getMongoWarningNotificationMessage()).toEqual(undefined);
|
||||
});
|
||||
|
||||
const sampleWarning = "sampleWarning";
|
||||
const sampleError = "sampleError";
|
||||
|
||||
const cases = [
|
||||
[
|
||||
{ type: MongoNotificationType.Warning, message: sampleWarning } as MongoNotificationMessage,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
sampleWarning
|
||||
],
|
||||
[
|
||||
{ type: MongoNotificationType.Error, message: sampleError } as MongoNotificationMessage,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
undefined
|
||||
],
|
||||
[
|
||||
{ type: MongoNotificationType.Error, message: sampleError } as MongoNotificationMessage,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
undefined
|
||||
],
|
||||
[undefined, false, true, true, undefined],
|
||||
[undefined, true, true, true, undefined]
|
||||
];
|
||||
|
||||
test.each(cases)(
|
||||
"",
|
||||
(
|
||||
notification: MongoNotificationMessage,
|
||||
indexToDropIsPresent: boolean,
|
||||
isMongoIndexingPolicySaveable: boolean,
|
||||
isMongoIndexingPolicyDiscardable: boolean,
|
||||
mongoWarningNotificationMessage: string
|
||||
) => {
|
||||
const addMongoIndexProps = {
|
||||
mongoIndex: { key: { keys: ["sampleKey"] } },
|
||||
type: MongoIndexTypes.Single,
|
||||
notification: notification
|
||||
};
|
||||
|
||||
let indexesToDrop: number[] = [];
|
||||
if (indexToDropIsPresent) {
|
||||
indexesToDrop = [0];
|
||||
}
|
||||
wrapper.setProps({ indexesToAdd: [addMongoIndexProps], indexesToDrop: indexesToDrop });
|
||||
wrapper.update();
|
||||
|
||||
expect(mongoIndexingPolicyComponent.isMongoIndexingPolicySaveable()).toEqual(isMongoIndexingPolicySaveable);
|
||||
expect(mongoIndexingPolicyComponent.isMongoIndexingPolicyDiscardable()).toEqual(
|
||||
isMongoIndexingPolicyDiscardable
|
||||
);
|
||||
expect(mongoIndexingPolicyComponent.getMongoWarningNotificationMessage()).toEqual(
|
||||
mongoWarningNotificationMessage
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,369 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
DetailsList,
|
||||
DetailsListLayoutMode,
|
||||
Stack,
|
||||
IconButton,
|
||||
Text,
|
||||
SelectionMode,
|
||||
IDetailsRowProps,
|
||||
DetailsRow,
|
||||
IColumn,
|
||||
MessageBar,
|
||||
MessageBarType,
|
||||
Spinner,
|
||||
SpinnerSize,
|
||||
Separator
|
||||
} from "office-ui-fabric-react";
|
||||
import {
|
||||
addMongoIndexStackProps,
|
||||
customDetailsListStyles,
|
||||
mongoIndexingPolicyDisclaimer,
|
||||
mediumWidthStackStyles,
|
||||
subComponentStackProps,
|
||||
transparentDetailsRowStyles,
|
||||
createAndAddMongoIndexStackProps,
|
||||
separatorStyles,
|
||||
mongoIndexingPolicyAADError,
|
||||
mongoIndexTransformationRefreshingMessage,
|
||||
renderMongoIndexTransformationRefreshMessage
|
||||
} from "../../SettingsRenderUtils";
|
||||
import { MongoIndex } from "../../../../../Utils/arm/generatedClients/2020-04-01/types";
|
||||
import {
|
||||
MongoIndexTypes,
|
||||
AddMongoIndexProps,
|
||||
MongoIndexIdField,
|
||||
MongoNotificationType,
|
||||
getMongoIndexType,
|
||||
getMongoIndexTypeText
|
||||
} from "../../SettingsUtils";
|
||||
import { AddMongoIndexComponent } from "./AddMongoIndexComponent";
|
||||
import { CollapsibleSectionComponent } from "../../../CollapsiblePanel/CollapsibleSectionComponent";
|
||||
import { handleError } from "../../../../../Common/ErrorHandlingUtils";
|
||||
import { AuthType } from "../../../../../AuthType";
|
||||
|
||||
export interface MongoIndexingPolicyComponentProps {
|
||||
mongoIndexes: MongoIndex[];
|
||||
onIndexDrop: (index: number) => void;
|
||||
indexesToDrop: number[];
|
||||
onRevertIndexDrop: (index: number) => void;
|
||||
indexesToAdd: AddMongoIndexProps[];
|
||||
onRevertIndexAdd: (index: number) => void;
|
||||
onIndexAddOrChange: (index: number, description: string, type: MongoIndexTypes) => void;
|
||||
indexTransformationProgress: number;
|
||||
refreshIndexTransformationProgress: () => Promise<void>;
|
||||
onMongoIndexingPolicySaveableChange: (isMongoIndexingPolicySaveable: boolean) => void;
|
||||
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
|
||||
> {
|
||||
private shouldCheckComponentIsDirty = true;
|
||||
private addMongoIndexComponentRefs: React.RefObject<AddMongoIndexComponent>[] = [];
|
||||
private initialIndexesColumns: IColumn[] = [
|
||||
{ key: "definition", name: "Definition", fieldName: "definition", minWidth: 100, maxWidth: 200, isResizable: true },
|
||||
{ key: "type", name: "Type", fieldName: "type", minWidth: 100, maxWidth: 200, isResizable: true },
|
||||
{
|
||||
key: "actionButton",
|
||||
name: "Drop Index",
|
||||
fieldName: "actionButton",
|
||||
minWidth: 100,
|
||||
maxWidth: 200,
|
||||
isResizable: true
|
||||
}
|
||||
];
|
||||
|
||||
private indexesToBeDroppedColumns: IColumn[] = [
|
||||
{ key: "definition", name: "Definition", fieldName: "definition", minWidth: 100, maxWidth: 200, isResizable: true },
|
||||
{ key: "type", name: "Type", fieldName: "type", minWidth: 100, maxWidth: 200, isResizable: true },
|
||||
{
|
||||
key: "actionButton",
|
||||
name: "Add index back",
|
||||
fieldName: "actionButton",
|
||||
minWidth: 100,
|
||||
maxWidth: 200,
|
||||
isResizable: true
|
||||
}
|
||||
];
|
||||
|
||||
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();
|
||||
}
|
||||
this.onComponentUpdate();
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
this.onComponentUpdate();
|
||||
}
|
||||
|
||||
private onComponentUpdate = (): void => {
|
||||
if (!this.shouldCheckComponentIsDirty) {
|
||||
this.shouldCheckComponentIsDirty = true;
|
||||
return;
|
||||
}
|
||||
this.props.onMongoIndexingPolicySaveableChange(this.isMongoIndexingPolicySaveable());
|
||||
this.props.onMongoIndexingPolicyDiscardableChange(this.isMongoIndexingPolicyDiscardable());
|
||||
this.shouldCheckComponentIsDirty = false;
|
||||
};
|
||||
|
||||
public isMongoIndexingPolicySaveable = (): boolean => {
|
||||
if (this.props.indexesToAdd.length === 0 && this.props.indexesToDrop.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const addErrorsExist = !!this.props.indexesToAdd.find(addMongoIndexProps => addMongoIndexProps.notification);
|
||||
|
||||
if (addErrorsExist) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public isMongoIndexingPolicyDiscardable = (): boolean => {
|
||||
return this.props.indexesToAdd.length > 0 || this.props.indexesToDrop.length > 0;
|
||||
};
|
||||
|
||||
public getMongoWarningNotificationMessage = (): string => {
|
||||
return this.props.indexesToAdd.find(
|
||||
addMongoIndexProps => addMongoIndexProps.notification?.type === MongoNotificationType.Warning
|
||||
)?.notification.message;
|
||||
};
|
||||
|
||||
private onRenderRow = (props: IDetailsRowProps): JSX.Element => {
|
||||
return <DetailsRow {...props} styles={transparentDetailsRowStyles} />;
|
||||
};
|
||||
|
||||
private getActionButton = (arrayPosition: number, isCurrentIndex: boolean): JSX.Element => {
|
||||
return isCurrentIndex ? (
|
||||
<IconButton
|
||||
ariaLabel="Delete index Button"
|
||||
iconProps={{ iconName: "Delete" }}
|
||||
disabled={this.isIndexingTransforming()}
|
||||
onClick={() => {
|
||||
this.props.onIndexDrop(arrayPosition);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<IconButton
|
||||
ariaLabel="Add back Index Button"
|
||||
iconProps={{ iconName: "Add" }}
|
||||
onClick={() => {
|
||||
this.props.onRevertIndexDrop(arrayPosition);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
private getMongoIndexDisplayProps = (
|
||||
mongoIndex: MongoIndex,
|
||||
arrayPosition: number,
|
||||
isCurrentIndex: boolean
|
||||
): MongoIndexDisplayProps => {
|
||||
const keys = mongoIndex?.key?.keys;
|
||||
const type = getMongoIndexType(keys);
|
||||
const definition = keys?.join();
|
||||
let mongoIndexDisplayProps: MongoIndexDisplayProps;
|
||||
if (type) {
|
||||
mongoIndexDisplayProps = {
|
||||
definition: <Text>{definition}</Text>,
|
||||
type: <Text>{getMongoIndexTypeText(type)}</Text>,
|
||||
actionButton: definition === MongoIndexIdField ? <></> : this.getActionButton(arrayPosition, isCurrentIndex)
|
||||
};
|
||||
}
|
||||
return mongoIndexDisplayProps;
|
||||
};
|
||||
|
||||
private renderIndexesToBeAdded = (): JSX.Element => {
|
||||
const indexesToAddLength = this.props.indexesToAdd.length;
|
||||
for (let i = 0; i < indexesToAddLength; i++) {
|
||||
const existingIndexToAddRef = React.createRef<AddMongoIndexComponent>();
|
||||
this.addMongoIndexComponentRefs[i] = existingIndexToAddRef;
|
||||
}
|
||||
const newIndexToAddRef = React.createRef<AddMongoIndexComponent>();
|
||||
this.addMongoIndexComponentRefs[indexesToAddLength] = newIndexToAddRef;
|
||||
|
||||
return (
|
||||
<Stack {...addMongoIndexStackProps} styles={mediumWidthStackStyles}>
|
||||
{this.props.indexesToAdd.map((mongoIndexWithType, arrayPosition) => {
|
||||
const keys = mongoIndexWithType.mongoIndex.key.keys;
|
||||
const type = mongoIndexWithType.type;
|
||||
const notification = mongoIndexWithType.notification;
|
||||
return (
|
||||
<AddMongoIndexComponent
|
||||
ref={this.addMongoIndexComponentRefs[arrayPosition]}
|
||||
position={arrayPosition}
|
||||
key={arrayPosition}
|
||||
description={keys.join()}
|
||||
type={type}
|
||||
notification={notification}
|
||||
onIndexAddOrChange={(description, type) =>
|
||||
this.props.onIndexAddOrChange(arrayPosition, description, type)
|
||||
}
|
||||
onDiscard={() => {
|
||||
this.addMongoIndexComponentRefs.splice(arrayPosition, 1);
|
||||
this.props.onRevertIndexAdd(arrayPosition);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
<AddMongoIndexComponent
|
||||
ref={this.addMongoIndexComponentRefs[indexesToAddLength]}
|
||||
disabled={this.isIndexingTransforming()}
|
||||
position={indexesToAddLength}
|
||||
key={indexesToAddLength}
|
||||
description={undefined}
|
||||
type={undefined}
|
||||
notification={undefined}
|
||||
onIndexAddOrChange={(description, type) =>
|
||||
this.props.onIndexAddOrChange(indexesToAddLength, description, type)
|
||||
}
|
||||
onDiscard={() => {
|
||||
this.props.onRevertIndexAdd(indexesToAddLength);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
private renderInitialIndexes = (): JSX.Element => {
|
||||
const initialIndexes = this.props.mongoIndexes
|
||||
.map((mongoIndex, arrayPosition) => this.getMongoIndexDisplayProps(mongoIndex, arrayPosition, true))
|
||||
.filter((value, arrayPosition) => !!value && !this.props.indexesToDrop.includes(arrayPosition));
|
||||
|
||||
return (
|
||||
<Stack {...createAndAddMongoIndexStackProps} styles={mediumWidthStackStyles}>
|
||||
<CollapsibleSectionComponent title="Current index(es)">
|
||||
{
|
||||
<>
|
||||
<DetailsList
|
||||
styles={customDetailsListStyles}
|
||||
disableSelectionZone
|
||||
items={initialIndexes}
|
||||
columns={this.initialIndexesColumns}
|
||||
selectionMode={SelectionMode.none}
|
||||
onRenderRow={this.onRenderRow}
|
||||
layoutMode={DetailsListLayoutMode.justified}
|
||||
/>
|
||||
{this.renderIndexesToBeAdded()}
|
||||
</>
|
||||
}
|
||||
</CollapsibleSectionComponent>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
private renderIndexesToBeDropped = (): JSX.Element => {
|
||||
const indexesToBeDropped = this.props.indexesToDrop.map((dropIndex, arrayPosition) =>
|
||||
this.getMongoIndexDisplayProps(this.props.mongoIndexes[dropIndex], arrayPosition, false)
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack styles={mediumWidthStackStyles}>
|
||||
<CollapsibleSectionComponent title="Index(es) to be dropped">
|
||||
{indexesToBeDropped.length > 0 && (
|
||||
<DetailsList
|
||||
styles={customDetailsListStyles}
|
||||
disableSelectionZone
|
||||
items={indexesToBeDropped}
|
||||
columns={this.indexesToBeDroppedColumns}
|
||||
selectionMode={SelectionMode.none}
|
||||
onRenderRow={this.onRenderRow}
|
||||
layoutMode={DetailsListLayoutMode.justified}
|
||||
/>
|
||||
)}
|
||||
</CollapsibleSectionComponent>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
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;
|
||||
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.";
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{this.renderIndexTransformationWarning() && (
|
||||
<MessageBar messageBarType={MessageBarType.warning}>{this.renderIndexTransformationWarning()}</MessageBar>
|
||||
)}
|
||||
|
||||
{warningMessage && (
|
||||
<MessageBar messageBarType={MessageBarType.warning}>
|
||||
<Text>{warningMessage}</Text>
|
||||
</MessageBar>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
public render(): JSX.Element {
|
||||
if (this.props.mongoIndexes) {
|
||||
return (
|
||||
<Stack {...subComponentStackProps}>
|
||||
{this.renderWarningMessage()}
|
||||
{mongoIndexingPolicyDisclaimer}
|
||||
{this.renderInitialIndexes()}
|
||||
<Separator styles={separatorStyles} />
|
||||
{this.renderIndexesToBeDropped()}
|
||||
</Stack>
|
||||
);
|
||||
} else {
|
||||
return window.authType !== AuthType.AAD ? mongoIndexingPolicyAADError : <Spinner size={SpinnerSize.large} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AddMongoIndexComponent renders 1`] = `
|
||||
<Stack
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 5,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Stack
|
||||
horizontal={true}
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 20,
|
||||
}
|
||||
}
|
||||
>
|
||||
<StyledTextFieldBase
|
||||
ariaLabel="Index Field Name 1"
|
||||
componentRef={[Function]}
|
||||
onChange={[Function]}
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"paddingLeft": 10,
|
||||
"width": 210,
|
||||
},
|
||||
}
|
||||
}
|
||||
value="sample_key"
|
||||
/>
|
||||
<StyledWithResponsiveMode
|
||||
ariaLabel="Index Type 1"
|
||||
onChange={[Function]}
|
||||
options={
|
||||
Array [
|
||||
Object {
|
||||
"key": "Single",
|
||||
"text": "Single Field",
|
||||
},
|
||||
Object {
|
||||
"key": "Wildcard",
|
||||
"text": "Wildcard",
|
||||
},
|
||||
]
|
||||
}
|
||||
placeholder="Select an index type"
|
||||
selectedKey="Single"
|
||||
styles={
|
||||
Object {
|
||||
"dropdown": Object {
|
||||
"paddingleft": 10,
|
||||
"width": 202,
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<CustomizedIconButton
|
||||
ariaLabel="Undo Button 1"
|
||||
disabled={false}
|
||||
iconProps={
|
||||
Object {
|
||||
"iconName": "Undo",
|
||||
}
|
||||
}
|
||||
onClick={[Function]}
|
||||
/>
|
||||
</Stack>
|
||||
<StyledMessageBarBase
|
||||
messageBarType={1}
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"marginLeft": 10,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
sample error
|
||||
</StyledMessageBarBase>
|
||||
</Stack>
|
||||
`;
|
||||
@@ -0,0 +1,137 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`MongoIndexingPolicyComponent renders 1`] = `
|
||||
<Stack
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 20,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Text>
|
||||
For queries that filter on multiple properties, create multiple single field indexes instead of a compound index.
|
||||
<StyledLinkBase
|
||||
href="https://docs.microsoft.com/azure/cosmos-db/mongodb-indexing#index-types"
|
||||
target="_blank"
|
||||
>
|
||||
Compound indexes
|
||||
</StyledLinkBase>
|
||||
are only used for sorting query results. If you need to add a compound index, you can create one using the Mongo shell.
|
||||
</Text>
|
||||
<Stack
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"width": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 5,
|
||||
}
|
||||
}
|
||||
>
|
||||
<CollapsibleSectionComponent
|
||||
title="Current index(es)"
|
||||
>
|
||||
<StyledWithViewportComponent
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"fieldName": "definition",
|
||||
"isResizable": true,
|
||||
"key": "definition",
|
||||
"maxWidth": 200,
|
||||
"minWidth": 100,
|
||||
"name": "Definition",
|
||||
},
|
||||
Object {
|
||||
"fieldName": "type",
|
||||
"isResizable": true,
|
||||
"key": "type",
|
||||
"maxWidth": 200,
|
||||
"minWidth": 100,
|
||||
"name": "Type",
|
||||
},
|
||||
Object {
|
||||
"fieldName": "actionButton",
|
||||
"isResizable": true,
|
||||
"key": "actionButton",
|
||||
"maxWidth": 200,
|
||||
"minWidth": 100,
|
||||
"name": "Drop Index",
|
||||
},
|
||||
]
|
||||
}
|
||||
disableSelectionZone={true}
|
||||
items={Array []}
|
||||
layoutMode={1}
|
||||
onRenderRow={[Function]}
|
||||
selectionMode={0}
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"selectors": Object {
|
||||
".ms-FocusZone": Object {
|
||||
"paddingTop": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<Stack
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"width": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
tokens={
|
||||
Object {
|
||||
"childrenGap": 10,
|
||||
}
|
||||
}
|
||||
>
|
||||
<AddMongoIndexComponent
|
||||
disabled={false}
|
||||
key="0"
|
||||
onDiscard={[Function]}
|
||||
onIndexAddOrChange={[Function]}
|
||||
position={0}
|
||||
/>
|
||||
</Stack>
|
||||
</CollapsibleSectionComponent>
|
||||
</Stack>
|
||||
<Styled
|
||||
styles={
|
||||
Object {
|
||||
"root": Array [
|
||||
Object {
|
||||
"selectors": Object {
|
||||
"::before": Object {
|
||||
"background": undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
/>
|
||||
<Stack
|
||||
styles={
|
||||
Object {
|
||||
"root": Object {
|
||||
"width": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<CollapsibleSectionComponent
|
||||
title="Index(es) to be dropped"
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
`;
|
||||
@@ -3,7 +3,7 @@ import * as AutoPilotUtils from "../../../../../Utils/AutoPilotUtils";
|
||||
import {
|
||||
getTextFieldStyles,
|
||||
getToolTipContainer,
|
||||
spendAckCheckBoxStyle,
|
||||
noLeftPaddingCheckBoxStyle,
|
||||
titleAndInputStackProps,
|
||||
checkBoxAndInputStackProps,
|
||||
getChoiceGroupStyles,
|
||||
@@ -278,7 +278,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
|
||||
{this.props.spendAckVisible && (
|
||||
<Checkbox
|
||||
id="spendAckCheckBox"
|
||||
styles={spendAckCheckBoxStyle}
|
||||
styles={noLeftPaddingCheckBoxStyle}
|
||||
label={this.props.spendAckText}
|
||||
checked={this.state.spendAckChecked}
|
||||
onChange={this.onSpendAckChecked}
|
||||
@@ -317,7 +317,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
|
||||
{this.props.spendAckVisible && (
|
||||
<Checkbox
|
||||
id="spendAckCheckBox"
|
||||
styles={spendAckCheckBoxStyle}
|
||||
styles={noLeftPaddingCheckBoxStyle}
|
||||
label={this.props.spendAckText}
|
||||
checked={this.state.spendAckChecked}
|
||||
onChange={this.onSpendAckChecked}
|
||||
|
||||
Reference in New Issue
Block a user