mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-21 09:51:11 +00:00
Move databases to zustand (#898)
This commit is contained in:
@@ -31,6 +31,7 @@ import { getUpsellMessage } from "../../Utils/PricingUtils";
|
||||
import { CollapsibleSectionComponent } from "../Controls/CollapsiblePanel/CollapsibleSectionComponent";
|
||||
import { ThroughputInput } from "../Controls/ThroughputInput/ThroughputInput";
|
||||
import Explorer from "../Explorer";
|
||||
import { useDatabases } from "../useDatabases";
|
||||
import { PanelFooterComponent } from "./PanelFooterComponent";
|
||||
import { PanelInfoErrorComponent } from "./PanelInfoErrorComponent";
|
||||
import { PanelLoadingScreen } from "./PanelLoadingScreen";
|
||||
@@ -125,6 +126,8 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
const isFirstResourceCreated = useDatabases.getState().isFirstResourceCreated();
|
||||
|
||||
return (
|
||||
<form className="panelFormWrapper" onSubmit={this.submit.bind(this)}>
|
||||
{this.state.errorMessage && (
|
||||
@@ -137,7 +140,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
|
||||
{!this.state.errorMessage && this.isFreeTierAccount() && (
|
||||
<PanelInfoErrorComponent
|
||||
message={getUpsellMessage(userContext.portalEnv, true, this.props.explorer.isFirstResourceCreated(), true)}
|
||||
message={getUpsellMessage(userContext.portalEnv, true, isFirstResourceCreated, true)}
|
||||
messageType="info"
|
||||
showErrorDetails={false}
|
||||
link={Constants.Urls.freeTierInformation}
|
||||
@@ -240,9 +243,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
|
||||
{!isServerlessAccount() && this.state.isSharedThroughputChecked && (
|
||||
<ThroughputInput
|
||||
showFreeTierExceedThroughputTooltip={
|
||||
this.isFreeTierAccount() && !this.props.explorer.isFirstResourceCreated()
|
||||
}
|
||||
showFreeTierExceedThroughputTooltip={this.isFreeTierAccount() && !isFirstResourceCreated}
|
||||
isDatabase={true}
|
||||
isSharded={this.state.isSharded}
|
||||
setThroughputValue={(throughput: number) => (this.newDatabaseThroughput = throughput)}
|
||||
@@ -469,9 +470,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
|
||||
{this.shouldShowCollectionThroughputInput() && (
|
||||
<ThroughputInput
|
||||
showFreeTierExceedThroughputTooltip={
|
||||
this.isFreeTierAccount() && !this.props.explorer.isFirstResourceCreated()
|
||||
}
|
||||
showFreeTierExceedThroughputTooltip={this.isFreeTierAccount() && !isFirstResourceCreated}
|
||||
isDatabase={false}
|
||||
isSharded={this.state.isSharded}
|
||||
setThroughputValue={(throughput: number) => (this.collectionThroughput = throughput)}
|
||||
@@ -680,7 +679,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
}
|
||||
|
||||
private getDatabaseOptions(): IDropdownOption[] {
|
||||
return this.props.explorer?.databases()?.map((database) => ({
|
||||
return useDatabases.getState().databases?.map((database) => ({
|
||||
key: database.id(),
|
||||
text: database.id(),
|
||||
}));
|
||||
@@ -772,9 +771,9 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
||||
return false;
|
||||
}
|
||||
|
||||
const selectedDatabase = this.props.explorer
|
||||
.databases()
|
||||
?.find((database) => database.id() === this.state.selectedDatabaseId);
|
||||
const selectedDatabase = useDatabases
|
||||
.getState()
|
||||
.databases?.find((database) => database.id() === this.state.selectedDatabaseId);
|
||||
return !!selectedDatabase?.offer();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import { isServerlessAccount } from "../../../Utils/CapabilityUtils";
|
||||
import { getUpsellMessage } from "../../../Utils/PricingUtils";
|
||||
import { ThroughputInput } from "../../Controls/ThroughputInput/ThroughputInput";
|
||||
import Explorer from "../../Explorer";
|
||||
import { useDatabases } from "../../useDatabases";
|
||||
import { PanelInfoErrorComponent } from "../PanelInfoErrorComponent";
|
||||
import { getTextFieldStyles } from "../PanelStyles";
|
||||
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
||||
@@ -172,7 +173,12 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
<RightPaneForm {...props}>
|
||||
{!formErrors && isFreeTierAccount && (
|
||||
<PanelInfoErrorComponent
|
||||
message={getUpsellMessage(userContext.portalEnv, true, container.isFirstResourceCreated(), true)}
|
||||
message={getUpsellMessage(
|
||||
userContext.portalEnv,
|
||||
true,
|
||||
useDatabases.getState().isFirstResourceCreated(),
|
||||
true
|
||||
)}
|
||||
messageType="info"
|
||||
showErrorDetails={false}
|
||||
link={Constants.Urls.freeTierInformation}
|
||||
@@ -225,7 +231,7 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
|
||||
{!isServerlessAccount() && databaseCreateNewShared && (
|
||||
<ThroughputInput
|
||||
showFreeTierExceedThroughputTooltip={isFreeTierAccount && !container?.isFirstResourceCreated()}
|
||||
showFreeTierExceedThroughputTooltip={isFreeTierAccount && !useDatabases.getState().isFirstResourceCreated()}
|
||||
isDatabase={true}
|
||||
isSharded={databaseCreateNewShared}
|
||||
setThroughputValue={(newThroughput: number) => (throughput = newThroughput)}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { mount } from "enzyme";
|
||||
import * as ko from "knockout";
|
||||
import React from "react";
|
||||
import { SavedQueries } from "../../../Common/Constants";
|
||||
import { QueriesClient } from "../../../Common/QueriesClient";
|
||||
import { Query } from "../../../Contracts/DataModels";
|
||||
import { Collection, Database } from "../../../Contracts/ViewModels";
|
||||
import Explorer from "../../Explorer";
|
||||
import { useDatabases } from "../../useDatabases";
|
||||
import { BrowseQueriesPane } from "./BrowseQueriesPane";
|
||||
|
||||
describe("Browse queries panel", () => {
|
||||
const fakeExplorer = {} as Explorer;
|
||||
fakeExplorer.canSaveQueries = ko.computed<boolean>(() => true);
|
||||
const fakeClientQuery = {} as QueriesClient;
|
||||
const fakeQueryData = [] as Query[];
|
||||
fakeClientQuery.getQueries = async () => fakeQueryData;
|
||||
@@ -17,6 +19,16 @@ describe("Browse queries panel", () => {
|
||||
explorer: fakeExplorer,
|
||||
closePanel: (): void => undefined,
|
||||
};
|
||||
useDatabases.getState().addDatabases([
|
||||
{
|
||||
id: ko.observable(SavedQueries.DatabaseName),
|
||||
collections: ko.observableArray([
|
||||
{
|
||||
id: ko.observable(SavedQueries.CollectionName),
|
||||
} as Collection,
|
||||
]),
|
||||
} as Database,
|
||||
]);
|
||||
|
||||
it("Should render Default properly", () => {
|
||||
const wrapper = mount(<BrowseQueriesPane {...props} />);
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from "../../Controls/QueriesGridReactComponent/QueriesGridComponent";
|
||||
import Explorer from "../../Explorer";
|
||||
import { NewQueryTab } from "../../Tabs/QueryTab/QueryTab";
|
||||
import { useDatabases } from "../../useDatabases";
|
||||
|
||||
interface BrowseQueriesPaneProps {
|
||||
explorer: Explorer;
|
||||
@@ -45,12 +46,13 @@ export const BrowseQueriesPane: FunctionComponent<BrowseQueriesPaneProps> = ({
|
||||
});
|
||||
closeSidePanel();
|
||||
};
|
||||
const isSaveQueryEnabled = useDatabases((state) => state.isSaveQueryEnabled);
|
||||
|
||||
const props: QueriesGridComponentProps = {
|
||||
queriesClient: explorer.queriesClient,
|
||||
onQuerySelect: loadSavedQuery,
|
||||
containerVisible: true,
|
||||
saveQueryEnabled: explorer.canSaveQueries(),
|
||||
saveQueryEnabled: isSaveQueryEnabled(),
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -5,7 +5,6 @@ exports[`Browse queries panel Should render Default properly 1`] = `
|
||||
closePanel={[Function]}
|
||||
explorer={
|
||||
Object {
|
||||
"canSaveQueries": [Function],
|
||||
"queriesClient": Object {
|
||||
"getQueries": [Function],
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ import { isServerlessAccount } from "../../../Utils/CapabilityUtils";
|
||||
import { ThroughputInput } from "../../Controls/ThroughputInput/ThroughputInput";
|
||||
import Explorer from "../../Explorer";
|
||||
import { CassandraAPIDataClient } from "../../Tables/TableDataClient";
|
||||
import { useDatabases } from "../../useDatabases";
|
||||
import { getTextFieldStyles } from "../PanelStyles";
|
||||
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
||||
|
||||
@@ -236,7 +237,7 @@ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectio
|
||||
styles={{ root: { width: 300 }, title: { fontSize: 12 }, dropdownItem: { fontSize: 12 } }}
|
||||
placeholder="Choose existing keyspace id"
|
||||
defaultSelectedKey={existingKeyspaceId}
|
||||
options={container?.databases()?.map((keyspace) => ({
|
||||
options={useDatabases.getState().databases?.map((keyspace) => ({
|
||||
key: keyspace.id(),
|
||||
text: keyspace.id(),
|
||||
data: {
|
||||
@@ -253,7 +254,9 @@ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectio
|
||||
|
||||
{!isServerlessAccount() && keyspaceCreateNew && isKeyspaceShared && (
|
||||
<ThroughputInput
|
||||
showFreeTierExceedThroughputTooltip={isFreeTierAccount && !container.isFirstResourceCreated()}
|
||||
showFreeTierExceedThroughputTooltip={
|
||||
isFreeTierAccount && !useDatabases.getState().isFirstResourceCreated()
|
||||
}
|
||||
isDatabase
|
||||
isSharded
|
||||
setThroughputValue={(throughput: number) => (newKeySpaceThroughput = throughput)}
|
||||
@@ -324,7 +327,7 @@ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectio
|
||||
)}
|
||||
{!isServerlessAccount() && (!isKeyspaceShared || dedicateTableThroughput) && (
|
||||
<ThroughputInput
|
||||
showFreeTierExceedThroughputTooltip={isFreeTierAccount && !container.isFirstResourceCreated()}
|
||||
showFreeTierExceedThroughputTooltip={isFreeTierAccount && !useDatabases.getState().isFirstResourceCreated()}
|
||||
isDatabase={false}
|
||||
isSharded={false}
|
||||
setThroughputValue={(throughput: number) => (tableThroughput = throughput)}
|
||||
|
||||
@@ -11,44 +11,42 @@ import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryCons
|
||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { updateUserContext } from "../../../UserContext";
|
||||
import Explorer from "../../Explorer";
|
||||
import { useDatabases } from "../../useDatabases";
|
||||
import { DeleteCollectionConfirmationPane } from "./DeleteCollectionConfirmationPane";
|
||||
|
||||
describe("Delete Collection Confirmation Pane", () => {
|
||||
describe("Explorer.isLastCollection()", () => {
|
||||
let explorer: Explorer;
|
||||
|
||||
beforeEach(() => {
|
||||
explorer = new Explorer();
|
||||
});
|
||||
describe("useDatabases.isLastCollection()", () => {
|
||||
beforeAll(() => useDatabases.getState().clearDatabases());
|
||||
afterEach(() => useDatabases.getState().clearDatabases());
|
||||
|
||||
it("should be true if 1 database and 1 collection", () => {
|
||||
const database = {} as Database;
|
||||
database.collections = ko.observableArray<Collection>([{} as Collection]);
|
||||
explorer.databases = ko.observableArray<Database>([database]);
|
||||
expect(explorer.isLastCollection()).toBe(true);
|
||||
const database = { id: ko.observable("testDB") } as Database;
|
||||
database.collections = ko.observableArray<Collection>([{ id: ko.observable("testCollection") } as Collection]);
|
||||
useDatabases.getState().addDatabases([database]);
|
||||
expect(useDatabases.getState().isLastCollection()).toBe(true);
|
||||
});
|
||||
|
||||
it("should be false if if 1 database and 2 collection", () => {
|
||||
const database = {} as Database;
|
||||
database.collections = ko.observableArray<Collection>([{} as Collection, {} as Collection]);
|
||||
explorer.databases = ko.observableArray<Database>([database]);
|
||||
expect(explorer.isLastCollection()).toBe(false);
|
||||
const database = { id: ko.observable("testDB") } as Database;
|
||||
database.collections = ko.observableArray<Collection>([
|
||||
{ id: ko.observable("coll1") } as Collection,
|
||||
{ id: ko.observable("coll2") } as Collection,
|
||||
]);
|
||||
useDatabases.getState().addDatabases([database]);
|
||||
expect(useDatabases.getState().isLastCollection()).toBe(false);
|
||||
});
|
||||
|
||||
it("should be false if 2 database and 1 collection each", () => {
|
||||
const database = {} as Database;
|
||||
database.collections = ko.observableArray<Collection>([{} as Collection]);
|
||||
const database2 = {} as Database;
|
||||
database2.collections = ko.observableArray<Collection>([{} as Collection]);
|
||||
explorer.databases = ko.observableArray<Database>([database, database2]);
|
||||
expect(explorer.isLastCollection()).toBe(false);
|
||||
const database = { id: ko.observable("testDB") } as Database;
|
||||
database.collections = ko.observableArray<Collection>([{ id: ko.observable("coll1") } as Collection]);
|
||||
const database2 = { id: ko.observable("testDB2") } as Database;
|
||||
database2.collections = ko.observableArray<Collection>([{ id: ko.observable("coll2") } as Collection]);
|
||||
useDatabases.getState().addDatabases([database, database2]);
|
||||
expect(useDatabases.getState().isLastCollection()).toBe(false);
|
||||
});
|
||||
|
||||
it("should be false if 0 databases", () => {
|
||||
const database = {} as Database;
|
||||
explorer.databases = ko.observableArray<Database>();
|
||||
database.collections = ko.observableArray<Collection>();
|
||||
expect(explorer.isLastCollection()).toBe(false);
|
||||
expect(useDatabases.getState().isLastCollection()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,7 +54,6 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||
it("should return true if last collection and database does not have shared throughput else false", () => {
|
||||
const fakeExplorer = new Explorer();
|
||||
fakeExplorer.refreshAllDatabases = () => undefined;
|
||||
fakeExplorer.isLastCollection = () => true;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
|
||||
const props = {
|
||||
@@ -65,15 +62,15 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||
collectionName: "container",
|
||||
};
|
||||
const wrapper = shallow(<DeleteCollectionConfirmationPane {...props} />);
|
||||
expect(wrapper.exists(".deleteCollectionFeedback")).toBe(true);
|
||||
|
||||
props.explorer.isLastCollection = () => true;
|
||||
props.explorer.isSelectedDatabaseShared = () => true;
|
||||
wrapper.setProps(props);
|
||||
expect(wrapper.exists(".deleteCollectionFeedback")).toBe(false);
|
||||
|
||||
props.explorer.isLastCollection = () => false;
|
||||
props.explorer.isSelectedDatabaseShared = () => false;
|
||||
const database = { id: ko.observable("testDB") } as Database;
|
||||
database.collections = ko.observableArray<Collection>([{ id: ko.observable("testCollection") } as Collection]);
|
||||
useDatabases.getState().addDatabases([database]);
|
||||
wrapper.setProps(props);
|
||||
expect(wrapper.exists(".deleteCollectionFeedback")).toBe(true);
|
||||
|
||||
props.explorer.isSelectedDatabaseShared = () => true;
|
||||
wrapper.setProps(props);
|
||||
expect(wrapper.exists(".deleteCollectionFeedback")).toBe(false);
|
||||
});
|
||||
@@ -94,8 +91,10 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||
fakeExplorer.selectedCollectionId = ko.computed<string>(() => selectedCollectionId);
|
||||
fakeExplorer.selectedNode = ko.observable<TreeNode>();
|
||||
fakeExplorer.refreshAllDatabases = () => undefined;
|
||||
fakeExplorer.isLastCollection = () => true;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
const database = { id: ko.observable("testDB") } as Database;
|
||||
database.collections = ko.observableArray<Collection>([{ id: ko.observable("testCollection") } as Collection]);
|
||||
useDatabases.getState().addDatabases([database]);
|
||||
|
||||
beforeAll(() => {
|
||||
updateUserContext({
|
||||
|
||||
@@ -13,7 +13,9 @@ import { userContext } from "../../../UserContext";
|
||||
import { getCollectionName } from "../../../Utils/APITypeUtils";
|
||||
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
|
||||
import Explorer from "../../Explorer";
|
||||
import { useDatabases } from "../../useDatabases";
|
||||
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
||||
|
||||
export interface DeleteCollectionConfirmationPaneProps {
|
||||
explorer: Explorer;
|
||||
}
|
||||
@@ -22,13 +24,14 @@ export const DeleteCollectionConfirmationPane: FunctionComponent<DeleteCollectio
|
||||
explorer,
|
||||
}: DeleteCollectionConfirmationPaneProps) => {
|
||||
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
|
||||
const isLastCollection = useDatabases((state) => state.isLastCollection);
|
||||
const [deleteCollectionFeedback, setDeleteCollectionFeedback] = useState<string>("");
|
||||
const [inputCollectionName, setInputCollectionName] = useState<string>("");
|
||||
const [formError, setFormError] = useState<string>("");
|
||||
const [isExecuting, setIsExecuting] = useState(false);
|
||||
|
||||
const shouldRecordFeedback = (): boolean => {
|
||||
return explorer.isLastCollection() && !explorer.isSelectedDatabaseShared();
|
||||
return isLastCollection() && !explorer.isSelectedDatabaseShared();
|
||||
};
|
||||
const collectionName = getCollectionName().toLocaleLowerCase();
|
||||
const paneTitle = "Delete " + collectionName;
|
||||
|
||||
@@ -7,7 +7,6 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
|
||||
explorer={
|
||||
Object {
|
||||
"findSelectedCollection": [Function],
|
||||
"isLastCollection": [Function],
|
||||
"isSelectedDatabaseShared": [Function],
|
||||
"refreshAllDatabases": [Function],
|
||||
"selectedCollectionId": [Function],
|
||||
|
||||
@@ -11,19 +11,20 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { updateUserContext } from "../../UserContext";
|
||||
import Explorer from "../Explorer";
|
||||
import { TabsManager } from "../Tabs/TabsManager";
|
||||
import { useDatabases } from "../useDatabases";
|
||||
import { DeleteDatabaseConfirmationPanel } from "./DeleteDatabaseConfirmationPanel";
|
||||
|
||||
describe("Delete Database Confirmation Pane", () => {
|
||||
describe("shouldRecordFeedback()", () => {
|
||||
it("should return true if last non empty database or is last database that has shared throughput, else false", () => {
|
||||
const fakeExplorer = new Explorer();
|
||||
const fakeExplorer = {} as Explorer;
|
||||
fakeExplorer.refreshAllDatabases = () => undefined;
|
||||
fakeExplorer.isLastCollection = () => true;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
|
||||
const database = {} as Database;
|
||||
database.collections = ko.observableArray<Collection>([{} as Collection]);
|
||||
database.id = ko.observable<string>("testDatabse");
|
||||
database.collections = ko.observableArray<Collection>([{ id: ko.observable("testCollection") } as Collection]);
|
||||
database.id = ko.observable<string>("testDatabase");
|
||||
|
||||
const props = {
|
||||
explorer: fakeExplorer,
|
||||
@@ -33,29 +34,26 @@ describe("Delete Database Confirmation Pane", () => {
|
||||
};
|
||||
|
||||
const wrapper = shallow(<DeleteDatabaseConfirmationPanel {...props} />);
|
||||
props.explorer.isLastNonEmptyDatabase = () => true;
|
||||
expect(wrapper.exists(".deleteDatabaseFeedback")).toBe(false);
|
||||
|
||||
useDatabases.getState().addDatabases([database]);
|
||||
|
||||
wrapper.setProps(props);
|
||||
expect(wrapper.exists(".deleteDatabaseFeedback")).toBe(true);
|
||||
|
||||
props.explorer.isLastNonEmptyDatabase = () => false;
|
||||
props.explorer.isLastDatabase = () => false;
|
||||
wrapper.setProps(props);
|
||||
expect(wrapper.exists(".deleteDatabaseFeedback")).toBe(false);
|
||||
|
||||
props.explorer.isLastNonEmptyDatabase = () => false;
|
||||
props.explorer.isLastDatabase = () => true;
|
||||
props.explorer.isSelectedDatabaseShared = () => false;
|
||||
wrapper.setProps(props);
|
||||
expect(wrapper.exists(".deleteDatabaseFeedback")).toBe(false);
|
||||
useDatabases.getState().clearDatabases();
|
||||
});
|
||||
});
|
||||
|
||||
describe("submit()", () => {
|
||||
const selectedDatabaseId = "testDatabse";
|
||||
const fakeExplorer = new Explorer();
|
||||
const database = { id: ko.observable("testDatabase") } as Database;
|
||||
database.collections = ko.observableArray<Collection>([{ id: ko.observable("testCollection") } as Collection]);
|
||||
database.id = ko.observable<string>(selectedDatabaseId);
|
||||
const fakeExplorer = {} as Explorer;
|
||||
fakeExplorer.refreshAllDatabases = () => undefined;
|
||||
fakeExplorer.isLastCollection = () => true;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
fakeExplorer.tabsManager = new TabsManager();
|
||||
fakeExplorer.selectedNode = ko.observable();
|
||||
|
||||
let wrapper: ReactWrapper;
|
||||
beforeAll(() => {
|
||||
@@ -71,13 +69,10 @@ describe("Delete Database Confirmation Pane", () => {
|
||||
});
|
||||
(deleteDatabase as jest.Mock).mockResolvedValue(undefined);
|
||||
(TelemetryProcessor.trace as jest.Mock).mockReturnValue(undefined);
|
||||
useDatabases.getState().addDatabases([database]);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
const database = {} as Database;
|
||||
database.collections = ko.observableArray<Collection>([{} as Collection]);
|
||||
database.id = ko.observable<string>(selectedDatabaseId);
|
||||
|
||||
const props = {
|
||||
explorer: fakeExplorer,
|
||||
closePanel: (): void => undefined,
|
||||
@@ -86,10 +81,10 @@ describe("Delete Database Confirmation Pane", () => {
|
||||
};
|
||||
|
||||
wrapper = mount(<DeleteDatabaseConfirmationPanel {...props} />);
|
||||
props.explorer.isLastNonEmptyDatabase = () => true;
|
||||
wrapper.setProps(props);
|
||||
});
|
||||
|
||||
afterAll(() => useDatabases.getState().clearDatabases());
|
||||
|
||||
it("Should call delete database", () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.exists("#confirmDatabaseId")).toBe(true);
|
||||
|
||||
@@ -13,6 +13,7 @@ import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { userContext } from "../../UserContext";
|
||||
import { logConsoleError } from "../../Utils/NotificationConsoleUtils";
|
||||
import Explorer from "../Explorer";
|
||||
import { useDatabases } from "../useDatabases";
|
||||
import { PanelInfoErrorComponent, PanelInfoErrorProps } from "./PanelInfoErrorComponent";
|
||||
import { RightPaneForm, RightPaneFormProps } from "./RightPaneForm/RightPaneForm";
|
||||
|
||||
@@ -26,6 +27,7 @@ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseCo
|
||||
selectedDatabase,
|
||||
}: DeleteDatabaseConfirmationPanelProps): JSX.Element => {
|
||||
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
|
||||
const isLastNonEmptyDatabase = useDatabases((state) => state.isLastNonEmptyDatabase);
|
||||
const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false);
|
||||
|
||||
const [formError, setFormError] = useState<string>("");
|
||||
@@ -70,7 +72,7 @@ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseCo
|
||||
startKey
|
||||
);
|
||||
|
||||
if (shouldRecordFeedback()) {
|
||||
if (isLastNonEmptyDatabase()) {
|
||||
const deleteFeedback = new DeleteFeedback(
|
||||
userContext?.databaseAccount.id,
|
||||
userContext?.databaseAccount.name,
|
||||
@@ -100,10 +102,6 @@ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseCo
|
||||
}
|
||||
};
|
||||
|
||||
const shouldRecordFeedback = (): boolean => {
|
||||
return explorer.isLastNonEmptyDatabase() || (explorer.isLastDatabase() && explorer.isSelectedDatabaseShared());
|
||||
};
|
||||
|
||||
const props: RightPaneFormProps = {
|
||||
formError,
|
||||
isExecuting: isLoading,
|
||||
@@ -134,7 +132,7 @@ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseCo
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{shouldRecordFeedback() && (
|
||||
{isLastNonEmptyDatabase() && (
|
||||
<div className="deleteDatabaseFeedback">
|
||||
<Text variant="small" block>
|
||||
Help us improve Azure Cosmos DB!
|
||||
|
||||
@@ -19,8 +19,6 @@ exports[`GitHub Repos Panel should render Default properly 1`] = `
|
||||
"container": Explorer {
|
||||
"_isInitializingNotebooks": false,
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
"canSaveQueries": [Function],
|
||||
"databases": [Function],
|
||||
"isAccountReady": [Function],
|
||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||
"isNotebookEnabled": [Function],
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
import { shallow } from "enzyme";
|
||||
import * as ko from "knockout";
|
||||
import React from "react";
|
||||
import { SavedQueries } from "../../../Common/Constants";
|
||||
import { Collection, Database } from "../../../Contracts/ViewModels";
|
||||
import Explorer from "../../Explorer";
|
||||
import { useDatabases } from "../../useDatabases";
|
||||
import { SaveQueryPane } from "./SaveQueryPane";
|
||||
|
||||
describe("Save Query Pane", () => {
|
||||
const fakeExplorer = {} as Explorer;
|
||||
fakeExplorer.canSaveQueries = ko.computed<boolean>(() => true);
|
||||
|
||||
const props = {
|
||||
explorer: fakeExplorer,
|
||||
closePanel: (): void => undefined,
|
||||
};
|
||||
|
||||
const wrapper = shallow(<SaveQueryPane {...props} />);
|
||||
|
||||
it("should return true if can save Queries else false", () => {
|
||||
fakeExplorer.canSaveQueries = ko.computed<boolean>(() => true);
|
||||
wrapper.setProps(props);
|
||||
expect(wrapper.exists("#saveQueryInput")).toBe(true);
|
||||
|
||||
fakeExplorer.canSaveQueries = ko.computed<boolean>(() => false);
|
||||
wrapper.setProps(props);
|
||||
expect(wrapper.exists("#saveQueryInput")).toBe(false);
|
||||
});
|
||||
|
||||
it("should render Default properly", () => {
|
||||
const wrapper = shallow(<SaveQueryPane {...props} />);
|
||||
expect(wrapper.exists("#saveQueryInput")).toBe(false);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should return true if can save Queries else false", () => {
|
||||
useDatabases.getState().addDatabases([
|
||||
{
|
||||
id: ko.observable(SavedQueries.DatabaseName),
|
||||
collections: ko.observableArray([
|
||||
{
|
||||
id: ko.observable(SavedQueries.CollectionName),
|
||||
} as Collection,
|
||||
]),
|
||||
} as Database,
|
||||
]);
|
||||
const wrapper = shallow(<SaveQueryPane {...props} />);
|
||||
expect(wrapper.exists("#saveQueryInput")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import { traceFailure, traceStart, traceSuccess } from "../../../Shared/Telemetr
|
||||
import { logConsoleError } from "../../../Utils/NotificationConsoleUtils";
|
||||
import Explorer from "../../Explorer";
|
||||
import { NewQueryTab } from "../../Tabs/QueryTab/QueryTab";
|
||||
import { useDatabases } from "../../useDatabases";
|
||||
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
||||
|
||||
interface SaveQueryPaneProps {
|
||||
@@ -24,11 +25,11 @@ export const SaveQueryPane: FunctionComponent<SaveQueryPaneProps> = ({ explorer
|
||||
|
||||
const setupSaveQueriesText = `For compliance reasons, we save queries in a container in your Azure Cosmos account, in a separate database called “${SavedQueries.DatabaseName}”. To proceed, we need to create a container in your account, estimated additional cost is $0.77 daily.`;
|
||||
const title = "Save Query";
|
||||
const { canSaveQueries } = explorer;
|
||||
const isSaveQueryEnabled = useDatabases((state) => state.isSaveQueryEnabled);
|
||||
|
||||
const submit = async (): Promise<void> => {
|
||||
setFormError("");
|
||||
if (!canSaveQueries()) {
|
||||
if (!isSaveQueryEnabled()) {
|
||||
setFormError("Cannot save query");
|
||||
logConsoleError("Failed to save query: account not setup to save queries");
|
||||
}
|
||||
@@ -129,16 +130,16 @@ export const SaveQueryPane: FunctionComponent<SaveQueryPaneProps> = ({ explorer
|
||||
const props: RightPaneFormProps = {
|
||||
formError: formError,
|
||||
isExecuting: isLoading,
|
||||
submitButtonText: canSaveQueries() ? "Save" : "Complete setup",
|
||||
submitButtonText: isSaveQueryEnabled() ? "Save" : "Complete setup",
|
||||
onSubmit: () => {
|
||||
canSaveQueries() ? submit() : setupQueries();
|
||||
isSaveQueryEnabled() ? submit() : setupQueries();
|
||||
},
|
||||
};
|
||||
return (
|
||||
<RightPaneForm {...props}>
|
||||
<div className="panelFormWrapper">
|
||||
<div className="panelMainContent">
|
||||
{!canSaveQueries() ? (
|
||||
{!isSaveQueryEnabled() ? (
|
||||
<Text variant="small">{setupSaveQueriesText}</Text>
|
||||
) : (
|
||||
<TextField
|
||||
|
||||
@@ -9,8 +9,6 @@ exports[`StringInput Pane should render Create new directory properly 1`] = `
|
||||
Explorer {
|
||||
"_isInitializingNotebooks": false,
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
"canSaveQueries": [Function],
|
||||
"databases": [Function],
|
||||
"isAccountReady": [Function],
|
||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||
"isNotebookEnabled": [Function],
|
||||
|
||||
@@ -4,50 +4,10 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
<DeleteDatabaseConfirmationPanel
|
||||
closePanel={[Function]}
|
||||
explorer={
|
||||
Explorer {
|
||||
"_isInitializingNotebooks": false,
|
||||
"_resetNotebookWorkspace": [Function],
|
||||
"canSaveQueries": [Function],
|
||||
"databases": [Function],
|
||||
"isAccountReady": [Function],
|
||||
"isFixedCollectionWithSharedThroughputSupported": [Function],
|
||||
"isLastCollection": [Function],
|
||||
"isLastNonEmptyDatabase": [Function],
|
||||
"isNotebookEnabled": [Function],
|
||||
"isNotebooksEnabledForAccount": [Function],
|
||||
"isResourceTokenCollectionNodeSelected": [Function],
|
||||
"isSchemaEnabled": [Function],
|
||||
Object {
|
||||
"isSelectedDatabaseShared": [Function],
|
||||
"isShellEnabled": [Function],
|
||||
"isSynapseLinkUpdating": [Function],
|
||||
"isTabsContentExpanded": [Function],
|
||||
"memoryUsageInfo": [Function],
|
||||
"notebookBasePath": [Function],
|
||||
"notebookServerInfo": [Function],
|
||||
"onRefreshDatabasesKeyPress": [Function],
|
||||
"onRefreshResourcesClick": [Function],
|
||||
"provideFeedbackEmail": [Function],
|
||||
"queriesClient": QueriesClient {
|
||||
"container": [Circular],
|
||||
},
|
||||
"refreshAllDatabases": [Function],
|
||||
"refreshNotebookList": [Function],
|
||||
"resourceTokenCollection": [Function],
|
||||
"resourceTree": ResourceTreeAdapter {
|
||||
"container": [Circular],
|
||||
"copyNotebook": [Function],
|
||||
"databaseCollectionIdMap": Map {},
|
||||
"koSubsCollectionIdMap": Map {},
|
||||
"koSubsDatabaseIdMap": Map {},
|
||||
"parameters": [Function],
|
||||
},
|
||||
"resourceTreeForResourceToken": ResourceTreeAdapterForResourceToken {
|
||||
"container": [Circular],
|
||||
"parameters": [Function],
|
||||
},
|
||||
"selectedDatabaseId": [Function],
|
||||
"selectedNode": [Function],
|
||||
"sparkClusterConnectionInfo": [Function],
|
||||
"tabsManager": TabsManager {
|
||||
"activeTab": [Function],
|
||||
"openedTabs": [Function],
|
||||
@@ -749,7 +709,7 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
variant="small"
|
||||
>
|
||||
<span
|
||||
className="css-77"
|
||||
className="css-69"
|
||||
>
|
||||
Help us improve Azure Cosmos DB!
|
||||
</span>
|
||||
@@ -759,7 +719,7 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
variant="small"
|
||||
>
|
||||
<span
|
||||
className="css-77"
|
||||
className="css-69"
|
||||
>
|
||||
What is the reason why you are deleting this database?
|
||||
</span>
|
||||
@@ -1067,11 +1027,11 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
className="ms-TextField-wrapper"
|
||||
>
|
||||
<div
|
||||
className="ms-TextField-fieldGroup fieldGroup-78"
|
||||
className="ms-TextField-fieldGroup fieldGroup-70"
|
||||
>
|
||||
<textarea
|
||||
aria-invalid={false}
|
||||
className="ms-TextField-field field-79"
|
||||
className="ms-TextField-field field-71"
|
||||
id="deleteDatabaseFeedbackInput"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
@@ -2797,7 +2757,7 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
>
|
||||
<button
|
||||
aria-label="OK"
|
||||
className="ms-Button ms-Button--primary root-69"
|
||||
className="ms-Button ms-Button--primary root-73"
|
||||
data-is-focusable={true}
|
||||
id="sidePanelOkButton"
|
||||
onClick={[Function]}
|
||||
@@ -2809,16 +2769,16 @@ exports[`Delete Database Confirmation Pane submit() Should call delete database
|
||||
type="submit"
|
||||
>
|
||||
<span
|
||||
className="ms-Button-flexContainer flexContainer-70"
|
||||
className="ms-Button-flexContainer flexContainer-74"
|
||||
data-automationid="splitbuttonprimary"
|
||||
>
|
||||
<span
|
||||
className="ms-Button-textContainer textContainer-71"
|
||||
className="ms-Button-textContainer textContainer-75"
|
||||
>
|
||||
<span
|
||||
className="ms-Button-label label-73"
|
||||
id="id__3"
|
||||
key="id__3"
|
||||
className="ms-Button-label label-77"
|
||||
id="id__6"
|
||||
key="id__6"
|
||||
>
|
||||
OK
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user