From 82bdeff158cb0b761f6501e74959bda5f6f3dbdc Mon Sep 17 00:00:00 2001 From: Asier Isayas Date: Wed, 11 Sep 2024 08:07:50 -0400 Subject: [PATCH] Add new Portal Backend Sample Data API and remove Notifications API references (#1965) * Fixed Sample Data logic and remove notifications references * fixed undefined * fixed unit tests * fixed format test * cleanup --------- Co-authored-by: Asier Isayas --- src/Common/Constants.ts | 3 +- src/Common/EnvironmentUtility.test.ts | 16 +++ src/Common/EnvironmentUtility.ts | 23 ++++ src/Common/PortalNotifications.ts | 39 ------ src/ConfigContext.ts | 6 +- src/Contracts/ViewModels.ts | 3 - .../Settings/SettingsComponent.test.tsx | 1 - .../Controls/Settings/SettingsComponent.tsx | 3 - .../ScaleComponent.test.tsx | 39 ------ .../SettingsSubComponents/ScaleComponent.tsx | 26 ---- .../ScaleComponent.test.tsx.snap | 64 ---------- .../Controls/Settings/SettingsUtils.test.tsx | 1 - src/Explorer/Explorer.tsx | 7 +- src/Explorer/QueryCopilot/CopilotCarousel.tsx | 2 +- .../QueryCopilotUtilities.test.tsx | 14 +-- .../QueryCopilotTab.test.tsx.snap | 2 +- .../Tabs/QueryTab/QueryTabComponent.test.tsx | 2 +- src/Explorer/Tabs/TabsBase.ts | 3 - src/Explorer/Tree/Collection.ts | 37 ------ src/Explorer/Tree/Database.tsx | 115 +++++------------- src/Utils/EndpointUtils.ts | 5 + src/hooks/useKnockoutExplorer.ts | 15 ++- 22 files changed, 107 insertions(+), 319 deletions(-) delete mode 100644 src/Common/PortalNotifications.ts delete mode 100644 src/Explorer/Controls/Settings/SettingsSubComponents/__snapshots__/ScaleComponent.test.tsx.snap diff --git a/src/Common/Constants.ts b/src/Common/Constants.ts index 23bcfc23f..a3e1ac7cf 100644 --- a/src/Common/Constants.ts +++ b/src/Common/Constants.ts @@ -136,6 +136,7 @@ export class BackendApi { public static readonly AccountRestrictions: string = "AccountRestrictions"; public static readonly RuntimeProxy: string = "RuntimeProxy"; public static readonly DisallowedLocations: string = "DisallowedLocations"; + public static readonly SampleData: string = "SampleData"; } export class PortalBackendEndpoints { @@ -503,7 +504,7 @@ export class PriorityLevel { public static readonly Default = "low"; } -export const QueryCopilotSampleDatabaseId = "CopilotSampleDb"; +export const QueryCopilotSampleDatabaseId = "CopilotSampleDB"; export const QueryCopilotSampleContainerId = "SampleContainer"; export const QueryCopilotSampleContainerSchema = { diff --git a/src/Common/EnvironmentUtility.test.ts b/src/Common/EnvironmentUtility.test.ts index 6b5b1e218..1c1d9d8da 100644 --- a/src/Common/EnvironmentUtility.test.ts +++ b/src/Common/EnvironmentUtility.test.ts @@ -1,3 +1,5 @@ +import { PortalBackendEndpoints } from "Common/Constants"; +import { updateConfigContext } from "ConfigContext"; import * as EnvironmentUtility from "./EnvironmentUtility"; describe("Environment Utility Test", () => { @@ -11,4 +13,18 @@ describe("Environment Utility Test", () => { const expectedResult = "test/"; expect(EnvironmentUtility.normalizeArmEndpoint(uri)).toEqual(expectedResult); }); + + it("Detect environment is Mpac", () => { + updateConfigContext({ + PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Mpac, + }); + expect(EnvironmentUtility.getEnvironment()).toBe(EnvironmentUtility.Environment.Mpac); + }); + + it("Detect environment is Development", () => { + updateConfigContext({ + PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Development, + }); + expect(EnvironmentUtility.getEnvironment()).toBe(EnvironmentUtility.Environment.Development); + }); }); diff --git a/src/Common/EnvironmentUtility.ts b/src/Common/EnvironmentUtility.ts index b133cd8b3..cafcbfb3e 100644 --- a/src/Common/EnvironmentUtility.ts +++ b/src/Common/EnvironmentUtility.ts @@ -1,6 +1,29 @@ +import { PortalBackendEndpoints } from "Common/Constants"; +import { configContext } from "ConfigContext"; + export function normalizeArmEndpoint(uri: string): string { if (uri && uri.slice(-1) !== "/") { return `${uri}/`; } return uri; } + +export enum Environment { + Development = "Development", + Mpac = "MPAC", + Prod = "Prod", + Fairfax = "Fairfax", + Mooncake = "Mooncake", +} + +export const getEnvironment = (): Environment => { + const environmentMap: { [key: string]: Environment } = { + [PortalBackendEndpoints.Development]: Environment.Development, + [PortalBackendEndpoints.Mpac]: Environment.Mpac, + [PortalBackendEndpoints.Prod]: Environment.Prod, + [PortalBackendEndpoints.Fairfax]: Environment.Fairfax, + [PortalBackendEndpoints.Mooncake]: Environment.Mooncake, + }; + + return environmentMap[configContext.PORTAL_BACKEND_ENDPOINT]; +}; diff --git a/src/Common/PortalNotifications.ts b/src/Common/PortalNotifications.ts deleted file mode 100644 index 774c37cad..000000000 --- a/src/Common/PortalNotifications.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { configContext, Platform } from "../ConfigContext"; -import * as DataModels from "../Contracts/DataModels"; -import * as ViewModels from "../Contracts/ViewModels"; -import { userContext } from "../UserContext"; -import { getAuthorizationHeader } from "../Utils/AuthorizationUtils"; - -const notificationsPath = () => { - switch (configContext.platform) { - case Platform.Hosted: - return "/api/guest/notifications"; - case Platform.Portal: - return "/api/notifications"; - default: - throw new Error(`Unknown platform: ${configContext.platform}`); - } -}; - -export const fetchPortalNotifications = async (): Promise => { - if (configContext.platform === Platform.Emulator || configContext.platform === Platform.Hosted) { - return []; - } - - const { databaseAccount, resourceGroup, subscriptionId } = userContext; - const url = `${configContext.BACKEND_ENDPOINT}${notificationsPath()}?accountName=${ - databaseAccount.name - }&subscriptionId=${subscriptionId}&resourceGroup=${resourceGroup}`; - const authorizationHeader: ViewModels.AuthorizationTokenHeaderMetadata = getAuthorizationHeader(); - const headers = { [authorizationHeader.header]: authorizationHeader.token }; - - const response = await window.fetch(url, { - headers, - }); - - if (!response.ok) { - throw new Error(await response.text()); - } - - return (await response.json()) as DataModels.Notification[]; -}; diff --git a/src/ConfigContext.ts b/src/ConfigContext.ts index 1877d8f0c..dd35909dd 100644 --- a/src/ConfigContext.ts +++ b/src/ConfigContext.ts @@ -49,13 +49,13 @@ export interface ConfigContext { ARCADIA_ENDPOINT: string; ARCADIA_LIVY_ENDPOINT_DNS_ZONE: string; BACKEND_ENDPOINT?: string; - PORTAL_BACKEND_ENDPOINT?: string; + PORTAL_BACKEND_ENDPOINT: string; NEW_BACKEND_APIS?: BackendApi[]; MONGO_BACKEND_ENDPOINT?: string; - MONGO_PROXY_ENDPOINT?: string; + MONGO_PROXY_ENDPOINT: string; NEW_MONGO_APIS?: string[]; MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED?: boolean; - CASSANDRA_PROXY_ENDPOINT?: string; + CASSANDRA_PROXY_ENDPOINT: string; NEW_CASSANDRA_APIS?: string[]; CASSANDRA_PROXY_OUTBOUND_IPS_ALLOWLISTED: boolean; PROXY_PATH?: string; diff --git a/src/Contracts/ViewModels.ts b/src/Contracts/ViewModels.ts index 04afc10bb..767665686 100644 --- a/src/Contracts/ViewModels.ts +++ b/src/Contracts/ViewModels.ts @@ -98,7 +98,6 @@ export interface Database extends TreeNode { openAddCollection(database: Database, event: MouseEvent): void; onSettingsClick: () => void; loadOffer(): Promise; - getPendingThroughputSplitNotification(): Promise; } export interface CollectionBase extends TreeNode { @@ -191,8 +190,6 @@ export interface Collection extends CollectionBase { onDragOver(source: Collection, event: { originalEvent: DragEvent }): void; onDrop(source: Collection, event: { originalEvent: DragEvent }): void; uploadFiles(fileList: FileList): Promise<{ data: UploadDetailsRecord[] }>; - - getPendingThroughputSplitNotification(): Promise; } /** diff --git a/src/Explorer/Controls/Settings/SettingsComponent.test.tsx b/src/Explorer/Controls/Settings/SettingsComponent.test.tsx index 20c2d027a..a97ee8f45 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.test.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.test.tsx @@ -134,7 +134,6 @@ describe("SettingsComponent", () => { readSettings: undefined, onSettingsClick: undefined, loadOffer: undefined, - getPendingThroughputSplitNotification: undefined, } as ViewModels.Database; newCollection.getDatabase = () => newDatabase; newCollection.offer = ko.observable(undefined); diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index 04e08753e..74f3fb4f6 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -130,7 +130,6 @@ export interface SettingsComponentState { conflictResolutionPolicyProcedureBaseline: string; isConflictResolutionDirty: boolean; - initialNotification: DataModels.Notification; selectedTab: SettingsV2TabTypes; } @@ -229,7 +228,6 @@ export class SettingsComponent extends React.Component { - const targetThroughput = 6000; - const baseProps: ScaleComponentProps = { collection: collection, database: undefined, @@ -36,39 +28,8 @@ describe("ScaleComponent", () => { onScaleDiscardableChange: () => { return; }, - initialNotification: { - description: `Throughput update for ${targetThroughput} ${throughputUnit}`, - } as DataModels.Notification, }; - it("renders with correct initial notification", () => { - let wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - expect(wrapper.exists(ThroughputInputAutoPilotV3Component)).toEqual(true); - expect(wrapper.exists("#throughputApplyLongDelayMessage")).toEqual(true); - expect(wrapper.exists("#throughputApplyShortDelayMessage")).toEqual(false); - expect(wrapper.find("#throughputApplyLongDelayMessage").html()).toContain(`${targetThroughput}`); - - const newCollection = { ...collection }; - const maxThroughput = 5000; - newCollection.offer = ko.observable({ - manualThroughput: undefined, - autoscaleMaxThroughput: maxThroughput, - minimumThroughput: 400, - id: "offer", - offerReplacePending: true, - }); - const newProps = { - ...baseProps, - initialNotification: undefined as DataModels.Notification, - collection: newCollection, - }; - wrapper = shallow(); - expect(wrapper.exists("#throughputApplyShortDelayMessage")).toEqual(true); - expect(wrapper.exists("#throughputApplyLongDelayMessage")).toEqual(false); - expect(wrapper.find("#throughputApplyShortDelayMessage").html()).toContain(`${maxThroughput}`); - }); - it("autoScale disabled", () => { const scaleComponent = new ScaleComponent(baseProps); expect(scaleComponent.isAutoScaleEnabled()).toEqual(false); diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.tsx index 761fe899b..251a3b841 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ScaleComponent.tsx @@ -10,7 +10,6 @@ import * as AutoPilotUtils from "../../../../Utils/AutoPilotUtils"; import { isRunningOnNationalCloud } from "../../../../Utils/CloudUtils"; import { getTextFieldStyles, - getThroughputApplyLongDelayMessage, getThroughputApplyShortDelayMessage, subComponentStackProps, throughputUnit, @@ -34,7 +33,6 @@ export interface ScaleComponentProps { onMaxAutoPilotThroughputChange: (newThroughput: number) => void; onScaleSaveableChange: (isScaleSaveable: boolean) => void; onScaleDiscardableChange: (isScaleDiscardable: boolean) => void; - initialNotification: DataModels.Notification; throughputError?: string; } @@ -102,10 +100,6 @@ export class ScaleComponent extends React.Component { }; public getInitialNotificationElement = (): JSX.Element => { - if (this.props.initialNotification) { - return this.getLongDelayMessage(); - } - if (this.offer?.offerReplacePending) { const throughput = this.offer.manualThroughput || this.offer.autoscaleMaxThroughput; return getThroughputApplyShortDelayMessage( @@ -120,26 +114,6 @@ export class ScaleComponent extends React.Component { return undefined; }; - public getLongDelayMessage = (): JSX.Element => { - const matches: string[] = this.props.initialNotification?.description.match( - `Throughput update for (.*) ${throughputUnit}`, - ); - - const throughput = this.props.throughputBaseline; - const targetThroughput: number = matches.length > 1 && Number(matches[1]); - if (targetThroughput) { - return getThroughputApplyLongDelayMessage( - this.props.wasAutopilotOriginallySet, - throughput, - throughputUnit, - this.databaseId, - this.collectionId, - targetThroughput, - ); - } - return <>; - }; - private getThroughputInputComponent = (): JSX.Element => ( - - - A request to increase the throughput is currently in progress. This operation will take 1-3 business days to complete. View the latest status in Notifications. -
- Database: test, Container: test - , Current autoscale throughput: 100 - 1000 RU/s, Target autoscale throughput: 600 - 6000 RU/s -
-
- - - - -`; diff --git a/src/Explorer/Controls/Settings/SettingsUtils.test.tsx b/src/Explorer/Controls/Settings/SettingsUtils.test.tsx index fd6a71eb9..020a8efef 100644 --- a/src/Explorer/Controls/Settings/SettingsUtils.test.tsx +++ b/src/Explorer/Controls/Settings/SettingsUtils.test.tsx @@ -44,7 +44,6 @@ describe("SettingsUtils", () => { readSettings: undefined, onSettingsClick: undefined, loadOffer: undefined, - getPendingThroughputSplitNotification: undefined, } as ViewModels.Database; }; newCollection.offer(undefined); diff --git a/src/Explorer/Explorer.tsx b/src/Explorer/Explorer.tsx index 4cfdc3bc3..da21f0cf8 100644 --- a/src/Explorer/Explorer.tsx +++ b/src/Explorer/Explorer.tsx @@ -1,6 +1,7 @@ import * as msal from "@azure/msal-browser"; import { Link } from "@fluentui/react/lib/Link"; import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility"; +import { Environment, getEnvironment } from "Common/EnvironmentUtility"; import { sendMessage } from "Common/MessageHandler"; import { Platform, configContext } from "ConfigContext"; import { MessageTypes } from "Contracts/ExplorerContracts"; @@ -1178,7 +1179,11 @@ export default class Explorer { } public async configureCopilot(): Promise { - if (userContext.apiType !== "SQL" || !userContext.subscriptionId) { + if ( + userContext.apiType !== "SQL" || + !userContext.subscriptionId || + ![Environment.Development, Environment.Mpac, Environment.Prod].includes(getEnvironment()) + ) { return; } const copilotEnabledPromise = getCopilotEnabled(); diff --git a/src/Explorer/QueryCopilot/CopilotCarousel.tsx b/src/Explorer/QueryCopilot/CopilotCarousel.tsx index d61924faf..4a73cacb8 100644 --- a/src/Explorer/QueryCopilot/CopilotCarousel.tsx +++ b/src/Explorer/QueryCopilot/CopilotCarousel.tsx @@ -171,7 +171,7 @@ export const QueryCopilotCarousel: React.FC = ({ the query builder. Database Id - CopilotSampleDb + CopilotSampleDB Database throughput (autoscale) Autoscale Database Max RU/s diff --git a/src/Explorer/QueryCopilot/QueryCopilotUtilities.test.tsx b/src/Explorer/QueryCopilot/QueryCopilotUtilities.test.tsx index c423b35ff..c0e6178eb 100644 --- a/src/Explorer/QueryCopilot/QueryCopilotUtilities.test.tsx +++ b/src/Explorer/QueryCopilot/QueryCopilotUtilities.test.tsx @@ -90,7 +90,7 @@ describe("QueryCopilotUtilities", () => { // Mock the items.query method to return the mockResult ( - sampleDataClient().database("CopilotSampleDb").container("SampleContainer").items.query as jest.Mock + sampleDataClient().database("CopilotSampleDB").container("SampleContainer").items.query as jest.Mock ).mockReturnValue(mockResult); const result = querySampleDocuments(query, options); @@ -119,10 +119,10 @@ describe("QueryCopilotUtilities", () => { const result = await readSampleDocument(documentId); expect(sampleDataClient).toHaveBeenCalled(); - expect(sampleDataClient().database).toHaveBeenCalledWith("CopilotSampleDb"); - expect(sampleDataClient().database("CopilotSampleDb").container).toHaveBeenCalledWith("SampleContainer"); + expect(sampleDataClient().database).toHaveBeenCalledWith("CopilotSampleDB"); + expect(sampleDataClient().database("CopilotSampleDB").container).toHaveBeenCalledWith("SampleContainer"); expect( - sampleDataClient().database("CopilotSampleDb").container("SampleContainer").item("DocumentId", undefined).read, + sampleDataClient().database("CopilotSampleDB").container("SampleContainer").item("DocumentId", undefined).read, ).toHaveBeenCalled(); expect(result).toEqual(expectedResponse); }); @@ -144,10 +144,10 @@ describe("QueryCopilotUtilities", () => { await expect(readSampleDocument(documentId)).rejects.toStrictEqual(errorMock); expect(sampleDataClient).toHaveBeenCalled(); - expect(sampleDataClient().database).toHaveBeenCalledWith("CopilotSampleDb"); - expect(sampleDataClient().database("CopilotSampleDb").container).toHaveBeenCalledWith("SampleContainer"); + expect(sampleDataClient().database).toHaveBeenCalledWith("CopilotSampleDB"); + expect(sampleDataClient().database("CopilotSampleDB").container).toHaveBeenCalledWith("SampleContainer"); expect( - sampleDataClient().database("CopilotSampleDb").container("SampleContainer").item("DocumentId", undefined).read, + sampleDataClient().database("CopilotSampleDB").container("SampleContainer").item("DocumentId", undefined).read, ).toHaveBeenCalled(); expect(handleError).toHaveBeenCalledWith(errorMock, "ReadDocument", expect.any(String)); }); diff --git a/src/Explorer/QueryCopilot/__snapshots__/QueryCopilotTab.test.tsx.snap b/src/Explorer/QueryCopilot/__snapshots__/QueryCopilotTab.test.tsx.snap index dd199c5c2..a3584164f 100644 --- a/src/Explorer/QueryCopilot/__snapshots__/QueryCopilotTab.test.tsx.snap +++ b/src/Explorer/QueryCopilot/__snapshots__/QueryCopilotTab.test.tsx.snap @@ -19,7 +19,7 @@ exports[`Query copilot tab snapshot test should render with initial input 1`] = > { }, }); const propsMock: Readonly = { - collection: { databaseId: "CopilotSampleDb" }, + collection: { databaseId: "CopilotSampleDB" }, onTabAccessor: () => jest.fn(), isExecutionError: false, tabId: "mockTabId", diff --git a/src/Explorer/Tabs/TabsBase.ts b/src/Explorer/Tabs/TabsBase.ts index 8b017f6bc..029fbfe6e 100644 --- a/src/Explorer/Tabs/TabsBase.ts +++ b/src/Explorer/Tabs/TabsBase.ts @@ -2,7 +2,6 @@ import { KeyboardActionGroup, clearKeyboardActionGroup } from "KeyboardShortcuts import * as ko from "knockout"; import * as Constants from "../../Common/Constants"; import * as ThemeUtility from "../../Common/ThemeUtility"; -import * as DataModels from "../../Contracts/DataModels"; import * as ViewModels from "../../Contracts/ViewModels"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; @@ -28,7 +27,6 @@ export default class TabsBase extends WaitsForTemplateViewModel { public tabPath: ko.Observable; public isExecutionError = ko.observable(false); public isExecuting = ko.observable(false); - public pendingNotification?: ko.Observable; protected _theme: string; public onLoadStartKey: number; @@ -45,7 +43,6 @@ export default class TabsBase extends WaitsForTemplateViewModel { this.tabPath = this.collection && ko.observable(`${this.collection.databaseId}>${this.collection.id()}>${options.title}`); - this.pendingNotification = ko.observable(undefined); this.onLoadStartKey = options.onLoadStartKey; this.closeTabButton = { enabled: ko.computed(() => { diff --git a/src/Explorer/Tree/Collection.ts b/src/Explorer/Tree/Collection.ts index fffacb134..26246f1b1 100644 --- a/src/Explorer/Tree/Collection.ts +++ b/src/Explorer/Tree/Collection.ts @@ -5,8 +5,6 @@ import * as ko from "knockout"; import * as _ from "underscore"; import * as Constants from "../../Common/Constants"; import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils"; -import * as Logger from "../../Common/Logger"; -import { fetchPortalNotifications } from "../../Common/PortalNotifications"; import { bulkCreateDocument } from "../../Common/dataAccess/bulkCreateDocument"; import { createDocument } from "../../Common/dataAccess/createDocument"; import { getCollectionUsageSizeInKB } from "../../Common/dataAccess/getCollectionDataUsageSize"; @@ -1020,41 +1018,6 @@ export default class Collection implements ViewModels.Collection { this.uploadFiles(event.originalEvent.dataTransfer.files); } - public async getPendingThroughputSplitNotification(): Promise { - if (!this.container) { - return undefined; - } - - try { - const notifications: DataModels.Notification[] = await fetchPortalNotifications(); - if (!notifications || notifications.length === 0) { - return undefined; - } - - return _.find(notifications, (notification: DataModels.Notification) => { - const throughputUpdateRegExp: RegExp = new RegExp("Throughput update (.*) in progress"); - return ( - notification.kind === "message" && - notification.collectionName === this.id() && - notification.description && - throughputUpdateRegExp.test(notification.description) - ); - }); - } catch (error) { - Logger.logError( - JSON.stringify({ - error: getErrorMessage(error), - accountName: userContext?.databaseAccount, - databaseName: this.databaseId, - collectionName: this.id(), - }), - "Settings tree node", - ); - - return undefined; - } - } - public async uploadFiles(files: FileList): Promise<{ data: UploadDetailsRecord[] }> { const data = await Promise.all(Array.from(files).map((file) => this.uploadFile(file))); diff --git a/src/Explorer/Tree/Database.tsx b/src/Explorer/Tree/Database.tsx index 7da55a1cf..0ed11cb5d 100644 --- a/src/Explorer/Tree/Database.tsx +++ b/src/Explorer/Tree/Database.tsx @@ -4,8 +4,6 @@ import * as _ from "underscore"; import { AuthType } from "../../AuthType"; import * as Constants from "../../Common/Constants"; import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils"; -import * as Logger from "../../Common/Logger"; -import { fetchPortalNotifications } from "../../Common/PortalNotifications"; import { readCollections, readCollectionsWithPagination } from "../../Common/dataAccess/readCollections"; import { readDatabaseOffer } from "../../Common/dataAccess/readDatabaseOffer"; import * as DataModels from "../../Contracts/DataModels"; @@ -76,7 +74,6 @@ export default class Database implements ViewModels.Database { await useDatabases.getState().loadAllOffers(); } - const pendingNotificationsPromise: Promise = this.getPendingThroughputSplitNotification(); const tabKind = ViewModels.CollectionTabKind.DatabaseSettingsV2; const matchingTabs = useTabs.getState().getTabs(tabKind, (tab) => tab.node?.id() === this.id()); let settingsTab = matchingTabs?.[0] as DatabaseSettingsTabV2; @@ -87,53 +84,39 @@ export default class Database implements ViewModels.Database { dataExplorerArea: Constants.Areas.Tab, tabTitle: "Scale", }); - pendingNotificationsPromise.then( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (data: any) => { - const pendingNotification: DataModels.Notification = data?.[0]; - const tabOptions: ViewModels.TabOptions = { - tabKind, - title: "Scale", - tabPath: "", - node: this, - rid: this.rid, - database: this, - onLoadStartKey: startKey, - }; - settingsTab = new DatabaseSettingsTabV2(tabOptions); - settingsTab.pendingNotification(pendingNotification); - useTabs.getState().activateNewTab(settingsTab); - }, - (error) => { - const errorMessage = getErrorMessage(error); - TelemetryProcessor.traceFailure( - Action.Tab, - { - databaseName: this.id(), - collectionName: this.id(), - dataExplorerArea: Constants.Areas.Tab, - tabTitle: "Scale", - error: errorMessage, - errorStack: getErrorStack(error), - }, - startKey, - ); - logConsoleError(`Error while fetching database settings for database ${this.id()}: ${errorMessage}`); - throw error; - }, - ); + try { + const tabOptions: ViewModels.TabOptions = { + tabKind, + title: "Scale", + tabPath: "", + node: this, + rid: this.rid, + database: this, + onLoadStartKey: startKey, + }; + settingsTab = new DatabaseSettingsTabV2(tabOptions); + useTabs.getState().activateNewTab(settingsTab); + } catch (error) { + const errorMessage = getErrorMessage(error); + TelemetryProcessor.traceFailure( + Action.Tab, + { + databaseName: this.id(), + collectionName: this.id(), + + dataExplorerArea: Constants.Areas.Tab, + tabTitle: "Scale", + error: errorMessage, + errorStack: getErrorStack(error), + }, + startKey, + ); + logConsoleError(`Error while fetching database settings for database ${this.id()}: ${errorMessage}`); + throw error; + } } else { - pendingNotificationsPromise.then( - (pendingNotification: DataModels.Notification) => { - settingsTab.pendingNotification(pendingNotification); - useTabs.getState().activateTab(settingsTab); - }, - () => { - settingsTab.pendingNotification(undefined); - useTabs.getState().activateTab(settingsTab); - }, - ); + useTabs.getState().activateTab(settingsTab); } }; @@ -260,42 +243,6 @@ export default class Database implements ViewModels.Database { } } - public async getPendingThroughputSplitNotification(): Promise { - if (!this.container) { - return undefined; - } - - try { - const notifications: DataModels.Notification[] = await fetchPortalNotifications(); - if (!notifications || notifications.length === 0) { - return undefined; - } - - return _.find(notifications, (notification: DataModels.Notification) => { - const throughputUpdateRegExp = new RegExp("Throughput update (.*) in progress"); - return ( - notification.kind === "message" && - !notification.collectionName && - notification.databaseName === this.id() && - notification.description && - throughputUpdateRegExp.test(notification.description) - ); - }); - } catch (error) { - Logger.logError( - JSON.stringify({ - error: getErrorMessage(error), - accountName: userContext?.databaseAccount, - databaseName: this.id(), - collectionName: this.id(), - }), - "Settings tree node", - ); - - return undefined; - } - } - private getDeltaCollections(updatedCollectionsList: DataModels.Collection[]): { toAdd: DataModels.Collection[]; toDelete: Collection[]; diff --git a/src/Utils/EndpointUtils.ts b/src/Utils/EndpointUtils.ts index cf0b66971..cbfa8d79d 100644 --- a/src/Utils/EndpointUtils.ts +++ b/src/Utils/EndpointUtils.ts @@ -192,6 +192,11 @@ export function useNewPortalBackendEndpoint(backendApi: string): boolean { PortalBackendEndpoints.Fairfax, PortalBackendEndpoints.Mooncake, ], + [BackendApi.SampleData]: [ + PortalBackendEndpoints.Development, + PortalBackendEndpoints.Mpac, + PortalBackendEndpoints.Prod, + ], }; if (!newBackendApiEnvironmentMap[backendApi] || !configContext.PORTAL_BACKEND_ENDPOINT) { diff --git a/src/hooks/useKnockoutExplorer.ts b/src/hooks/useKnockoutExplorer.ts index 028925d7d..08afeb65f 100644 --- a/src/hooks/useKnockoutExplorer.ts +++ b/src/hooks/useKnockoutExplorer.ts @@ -8,6 +8,7 @@ import { useDataPlaneRbac } from "Explorer/Panes/SettingsPane/SettingsPane"; import { useSelectedNode } from "Explorer/useSelectedNode"; import { scheduleRefreshDatabaseResourceToken } from "Platform/Fabric/FabricUtil"; import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility"; +import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils"; import { getNetworkSettingsWarningMessage } from "Utils/NetworkUtility"; import { logConsoleError } from "Utils/NotificationConsoleUtils"; import { useQueryCopilot } from "hooks/useQueryCopilot"; @@ -760,11 +761,17 @@ async function updateContextForSampleData(explorer: Explorer): Promise { return; } - const sampleDatabaseEndpoint = useQueryCopilot.getState().copilotUserDBEnabled - ? `/api/tokens/sampledataconnection/v2` - : `/api/tokens/sampledataconnection`; + let url: string; + if (useNewPortalBackendEndpoint(Constants.BackendApi.SampleData)) { + url = createUri(configContext.PORTAL_BACKEND_ENDPOINT, "/api/sampledata"); + } else { + const sampleDatabaseEndpoint = useQueryCopilot.getState().copilotUserDBEnabled + ? `/api/tokens/sampledataconnection/v2` + : `/api/tokens/sampledataconnection`; + + url = createUri(`${configContext.BACKEND_ENDPOINT}`, sampleDatabaseEndpoint); + } - const url = createUri(`${configContext.BACKEND_ENDPOINT}`, sampleDatabaseEndpoint); const authorizationHeader = getAuthorizationHeader(); const headers = { [authorizationHeader.header]: authorizationHeader.token };