mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-19 17:01:13 +00:00
@@ -1,5 +1,8 @@
|
||||
import { IndexingPolicy } from "@azure/cosmos";
|
||||
import { act } from "@testing-library/react";
|
||||
import { AuthType } from "AuthType";
|
||||
import { shallow } from "enzyme";
|
||||
import { useIndexingPolicyStore } from "Explorer/Tabs/QueryTab/ResultsView";
|
||||
import ko from "knockout";
|
||||
import React from "react";
|
||||
import { updateCollection } from "../../../Common/dataAccess/updateCollection";
|
||||
@@ -287,3 +290,47 @@ describe("SettingsComponent", () => {
|
||||
expect(wrapper.state("isThroughputBucketsSaveable")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("SettingsComponent - indexing policy subscription", () => {
|
||||
const baseProps: SettingsComponentProps = {
|
||||
settingsTab: new CollectionSettingsTabV2({
|
||||
collection: collection,
|
||||
tabKind: ViewModels.CollectionTabKind.CollectionSettingsV2,
|
||||
title: "Scale & Settings",
|
||||
tabPath: "",
|
||||
node: undefined,
|
||||
}),
|
||||
};
|
||||
|
||||
it("subscribes to the correct container's indexing policy and updates state on change", async () => {
|
||||
const containerId = collection.id();
|
||||
const mockIndexingPolicy: IndexingPolicy = {
|
||||
automatic: false,
|
||||
indexingMode: "lazy",
|
||||
includedPaths: [{ path: "/foo/*" }],
|
||||
excludedPaths: [{ path: "/bar/*" }],
|
||||
compositeIndexes: [],
|
||||
spatialIndexes: [],
|
||||
vectorIndexes: [],
|
||||
fullTextIndexes: [],
|
||||
};
|
||||
|
||||
const wrapper = shallow(<SettingsComponent {...baseProps} />);
|
||||
const instance = wrapper.instance() as SettingsComponent;
|
||||
|
||||
await act(async () => {
|
||||
useIndexingPolicyStore.setState({
|
||||
indexingPolicies: {
|
||||
[containerId]: mockIndexingPolicy,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
wrapper.update();
|
||||
|
||||
expect(wrapper.state("indexingPolicyContent")).toEqual(mockIndexingPolicy);
|
||||
expect(wrapper.state("indexingPolicyContentBaseline")).toEqual(mockIndexingPolicy);
|
||||
// @ts-expect-error: rawDataModel is intentionally accessed for test validation
|
||||
expect(instance.collection.rawDataModel.indexingPolicy).toEqual(mockIndexingPolicy);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
ThroughputBucketsComponent,
|
||||
ThroughputBucketsComponentProps,
|
||||
} from "Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputBucketsComponent";
|
||||
import { useIndexingPolicyStore } from "Explorer/Tabs/QueryTab/ResultsView";
|
||||
import { useDatabases } from "Explorer/useDatabases";
|
||||
import { isFabricNative } from "Platform/Fabric/FabricUtil";
|
||||
import { isVectorSearchEnabled } from "Utils/CapabilityUtils";
|
||||
@@ -72,7 +73,6 @@ import {
|
||||
parseConflictResolutionMode,
|
||||
parseConflictResolutionProcedure,
|
||||
} from "./SettingsUtils";
|
||||
|
||||
interface SettingsV2TabInfo {
|
||||
tab: SettingsV2TabTypes;
|
||||
content: JSX.Element;
|
||||
@@ -175,7 +175,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
||||
private totalThroughputUsed: number;
|
||||
private throughputBucketsEnabled: boolean;
|
||||
public mongoDBCollectionResource: MongoDBCollectionResource;
|
||||
|
||||
private unsubscribe: () => void;
|
||||
constructor(props: SettingsComponentProps) {
|
||||
super(props);
|
||||
|
||||
@@ -305,8 +305,19 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
||||
if (this.props.settingsTab.isActive()) {
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
}
|
||||
this.unsubscribe = useIndexingPolicyStore.subscribe(
|
||||
() => {
|
||||
this.refreshCollectionData();
|
||||
},
|
||||
(state) => state.indexingPolicies[this.collection.id()],
|
||||
);
|
||||
this.refreshCollectionData();
|
||||
}
|
||||
componentWillUnmount(): void {
|
||||
if (this.unsubscribe) {
|
||||
this.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(): void {
|
||||
if (this.props.settingsTab.isActive()) {
|
||||
useCommandBar.getState().setContextButtons(this.getTabsButtons());
|
||||
@@ -788,7 +799,6 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
||||
{ name: "name_of_property", query: "query_to_compute_property" },
|
||||
] as DataModels.ComputedProperties;
|
||||
}
|
||||
|
||||
const throughputBuckets = this.offer?.throughputBuckets;
|
||||
|
||||
return {
|
||||
@@ -940,10 +950,31 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
||||
startKey,
|
||||
);
|
||||
};
|
||||
private refreshCollectionData = async (): Promise<void> => {
|
||||
const containerId = this.collection.id();
|
||||
const latestIndexingPolicy = useIndexingPolicyStore.getState().indexingPolicies[containerId];
|
||||
const rawPolicy = latestIndexingPolicy ?? this.collection.indexingPolicy();
|
||||
|
||||
const latestCollection: DataModels.IndexingPolicy = {
|
||||
automatic: rawPolicy?.automatic ?? true,
|
||||
indexingMode: rawPolicy?.indexingMode ?? "consistent",
|
||||
includedPaths: rawPolicy?.includedPaths ?? [],
|
||||
excludedPaths: rawPolicy?.excludedPaths ?? [],
|
||||
compositeIndexes: rawPolicy?.compositeIndexes ?? [],
|
||||
spatialIndexes: rawPolicy?.spatialIndexes ?? [],
|
||||
vectorIndexes: rawPolicy?.vectorIndexes ?? [],
|
||||
fullTextIndexes: rawPolicy?.fullTextIndexes ?? [],
|
||||
};
|
||||
|
||||
this.collection.rawDataModel.indexingPolicy = latestCollection;
|
||||
this.setState({
|
||||
indexingPolicyContent: latestCollection,
|
||||
indexingPolicyContentBaseline: latestCollection,
|
||||
});
|
||||
};
|
||||
|
||||
private saveCollectionSettings = async (startKey: number): Promise<void> => {
|
||||
const newCollection: DataModels.Collection = { ...this.collection.rawDataModel };
|
||||
|
||||
if (
|
||||
this.state.isSubSettingsSaveable ||
|
||||
this.state.isContainerPolicyDirty ||
|
||||
@@ -1172,7 +1203,6 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
|
||||
onScaleDiscardableChange: this.onScaleDiscardableChange,
|
||||
throughputError: this.state.throughputError,
|
||||
};
|
||||
|
||||
if (!this.isCollectionSettingsTab) {
|
||||
return (
|
||||
<div className="settingsV2MainContainer">
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as React from "react";
|
||||
import { MessageBar, MessageBarType } from "@fluentui/react";
|
||||
import * as React from "react";
|
||||
import { handleError } from "../../../../../Common/ErrorHandlingUtils";
|
||||
import {
|
||||
mongoIndexTransformationRefreshingMessage,
|
||||
renderMongoIndexTransformationRefreshMessage,
|
||||
} from "../../SettingsRenderUtils";
|
||||
import { handleError } from "../../../../../Common/ErrorHandlingUtils";
|
||||
import { isIndexTransforming } from "../../SettingsUtils";
|
||||
|
||||
export interface IndexingPolicyRefreshComponentProps {
|
||||
|
||||
@@ -72,6 +72,16 @@ exports[`SettingsComponent renders 1`] = `
|
||||
"partitionKey",
|
||||
],
|
||||
"rawDataModel": {
|
||||
"indexingPolicy": {
|
||||
"automatic": true,
|
||||
"compositeIndexes": [],
|
||||
"excludedPaths": [],
|
||||
"fullTextIndexes": [],
|
||||
"includedPaths": [],
|
||||
"indexingMode": "consistent",
|
||||
"spatialIndexes": [],
|
||||
"vectorIndexes": [],
|
||||
},
|
||||
"uniqueKeyPolicy": {
|
||||
"uniqueKeys": [
|
||||
{
|
||||
@@ -164,6 +174,16 @@ exports[`SettingsComponent renders 1`] = `
|
||||
"partitionKey",
|
||||
],
|
||||
"rawDataModel": {
|
||||
"indexingPolicy": {
|
||||
"automatic": true,
|
||||
"compositeIndexes": [],
|
||||
"excludedPaths": [],
|
||||
"fullTextIndexes": [],
|
||||
"includedPaths": [],
|
||||
"indexingMode": "consistent",
|
||||
"spatialIndexes": [],
|
||||
"vectorIndexes": [],
|
||||
},
|
||||
"uniqueKeyPolicy": {
|
||||
"uniqueKeys": [
|
||||
{
|
||||
@@ -238,17 +258,25 @@ exports[`SettingsComponent renders 1`] = `
|
||||
indexingPolicyContent={
|
||||
{
|
||||
"automatic": true,
|
||||
"compositeIndexes": [],
|
||||
"excludedPaths": [],
|
||||
"fullTextIndexes": [],
|
||||
"includedPaths": [],
|
||||
"indexingMode": "consistent",
|
||||
"spatialIndexes": [],
|
||||
"vectorIndexes": [],
|
||||
}
|
||||
}
|
||||
indexingPolicyContentBaseline={
|
||||
{
|
||||
"automatic": true,
|
||||
"compositeIndexes": [],
|
||||
"excludedPaths": [],
|
||||
"fullTextIndexes": [],
|
||||
"includedPaths": [],
|
||||
"indexingMode": "consistent",
|
||||
"spatialIndexes": [],
|
||||
"vectorIndexes": [],
|
||||
}
|
||||
}
|
||||
isVectorSearchEnabled={false}
|
||||
@@ -321,6 +349,16 @@ exports[`SettingsComponent renders 1`] = `
|
||||
"partitionKey",
|
||||
],
|
||||
"rawDataModel": {
|
||||
"indexingPolicy": {
|
||||
"automatic": true,
|
||||
"compositeIndexes": [],
|
||||
"excludedPaths": [],
|
||||
"fullTextIndexes": [],
|
||||
"includedPaths": [],
|
||||
"indexingMode": "consistent",
|
||||
"spatialIndexes": [],
|
||||
"vectorIndexes": [],
|
||||
},
|
||||
"uniqueKeyPolicy": {
|
||||
"uniqueKeys": [
|
||||
{
|
||||
@@ -461,6 +499,16 @@ exports[`SettingsComponent renders 1`] = `
|
||||
"partitionKey",
|
||||
],
|
||||
"rawDataModel": {
|
||||
"indexingPolicy": {
|
||||
"automatic": true,
|
||||
"compositeIndexes": [],
|
||||
"excludedPaths": [],
|
||||
"fullTextIndexes": [],
|
||||
"includedPaths": [],
|
||||
"indexingMode": "consistent",
|
||||
"spatialIndexes": [],
|
||||
"vectorIndexes": [],
|
||||
},
|
||||
"uniqueKeyPolicy": {
|
||||
"uniqueKeys": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user