mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-23 02:41:39 +00:00
Compare commits
4 Commits
master
...
new-access
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31ff90e2f9 | ||
|
|
fe0457bcb0 | ||
|
|
9c1d2a300e | ||
|
|
81a4c8039b |
@@ -52,12 +52,15 @@ export const createDatabaseContextMenu = (container: Explorer, databaseId: strin
|
||||
if (userContext.apiType !== "Tables" || userContext.features.enableSDKoperations) {
|
||||
items.push({
|
||||
iconSrc: DeleteDatabaseIcon,
|
||||
onClick: () =>
|
||||
onClick: (lastFocusedElement?: React.RefObject<HTMLElement>) =>
|
||||
useSidePanel
|
||||
.getState()
|
||||
.openSidePanel(
|
||||
"Delete " + getDatabaseName(),
|
||||
<DeleteDatabaseConfirmationPanel refreshDatabases={() => container.refreshAllDatabases()} />,
|
||||
<DeleteDatabaseConfirmationPanel
|
||||
lastFocusedElement={lastFocusedElement}
|
||||
refreshDatabases={() => container.refreshAllDatabases()}
|
||||
/>,
|
||||
),
|
||||
label: `Delete ${getDatabaseName()}`,
|
||||
styleClass: "deleteDatabaseMenuItem",
|
||||
@@ -132,13 +135,16 @@ export const createCollectionContextMenuButton = (
|
||||
if (configContext.platform !== Platform.Fabric) {
|
||||
items.push({
|
||||
iconSrc: DeleteCollectionIcon,
|
||||
onClick: () => {
|
||||
onClick: (lastFocusedElement?: React.RefObject<HTMLElement>) => {
|
||||
useSelectedNode.getState().setSelectedNode(selectedCollection);
|
||||
useSidePanel
|
||||
.getState()
|
||||
.openSidePanel(
|
||||
"Delete " + getCollectionName(),
|
||||
<DeleteCollectionConfirmationPane refreshDatabases={() => container.refreshAllDatabases()} />,
|
||||
<DeleteCollectionConfirmationPane
|
||||
lastFocusedElement={lastFocusedElement}
|
||||
refreshDatabases={() => container.refreshAllDatabases()}
|
||||
/>,
|
||||
);
|
||||
},
|
||||
label: `Delete ${getCollectionName()}`,
|
||||
|
||||
@@ -21,7 +21,7 @@ import { useCallback } from "react";
|
||||
|
||||
export interface TreeNodeMenuItem {
|
||||
label: string;
|
||||
onClick: () => void;
|
||||
onClick: (value?: React.RefObject<HTMLElement>) => void;
|
||||
iconSrc?: string;
|
||||
isDisabled?: boolean;
|
||||
styleClass?: string;
|
||||
@@ -73,6 +73,7 @@ export const TreeNodeComponent: React.FC<TreeNodeComponentProps> = ({
|
||||
treeNodeId,
|
||||
}: TreeNodeComponentProps): JSX.Element => {
|
||||
const [isLoading, setIsLoading] = React.useState<boolean>(false);
|
||||
const contextMenuRef = React.useRef<HTMLButtonElement>(null);
|
||||
|
||||
const getSortedChildren = (treeNode: TreeNode): TreeNode[] => {
|
||||
if (!treeNode || !treeNode.children) {
|
||||
@@ -139,7 +140,7 @@ export const TreeNodeComponent: React.FC<TreeNodeComponentProps> = ({
|
||||
data-test={`TreeNode/ContextMenuItem:${menuItem.label}`}
|
||||
disabled={menuItem.isDisabled}
|
||||
key={menuItem.label}
|
||||
onClick={menuItem.onClick}
|
||||
onClick={() => menuItem.onClick(contextMenuRef)}
|
||||
>
|
||||
{menuItem.label}
|
||||
</MenuItem>
|
||||
@@ -163,6 +164,7 @@ export const TreeNodeComponent: React.FC<TreeNodeComponentProps> = ({
|
||||
aria-label="More options"
|
||||
data-test="TreeNode/ContextMenuTrigger"
|
||||
appearance="subtle"
|
||||
ref={contextMenuRef}
|
||||
icon={<MoreHorizontal20Regular />}
|
||||
/>
|
||||
</MenuTrigger>
|
||||
|
||||
@@ -1560,14 +1560,14 @@ exports[`TreeNodeComponent renders a node with a menu 1`] = `
|
||||
<MenuList>
|
||||
<MenuItem
|
||||
data-test="TreeNode/ContextMenuItem:enabledItem"
|
||||
onClick={[MockFunction enabledItemClick]}
|
||||
onClick={[Function]}
|
||||
>
|
||||
enabledItem
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
data-test="TreeNode/ContextMenuItem:disabledItem"
|
||||
disabled={true}
|
||||
onClick={[MockFunction disabledItemClick]}
|
||||
onClick={[Function]}
|
||||
>
|
||||
disabledItem
|
||||
</MenuItem>
|
||||
@@ -1604,7 +1604,7 @@ exports[`TreeNodeComponent renders a node with a menu 1`] = `
|
||||
<MenuItem
|
||||
data-test="TreeNode/ContextMenuItem:enabledItem"
|
||||
key="enabledItem"
|
||||
onClick={[MockFunction enabledItemClick]}
|
||||
onClick={[Function]}
|
||||
>
|
||||
enabledItem
|
||||
</MenuItem>
|
||||
@@ -1612,7 +1612,7 @@ exports[`TreeNodeComponent renders a node with a menu 1`] = `
|
||||
data-test="TreeNode/ContextMenuItem:disabledItem"
|
||||
disabled={true}
|
||||
key="disabledItem"
|
||||
onClick={[MockFunction disabledItemClick]}
|
||||
onClick={[Function]}
|
||||
>
|
||||
disabledItem
|
||||
</MenuItem>
|
||||
|
||||
@@ -52,7 +52,9 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||
|
||||
describe("shouldRecordFeedback()", () => {
|
||||
it("should return true if last collection and database does not have shared throughput else false", () => {
|
||||
const wrapper = shallow(<DeleteCollectionConfirmationPane refreshDatabases={() => undefined} />);
|
||||
const wrapper = shallow(
|
||||
<DeleteCollectionConfirmationPane refreshDatabases={() => undefined} lastFocusedElement={undefined} />,
|
||||
);
|
||||
expect(wrapper.exists(".deleteCollectionFeedback")).toBe(false);
|
||||
|
||||
const database = { id: ko.observable("testDB") } as Database;
|
||||
@@ -109,7 +111,9 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||
});
|
||||
|
||||
it("should call delete collection", () => {
|
||||
const wrapper = mount(<DeleteCollectionConfirmationPane refreshDatabases={() => undefined} />);
|
||||
const wrapper = mount(
|
||||
<DeleteCollectionConfirmationPane refreshDatabases={() => undefined} lastFocusedElement={undefined} />,
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
expect(wrapper.exists("#confirmCollectionId")).toBe(true);
|
||||
@@ -126,7 +130,9 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||
});
|
||||
|
||||
it("should record feedback", async () => {
|
||||
const wrapper = mount(<DeleteCollectionConfirmationPane refreshDatabases={() => undefined} />);
|
||||
const wrapper = mount(
|
||||
<DeleteCollectionConfirmationPane refreshDatabases={() => undefined} lastFocusedElement={undefined} />,
|
||||
);
|
||||
expect(wrapper.exists("#confirmCollectionId")).toBe(true);
|
||||
wrapper
|
||||
.find("#confirmCollectionId")
|
||||
|
||||
@@ -12,17 +12,19 @@ import { getCollectionName } from "Utils/APITypeUtils";
|
||||
import * as NotificationConsoleUtils from "Utils/NotificationConsoleUtils";
|
||||
import { useSidePanel } from "hooks/useSidePanel";
|
||||
import { useTabs } from "hooks/useTabs";
|
||||
import React, { FunctionComponent, useState } from "react";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import { useDatabases } from "../../useDatabases";
|
||||
import { useSelectedNode } from "../../useSelectedNode";
|
||||
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
||||
|
||||
export interface DeleteCollectionConfirmationPaneProps {
|
||||
refreshDatabases: () => Promise<void>;
|
||||
lastFocusedElement: React.MutableRefObject<HTMLElement>;
|
||||
}
|
||||
|
||||
export const DeleteCollectionConfirmationPane: FunctionComponent<DeleteCollectionConfirmationPaneProps> = ({
|
||||
refreshDatabases,
|
||||
lastFocusedElement,
|
||||
}: DeleteCollectionConfirmationPaneProps) => {
|
||||
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
|
||||
const [deleteCollectionFeedback, setDeleteCollectionFeedback] = useState<string>("");
|
||||
@@ -35,7 +37,7 @@ export const DeleteCollectionConfirmationPane: FunctionComponent<DeleteCollectio
|
||||
|
||||
const collectionName = getCollectionName().toLocaleLowerCase();
|
||||
const paneTitle = "Delete " + collectionName;
|
||||
|
||||
const lastItemElement = lastFocusedElement?.current;
|
||||
const onSubmit = async (): Promise<void> => {
|
||||
const collection = useSelectedNode.getState().findSelectedCollection();
|
||||
if (!collection || inputCollectionName !== collection.id()) {
|
||||
@@ -111,6 +113,14 @@ export const DeleteCollectionConfirmationPane: FunctionComponent<DeleteCollectio
|
||||
};
|
||||
const confirmContainer = `Confirm by typing the ${collectionName.toLowerCase()} id`;
|
||||
const reasonInfo = `Help us improve Azure Cosmos DB! What is the reason why you are deleting this ${collectionName}?`;
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (lastItemElement) {
|
||||
lastItemElement.focus();
|
||||
}
|
||||
};
|
||||
}, [lastItemElement]);
|
||||
|
||||
return (
|
||||
<RightPaneForm {...props}>
|
||||
<div className="panelFormWrapper">
|
||||
|
||||
@@ -49,7 +49,9 @@ describe("Delete Database Confirmation Pane", () => {
|
||||
});
|
||||
|
||||
it("shouldRecordFeedback() should return true if last non empty database or is last database that has shared throughput", () => {
|
||||
const wrapper = shallow(<DeleteDatabaseConfirmationPanel refreshDatabases={() => undefined} />);
|
||||
const wrapper = shallow(
|
||||
<DeleteDatabaseConfirmationPanel refreshDatabases={() => undefined} lastFocusedElement={undefined} />,
|
||||
);
|
||||
expect(wrapper.exists(".deleteDatabaseFeedback")).toBe(true);
|
||||
|
||||
useDatabases.getState().addDatabases([database]);
|
||||
@@ -59,7 +61,9 @@ describe("Delete Database Confirmation Pane", () => {
|
||||
});
|
||||
|
||||
it("Should call delete database", () => {
|
||||
const wrapper = mount(<DeleteDatabaseConfirmationPanel refreshDatabases={() => undefined} />);
|
||||
const wrapper = mount(
|
||||
<DeleteDatabaseConfirmationPanel refreshDatabases={() => undefined} lastFocusedElement={undefined} />,
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
expect(wrapper.exists("#confirmDatabaseId")).toBe(true);
|
||||
|
||||
@@ -74,7 +78,9 @@ describe("Delete Database Confirmation Pane", () => {
|
||||
});
|
||||
|
||||
it("should record feedback", async () => {
|
||||
const wrapper = mount(<DeleteDatabaseConfirmationPanel refreshDatabases={() => undefined} />);
|
||||
const wrapper = mount(
|
||||
<DeleteDatabaseConfirmationPanel refreshDatabases={() => undefined} lastFocusedElement={undefined} />,
|
||||
);
|
||||
expect(wrapper.exists("#confirmDatabaseId")).toBe(true);
|
||||
wrapper
|
||||
.find("#confirmDatabaseId")
|
||||
|
||||
@@ -13,7 +13,7 @@ import { getDatabaseName } from "Utils/APITypeUtils";
|
||||
import { logConsoleError } from "Utils/NotificationConsoleUtils";
|
||||
import { useSidePanel } from "hooks/useSidePanel";
|
||||
import { useTabs } from "hooks/useTabs";
|
||||
import React, { FunctionComponent, useState } from "react";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import { useDatabases } from "../useDatabases";
|
||||
import { useSelectedNode } from "../useSelectedNode";
|
||||
import { PanelInfoErrorComponent, PanelInfoErrorProps } from "./PanelInfoErrorComponent";
|
||||
@@ -21,10 +21,12 @@ import { RightPaneForm, RightPaneFormProps } from "./RightPaneForm/RightPaneForm
|
||||
|
||||
interface DeleteDatabaseConfirmationPanelProps {
|
||||
refreshDatabases: () => Promise<void>;
|
||||
lastFocusedElement: React.MutableRefObject<HTMLElement>;
|
||||
}
|
||||
|
||||
export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseConfirmationPanelProps> = ({
|
||||
refreshDatabases,
|
||||
lastFocusedElement,
|
||||
}: DeleteDatabaseConfirmationPanelProps): JSX.Element => {
|
||||
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
|
||||
const isLastNonEmptyDatabase = useDatabases((state) => state.isLastNonEmptyDatabase);
|
||||
@@ -34,7 +36,7 @@ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseCo
|
||||
const [databaseInput, setDatabaseInput] = useState<string>("");
|
||||
const [databaseFeedbackInput, setDatabaseFeedbackInput] = useState<string>("");
|
||||
const selectedDatabase: Database = useDatabases.getState().findSelectedDatabase();
|
||||
|
||||
const lastItemElement = lastFocusedElement?.current;
|
||||
const submit = async (): Promise<void> => {
|
||||
if (selectedDatabase?.id() && databaseInput !== selectedDatabase.id()) {
|
||||
setFormError(
|
||||
@@ -126,6 +128,13 @@ export const DeleteDatabaseConfirmationPanel: FunctionComponent<DeleteDatabaseCo
|
||||
};
|
||||
const confirmDatabase = `Confirm by typing the ${getDatabaseName()} id`;
|
||||
const reasonInfo = `Help us improve Azure Cosmos DB! What is the reason why you are deleting this ${getDatabaseName()}?`;
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (lastItemElement) {
|
||||
lastItemElement.focus();
|
||||
}
|
||||
};
|
||||
}, [lastItemElement]);
|
||||
return (
|
||||
<RightPaneForm {...props}>
|
||||
{!formError && <PanelInfoErrorComponent {...errorProps} />}
|
||||
|
||||
Reference in New Issue
Block a user