From 263ad9a5e6f09181a5a01b2315e129011ea9a91d Mon Sep 17 00:00:00 2001 From: Chuck Skelton Date: Fri, 23 Jun 2023 16:02:11 -0700 Subject: [PATCH 1/8] Added Computed Properties tab to scale and settings --- src/Contracts/DataModels.ts | 10 +- src/Contracts/ViewModels.ts | 1 + .../Controls/Settings/SettingsComponent.tsx | 95 ++++++++++++- .../Controls/Settings/SettingsRenderUtils.tsx | 7 +- .../ComputedPropertiesComponent.test.tsx | 56 ++++++++ .../ComputedPropertiesComponent.tsx | 125 ++++++++++++++++++ .../IndexingPolicyComponent.tsx | 4 +- .../MongoIndexingPolicyComponent.tsx | 10 +- .../ComputedPropertiesComponent.test.tsx.snap | 16 +++ .../Controls/Settings/SettingsUtils.tsx | 5 +- src/Explorer/Controls/Settings/TestUtils.tsx | 6 + .../SettingsComponent.test.tsx.snap | 36 +++++ .../SettingsRenderUtils.test.tsx.snap | 12 -- src/Explorer/Tree/Collection.ts | 12 +- .../arm/generatedClients/cosmos/types.ts | 9 ++ 15 files changed, 369 insertions(+), 35 deletions(-) create mode 100644 src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.test.tsx create mode 100644 src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.tsx create mode 100644 src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ComputedPropertiesComponent.test.tsx.snap diff --git a/src/Contracts/DataModels.ts b/src/Contracts/DataModels.ts index dd8f95c18..49e72473d 100644 --- a/src/Contracts/DataModels.ts +++ b/src/Contracts/DataModels.ts @@ -154,6 +154,7 @@ export interface Collection extends Resource { geospatialConfig?: GeospatialConfig; schema?: ISchema; requestSchema?: () => void; + computedProperties?: ComputedProperties; } export interface CollectionsWithPagination { @@ -165,7 +166,7 @@ export interface Database extends Resource { collections?: Collection[]; } -export interface DocumentId extends Resource {} +export interface DocumentId extends Resource { } export interface ConflictId extends Resource { resourceId?: string; @@ -192,6 +193,13 @@ export interface IndexingPolicy { spatialIndexes?: any; } +export interface ComputedProperty { + name: string; + query: string; +} + +export type ComputedProperties = ComputedProperty[] + export interface PartitionKey { paths: string[]; kind: "Hash" | "Range" | "MultiHash"; diff --git a/src/Contracts/ViewModels.ts b/src/Contracts/ViewModels.ts index c9bb351bc..bc36a4e8a 100644 --- a/src/Contracts/ViewModels.ts +++ b/src/Contracts/ViewModels.ts @@ -135,6 +135,7 @@ export interface Collection extends CollectionBase { changeFeedPolicy: ko.Observable; geospatialConfig: ko.Observable; documentIds: ko.ObservableArray; + computedProperties: ko.Observable; cassandraKeys: CassandraTableKeys; cassandraSchema: CassandraTableKey[]; diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index ee3393ee9..cc4912921 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -1,22 +1,26 @@ import { IPivotItemProps, IPivotProps, Pivot, PivotItem } from "@fluentui/react"; +import { + ComputedPropertiesComponent, + ComputedPropertiesComponentProps, +} from "Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent"; import { useDatabases } from "Explorer/useDatabases"; import * as React from "react"; import DiscardIcon from "../../../../images/discard.svg"; import SaveIcon from "../../../../images/save-cosmos.svg"; import { AuthType } from "../../../AuthType"; import * as Constants from "../../../Common/Constants"; +import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils"; import { getIndexTransformationProgress } from "../../../Common/dataAccess/getIndexTransformationProgress"; import { readMongoDBCollectionThroughRP } from "../../../Common/dataAccess/readMongoDBCollection"; import { updateCollection } from "../../../Common/dataAccess/updateCollection"; import { updateOffer } from "../../../Common/dataAccess/updateOffer"; -import { getErrorMessage, getErrorStack } from "../../../Common/ErrorHandlingUtils"; import * as DataModels from "../../../Contracts/DataModels"; import * as ViewModels from "../../../Contracts/ViewModels"; import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; import { trace, traceFailure, traceStart, traceSuccess } from "../../../Shared/Telemetry/TelemetryProcessor"; import { userContext } from "../../../UserContext"; -import { MongoDBCollectionResource, MongoIndex } from "../../../Utils/arm/generatedClients/cosmos/types"; import * as AutoPilotUtils from "../../../Utils/AutoPilotUtils"; +import { MongoDBCollectionResource, MongoIndex } from "../../../Utils/arm/generatedClients/cosmos/types"; import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; import { useCommandBar } from "../../Menus/CommandBar/CommandBarComponentAdapter"; import { SettingsTabV2 } from "../../Tabs/SettingsTabV2"; @@ -37,15 +41,15 @@ import { AddMongoIndexProps, ChangeFeedPolicyState, GeospatialConfigType, + MongoIndexTypes, + SettingsV2TabTypes, + TtlType, getMongoNotification, getTabTitle, hasDatabaseSharedThroughput, isDirty, - MongoIndexTypes, parseConflictResolutionMode, parseConflictResolutionProcedure, - SettingsV2TabTypes, - TtlType, } from "./SettingsUtils"; interface SettingsV2TabInfo { @@ -101,6 +105,11 @@ export interface SettingsComponentState { indexesToAdd: AddMongoIndexProps[]; indexTransformationProgress: number; + computedPropertiesContent: DataModels.ComputedProperties; + computedPropertiesContentBaseline: DataModels.ComputedProperties; + shouldDiscardComputedProperties: boolean; + isComputedPropertiesDirty: boolean; + conflictResolutionPolicyMode: DataModels.ConflictResolutionMode; conflictResolutionPolicyModeBaseline: DataModels.ConflictResolutionMode; conflictResolutionPolicyPath: string; @@ -125,6 +134,7 @@ export class SettingsComponent extends React.Component this.setState({ isMongoIndexingPolicyDiscardable }); + private onComputedPropertiesContentChange = (newComputedProperties: DataModels.ComputedProperties): void => + this.setState({ computedPropertiesContent: newComputedProperties }); + + private resetShouldDiscardComputedProperties = (): void => this.setState({ shouldDiscardComputedProperties: false }); + + private logComputedPropertiesSuccessMessage = (): void => { + if (this.props.settingsTab.onLoadStartKey) { + traceSuccess( + Action.Tab, + { + databaseName: this.collection.databaseId, + collectionName: this.collection.id(), + + dataExplorerArea: Constants.Areas.Tab, + tabTitle: this.props.settingsTab.tabTitle(), + }, + this.props.settingsTab.onLoadStartKey + ); + this.props.settingsTab.onLoadStartKey = undefined; + } + }; + + private onComputedPropertiesDirtyChange = (isComputedPropertiesDirty: boolean): void => + this.setState({ isComputedPropertiesDirty: isComputedPropertiesDirty }); + private calculateTotalThroughputUsed = (): void => { this.totalThroughputUsed = 0; (useDatabases.getState().databases || []).forEach(async (database) => { @@ -626,7 +672,6 @@ export class SettingsComponent extends React.Component => { const newCollection: DataModels.Collection = { ...this.collection.rawDataModel }; - if (this.state.isSubSettingsSaveable || this.state.isIndexingPolicyDirty || this.state.isConflictResolutionDirty) { + if ( + this.state.isSubSettingsSaveable || + this.state.isIndexingPolicyDirty || + this.state.isConflictResolutionDirty || + this.state.isComputedPropertiesDirty + ) { let defaultTtl: number; switch (this.state.timeToLive) { case TtlType.On: @@ -813,6 +871,10 @@ export class SettingsComponent extends React.Component, + }); + } + if (this.hasConflictResolution()) { tabs.push({ tab: SettingsV2TabTypes.ConflictResolutionTab, diff --git a/src/Explorer/Controls/Settings/SettingsRenderUtils.tsx b/src/Explorer/Controls/Settings/SettingsRenderUtils.tsx index b2c5c7c73..ce0c86978 100644 --- a/src/Explorer/Controls/Settings/SettingsRenderUtils.tsx +++ b/src/Explorer/Controls/Settings/SettingsRenderUtils.tsx @@ -60,6 +60,8 @@ export interface PriceBreakdown { currencySign: string; } +export type editorType = "indexPolicy" | "computedProperties"; + export const infoAndToolTipTextStyle: ITextStyles = { root: { fontSize: 14, color: "windowtext" } }; export const noLeftPaddingCheckBoxStyle: ICheckboxStyles = { @@ -253,9 +255,10 @@ export const ttlWarning: JSX.Element = ( ); -export const indexingPolicynUnsavedWarningMessage: JSX.Element = ( +export const unsavedEditorWarningMessage = (editor: editorType): JSX.Element => ( - You have not saved the latest changes made to your indexing policy. Please click save to confirm the changes. + You have not saved the latest changes made to your{" "} + {editor == "indexPolicy" ? "indexing policy" : "computed properties"}. Please click save to confirm the changes. ); diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.test.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.test.tsx new file mode 100644 index 000000000..811bc17ba --- /dev/null +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.test.tsx @@ -0,0 +1,56 @@ +import * as DataModels from "Contracts/DataModels"; +import { shallow } from "enzyme"; +import React from "react"; +import { ComputedPropertiesComponent, ComputedPropertiesComponentProps } from "./ComputedPropertiesComponent"; + +describe("ComputedPropertiesComponent", () => { + const initialComputedPropertiesContent: DataModels.ComputedProperties = [ + { + name: "prop1", + query: "query1", + }, + ]; + const baseProps: ComputedPropertiesComponentProps = { + computedPropertiesContent: initialComputedPropertiesContent, + computedPropertiesContentBaseline: initialComputedPropertiesContent, + logComputedPropertiesSuccessMessage: () => { + return; + }, + onComputedPropertiesContentChange: () => { + return; + }, + onComputedPropertiesDirtyChange: () => { + return; + }, + resetShouldDiscardComputedProperties: () => { + return; + }, + shouldDiscardComputedProperties: false, + }; + + it("renders", () => { + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + }); + + it("computed properties are reset", () => { + const wrapper = shallow(); + + const computedPropertiesComponentInstance = wrapper.instance() as ComputedPropertiesComponent; + const resetComputedPropertiesEditorMockFn = jest.fn(); + computedPropertiesComponentInstance.resetComputedPropertiesEditor = resetComputedPropertiesEditorMockFn; + + wrapper.setProps({ shouldDiscardComputedProperties: true }); + wrapper.update(); + expect(resetComputedPropertiesEditorMockFn.mock.calls.length).toEqual(1); + }); + + it("dirty is set", () => { + let computedPropertiesComponent = new ComputedPropertiesComponent(baseProps); + expect(computedPropertiesComponent.IsComponentDirty()).toEqual(false); + + const newProps = { ...baseProps, computedPropertiesContent: undefined as DataModels.ComputedProperties }; + computedPropertiesComponent = new ComputedPropertiesComponent(newProps); + expect(computedPropertiesComponent.IsComponentDirty()).toEqual(true); + }); +}); diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.tsx new file mode 100644 index 000000000..9fb8aabc9 --- /dev/null +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.tsx @@ -0,0 +1,125 @@ +// CTODO: Render/edit CP in monaco +// CTODO: Get CPs from RP +// CTODO: Save CPs to RP +import { MessageBar, MessageBarType, Stack } from "@fluentui/react"; +import * as DataModels from "Contracts/DataModels"; +import { titleAndInputStackProps, unsavedEditorWarningMessage } from "Explorer/Controls/Settings/SettingsRenderUtils"; +import { isDirty } from "Explorer/Controls/Settings/SettingsUtils"; +import { loadMonaco } from "Explorer/LazyMonaco"; +import * as monaco from "monaco-editor"; +import * as React from "react"; + +export interface ComputedPropertiesComponentProps { + computedPropertiesContent: DataModels.ComputedProperties; + computedPropertiesContentBaseline: DataModels.ComputedProperties; + logComputedPropertiesSuccessMessage: () => void; + onComputedPropertiesContentChange: (newComputedProperties: DataModels.ComputedProperties) => void; + onComputedPropertiesDirtyChange: (isComputedPropertiesDirty: boolean) => void; + resetShouldDiscardComputedProperties: () => void; + shouldDiscardComputedProperties: boolean; +} + +interface ComputedPropertiesComponentState { + computedPropertiesContentIsValid: boolean; +} + +export class ComputedPropertiesComponent extends React.Component< + ComputedPropertiesComponentProps, + ComputedPropertiesComponentState +> { + private shouldCheckComponentIsDirty = true; + private computedPropertiesDiv = React.createRef(); + private computedPropertiesEditor: monaco.editor.IStandaloneCodeEditor; + + constructor(props: ComputedPropertiesComponentProps) { + super(props); + this.state = { + computedPropertiesContentIsValid: true, + }; + } + + componentDidUpdate(): void { + if (this.props.shouldDiscardComputedProperties) { + this.resetComputedPropertiesEditor(); + this.props.resetShouldDiscardComputedProperties(); + } + this.onComponentUpdate(); + } + + componentDidMount(): void { + this.resetComputedPropertiesEditor(); + this.onComponentUpdate(); + } + + public resetComputedPropertiesEditor = (): void => { + if (!this.computedPropertiesEditor) { + this.createComputedPropertiesEditor(); + } else { + const indexingPolicyEditorModel = this.computedPropertiesEditor.getModel(); + const value: string = JSON.stringify(this.props.computedPropertiesContent, undefined, 4); + indexingPolicyEditorModel.setValue(value); + } + this.onComponentUpdate(); + }; + + private onComponentUpdate = (): void => { + if (!this.shouldCheckComponentIsDirty) { + this.shouldCheckComponentIsDirty = true; + return; + } + this.props.onComputedPropertiesDirtyChange(this.IsComponentDirty()); + this.shouldCheckComponentIsDirty = false; + }; + + public IsComponentDirty = (): boolean => { + if ( + isDirty(this.props.computedPropertiesContent, this.props.computedPropertiesContentBaseline) && + this.state.computedPropertiesContentIsValid + ) { + return true; + } + + return false; + }; + + private async createComputedPropertiesEditor(): Promise { + const value: string = JSON.stringify(this.props.computedPropertiesContent, undefined, 4); + const monaco = await loadMonaco(); + this.computedPropertiesEditor = monaco.editor.create(this.computedPropertiesDiv.current, { + value: value, + language: "json", + ariaLabel: "Indexing Policy", + }); + if (this.computedPropertiesEditor) { + const computedPropertiesEditorModel = this.computedPropertiesEditor.getModel(); + computedPropertiesEditorModel.onDidChangeContent(this.onEditorContentChange.bind(this)); + this.props.logComputedPropertiesSuccessMessage(); + } + } + + private onEditorContentChange = (): void => { + const computedPropertiesEditorModel = this.computedPropertiesEditor.getModel(); + try { + const newComputedPropertiesContent = JSON.parse( + computedPropertiesEditorModel.getValue() + ) as DataModels.ComputedProperties; + this.props.onComputedPropertiesContentChange(newComputedPropertiesContent); + this.setState({ computedPropertiesContentIsValid: true }); + } catch (e) { + this.setState({ computedPropertiesContentIsValid: false }); + } + }; + + public render(): JSX.Element { + return ( + + {isDirty(this.props.computedPropertiesContent, this.props.computedPropertiesContentBaseline) && ( + + {unsavedEditorWarningMessage("computedProperties")} + + )} +
+
+ ); + } +} diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/IndexingPolicyComponent.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/IndexingPolicyComponent.tsx index 1f216b241..4d6ca765f 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/IndexingPolicyComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/IndexingPolicyComponent.tsx @@ -3,7 +3,7 @@ import * as monaco from "monaco-editor"; import * as React from "react"; import * as DataModels from "../../../../Contracts/DataModels"; import { loadMonaco } from "../../../LazyMonaco"; -import { indexingPolicynUnsavedWarningMessage, titleAndInputStackProps } from "../SettingsRenderUtils"; +import { titleAndInputStackProps, unsavedEditorWarningMessage } from "../SettingsRenderUtils"; import { isDirty, isIndexTransforming } from "../SettingsUtils"; import { IndexingPolicyRefreshComponent } from "./IndexingPolicyRefresh/IndexingPolicyRefreshComponent"; @@ -120,7 +120,7 @@ export class IndexingPolicyComponent extends React.Component< refreshIndexTransformationProgress={this.props.refreshIndexTransformationProgress} /> {isDirty(this.props.indexingPolicyContent, this.props.indexingPolicyContentBaseline) && ( - {indexingPolicynUnsavedWarningMessage} + {unsavedEditorWarningMessage("indexPolicy")} )}
diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/MongoIndexingPolicy/MongoIndexingPolicyComponent.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/MongoIndexingPolicy/MongoIndexingPolicyComponent.tsx index 87ff37d75..cb7932f73 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/MongoIndexingPolicy/MongoIndexingPolicyComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/MongoIndexingPolicy/MongoIndexingPolicyComponent.tsx @@ -19,7 +19,6 @@ import { addMongoIndexStackProps, createAndAddMongoIndexStackProps, customDetailsListStyles, - indexingPolicynUnsavedWarningMessage, infoAndToolTipTextStyle, mediumWidthStackStyles, mongoCompoundIndexNotSupportedMessage, @@ -27,15 +26,16 @@ import { onRenderRow, separatorStyles, subComponentStackProps, + unsavedEditorWarningMessage, } from "../../SettingsRenderUtils"; import { AddMongoIndexProps, - getMongoIndexType, - getMongoIndexTypeText, - isIndexTransforming, MongoIndexIdField, MongoIndexTypes, MongoNotificationType, + getMongoIndexType, + getMongoIndexTypeText, + isIndexTransforming, } from "../../SettingsUtils"; import { IndexingPolicyRefreshComponent } from "../IndexingPolicyRefresh/IndexingPolicyRefreshComponent"; import { AddMongoIndexComponent } from "./AddMongoIndexComponent"; @@ -297,7 +297,7 @@ export class MongoIndexingPolicyComponent extends React.Component +
+ +`; diff --git a/src/Explorer/Controls/Settings/SettingsUtils.tsx b/src/Explorer/Controls/Settings/SettingsUtils.tsx index a533b6446..2764c9547 100644 --- a/src/Explorer/Controls/Settings/SettingsUtils.tsx +++ b/src/Explorer/Controls/Settings/SettingsUtils.tsx @@ -4,7 +4,7 @@ import * as ViewModels from "../../../Contracts/ViewModels"; import { MongoIndex } from "../../../Utils/arm/generatedClients/cosmos/types"; const zeroValue = 0; -export type isDirtyTypes = boolean | string | number | DataModels.IndexingPolicy; +export type isDirtyTypes = boolean | string | number | DataModels.IndexingPolicy | DataModels.ComputedProperties; export const TtlOff = "off"; export const TtlOn = "on"; export const TtlOnNoDefault = "on-nodefault"; @@ -45,6 +45,7 @@ export enum SettingsV2TabTypes { ConflictResolutionTab, SubSettingsTab, IndexingPolicyTab, + ComputedPropertiesTab, } export interface IsComponentDirtyResult { @@ -146,6 +147,8 @@ export const getTabTitle = (tab: SettingsV2TabTypes): string => { return "Settings"; case SettingsV2TabTypes.IndexingPolicyTab: return "Indexing Policy"; + case SettingsV2TabTypes.ComputedPropertiesTab: + return "Computed Properties"; default: throw new Error(`Unknown tab ${tab}`); } diff --git a/src/Explorer/Controls/Settings/TestUtils.tsx b/src/Explorer/Controls/Settings/TestUtils.tsx index 1d05c91f6..4039da5a5 100644 --- a/src/Explorer/Controls/Settings/TestUtils.tsx +++ b/src/Explorer/Controls/Settings/TestUtils.tsx @@ -40,6 +40,12 @@ export const collection = ({ version: 2, }, partitionKeyProperties: ["partitionKey"], + computedProperties: ko.observable([ + { + name: "queryName", + query: "query", + }, + ]), readSettings: () => { return; }, diff --git a/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap b/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap index bdad7d1f7..746db373b 100644 --- a/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap +++ b/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap @@ -26,6 +26,7 @@ exports[`SettingsComponent renders 1`] = ` Object { "analyticalStorageTtl": [Function], "changeFeedPolicy": [Function], + "computedProperties": [Function], "conflictResolutionPolicy": [Function], "container": Explorer { "_isInitializingNotebooks": false, @@ -103,6 +104,7 @@ exports[`SettingsComponent renders 1`] = ` Object { "analyticalStorageTtl": [Function], "changeFeedPolicy": [Function], + "computedProperties": [Function], "conflictResolutionPolicy": [Function], "container": Explorer { "_isInitializingNotebooks": false, @@ -202,6 +204,40 @@ exports[`SettingsComponent renders 1`] = ` shouldDiscardIndexingPolicy={false} /> + + +
diff --git a/src/Explorer/Controls/Settings/__snapshots__/SettingsRenderUtils.test.tsx.snap b/src/Explorer/Controls/Settings/__snapshots__/SettingsRenderUtils.test.tsx.snap index 004862ffe..5a71353cd 100644 --- a/src/Explorer/Controls/Settings/__snapshots__/SettingsRenderUtils.test.tsx.snap +++ b/src/Explorer/Controls/Settings/__snapshots__/SettingsRenderUtils.test.tsx.snap @@ -99,18 +99,6 @@ exports[`SettingsUtils functions render 1`] = ` . - - You have not saved the latest changes made to your indexing policy. Please click save to confirm the changes. - ; public uniqueKeyPolicy: DataModels.UniqueKeyPolicy; public usageSizeInKB: ko.Observable; + public computedProperties: ko.Observable; public offer: ko.Observable; public conflictResolutionPolicy: ko.Observable; @@ -120,6 +121,7 @@ export default class Collection implements ViewModels.Collection { this.schema = data.schema; this.requestSchema = data.requestSchema; this.geospatialConfig = ko.observable(data.geospatialConfig); + this.computedProperties = ko.observable(data.computedProperties); this.partitionKeyPropertyHeaders = this.partitionKey?.paths; this.partitionKeyProperties = this.partitionKeyPropertyHeaders?.map((partitionKeyPropertyHeader, i) => { diff --git a/src/Utils/arm/generatedClients/cosmos/types.ts b/src/Utils/arm/generatedClients/cosmos/types.ts index 7834ab96e..cc92bb98c 100644 --- a/src/Utils/arm/generatedClients/cosmos/types.ts +++ b/src/Utils/arm/generatedClients/cosmos/types.ts @@ -1045,6 +1045,8 @@ export interface SqlContainerResource { /* Analytical TTL. */ analyticalStorageTtl?: number; + + computedProperties?: ComputedProperties; } /* Cosmos DB indexing policy */ @@ -1067,6 +1069,13 @@ export interface IndexingPolicy { spatialIndexes?: SpatialSpec[]; } +export type ComputedProperties = ComputedProperty[]; + +export interface ComputedProperty { + name?: string; + query?: string; +} + /* undocumented */ export interface ExcludedPath { /* The path for which the indexing behavior applies to. Index paths typically start with root and end with wildcard (/path/*) */ From bb8529c79c27635a8352eab9c64430cd3afe8e42 Mon Sep 17 00:00:00 2001 From: Chuck Skelton Date: Fri, 23 Jun 2023 16:22:57 -0700 Subject: [PATCH 2/8] Fixing minor issues --- src/Contracts/DataModels.ts | 4 ++-- .../Controls/Settings/SettingsComponent.tsx | 16 +++++++--------- .../Settings/SettingsRenderUtils.test.tsx | 2 -- .../Controls/Settings/SettingsRenderUtils.tsx | 10 +++++----- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/Contracts/DataModels.ts b/src/Contracts/DataModels.ts index 49e72473d..2d7bfde25 100644 --- a/src/Contracts/DataModels.ts +++ b/src/Contracts/DataModels.ts @@ -166,7 +166,7 @@ export interface Database extends Resource { collections?: Collection[]; } -export interface DocumentId extends Resource { } +export interface DocumentId extends Resource {} export interface ConflictId extends Resource { resourceId?: string; @@ -198,7 +198,7 @@ export interface ComputedProperty { query: string; } -export type ComputedProperties = ComputedProperty[] +export type ComputedProperties = ComputedProperty[]; export interface PartitionKey { paths: string[]; diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index cc4912921..cfff241e6 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -681,7 +681,7 @@ export class SettingsComponent extends React.Component ( You have not saved the latest changes made to your{" "} - {editor == "indexPolicy" ? "indexing policy" : "computed properties"}. Please click save to confirm the changes. + {editor === "indexPolicy" ? "indexing policy" : "computed properties"}. Please click save to confirm the changes. ); @@ -341,10 +341,10 @@ const getCurrentThroughput = ( if (throughput) { return isAutoscale ? `, Current autoscale throughput: ${Math.round( - throughput / 10 - )} - ${throughput} ${throughputUnit}, Target autoscale throughput: ${Math.round( - targetThroughput / 10 - )} - ${targetThroughput} ${throughputUnit}` + throughput / 10 + )} - ${throughput} ${throughputUnit}, Target autoscale throughput: ${Math.round( + targetThroughput / 10 + )} - ${targetThroughput} ${throughputUnit}` : `, Current manual throughput: ${throughput} ${throughputUnit}, Target manual throughput: ${targetThroughput}`; } else { return isAutoscale From 4fd75f124dd8c8ac3c291de90b6c34556c5c5e24 Mon Sep 17 00:00:00 2001 From: Chuck Skelton Date: Fri, 23 Jun 2023 16:27:13 -0700 Subject: [PATCH 3/8] Fixing prettier --- .../Controls/Settings/SettingsComponent.tsx | 14 ++++++++------ .../Controls/Settings/SettingsRenderUtils.tsx | 8 ++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index cfff241e6..3b7c6a029 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -751,8 +751,9 @@ export class SettingsComponent extends React.Component Date: Fri, 23 Jun 2023 16:53:04 -0700 Subject: [PATCH 4/8] Making computed properties available only to non-SDK users --- src/Explorer/Controls/Settings/SettingsComponent.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index 3b7c6a029..e3fd1bb3a 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -1144,7 +1144,11 @@ export class SettingsComponent extends React.Component, From 00d30d5ef0663a5b2c2b30e91195ccfe11387aab Mon Sep 17 00:00:00 2001 From: Chuck Skelton Date: Fri, 23 Jun 2023 17:31:57 -0700 Subject: [PATCH 5/8] Minor text change, enabling feature for connection string --- .../Controls/Settings/SettingsComponent.tsx | 18 +++++++----------- .../Controls/Settings/SettingsUtils.tsx | 2 +- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index e3fd1bb3a..07d932970 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -751,9 +751,8 @@ export class SettingsComponent extends React.Component { case SettingsV2TabTypes.IndexingPolicyTab: return "Indexing Policy"; case SettingsV2TabTypes.ComputedPropertiesTab: - return "Computed Properties"; + return "Computed Properties (preview)"; default: throw new Error(`Unknown tab ${tab}`); } From f54c12329053b8121251bbeed15eb3fe91c952d9 Mon Sep 17 00:00:00 2001 From: Chuck Skelton Date: Fri, 23 Jun 2023 17:36:16 -0700 Subject: [PATCH 6/8] Updating test snapshot --- .../Settings/__snapshots__/SettingsComponent.test.tsx.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap b/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap index 746db373b..a9d03795a 100644 --- a/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap +++ b/src/Explorer/Controls/Settings/__snapshots__/SettingsComponent.test.tsx.snap @@ -205,7 +205,7 @@ exports[`SettingsComponent renders 1`] = ` /> Date: Fri, 23 Jun 2023 17:37:40 -0700 Subject: [PATCH 7/8] Prettier fix --- .../Controls/Settings/SettingsComponent.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index 07d932970..3b7c6a029 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -751,8 +751,9 @@ export class SettingsComponent extends React.Component, From e4708516ed61ad73bf50ce6e56b9c6985116fb38 Mon Sep 17 00:00:00 2001 From: Chuck Skelton Date: Thu, 29 Jun 2023 17:43:20 -0700 Subject: [PATCH 8/8] Added link to computed properties docs --- .../ComputedPropertiesComponent.tsx | 13 +++++++----- .../ComputedPropertiesComponent.test.tsx.snap | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.tsx index 9fb8aabc9..bbc9d2f16 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ComputedPropertiesComponent.tsx @@ -1,7 +1,4 @@ -// CTODO: Render/edit CP in monaco -// CTODO: Get CPs from RP -// CTODO: Save CPs to RP -import { MessageBar, MessageBarType, Stack } from "@fluentui/react"; +import { FontIcon, Link, MessageBar, MessageBarType, Stack, Text } from "@fluentui/react"; import * as DataModels from "Contracts/DataModels"; import { titleAndInputStackProps, unsavedEditorWarningMessage } from "Explorer/Controls/Settings/SettingsRenderUtils"; import { isDirty } from "Explorer/Controls/Settings/SettingsUtils"; @@ -88,7 +85,7 @@ export class ComputedPropertiesComponent extends React.Component< this.computedPropertiesEditor = monaco.editor.create(this.computedPropertiesDiv.current, { value: value, language: "json", - ariaLabel: "Indexing Policy", + ariaLabel: "Computed properties", }); if (this.computedPropertiesEditor) { const computedPropertiesEditorModel = this.computedPropertiesEditor.getModel(); @@ -118,6 +115,12 @@ export class ComputedPropertiesComponent extends React.Component< {unsavedEditorWarningMessage("computedProperties")} )} + + + {"Learn more"} + +   about how to define computed properties and how to use them. +
); diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ComputedPropertiesComponent.test.tsx.snap b/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ComputedPropertiesComponent.test.tsx.snap index eab45e0ba..86a9bda74 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ComputedPropertiesComponent.test.tsx.snap +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ComputedPropertiesComponent.test.tsx.snap @@ -8,6 +8,26 @@ exports[`ComputedPropertiesComponent renders 1`] = ` } } > + + + Learn more + + + +   about how to define computed properties and how to use them. +