mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-01-22 11:14:05 +00:00
Compare commits
1 Commits
master
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86a3cd6ae0 |
34
package-lock.json
generated
34
package-lock.json
generated
@@ -15191,6 +15191,8 @@
|
||||
},
|
||||
"node_modules/buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
@@ -17899,6 +17901,8 @@
|
||||
},
|
||||
"node_modules/ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
@@ -27702,21 +27706,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken/node_modules/jwa": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
||||
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz",
|
||||
"integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-equal-constant-time": "1.0.1",
|
||||
"buffer-equal-constant-time": "^1.0.1",
|
||||
"ecdsa-sig-formatter": "1.0.11",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken/node_modules/jws": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
|
||||
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz",
|
||||
"integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jwa": "^1.4.1",
|
||||
"jwa": "^1.4.2",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
@@ -27763,19 +27769,23 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jwa": {
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
|
||||
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-equal-constant-time": "1.0.1",
|
||||
"buffer-equal-constant-time": "^1.0.1",
|
||||
"ecdsa-sig-formatter": "1.0.11",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/jws": {
|
||||
"version": "4.0.0",
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
|
||||
"integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jwa": "^2.0.0",
|
||||
"jwa": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -516,7 +516,7 @@ describe("CopyJobActionMenu", () => {
|
||||
expect(screen.getByText("Cancel")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should disable complete action when job is being updated", () => {
|
||||
it("should handle complete action disabled state for online jobs", () => {
|
||||
const job = createMockJob({
|
||||
Status: CopyJobStatusType.InProgress,
|
||||
Mode: CopyJobMigrationType.Online,
|
||||
@@ -530,34 +530,8 @@ describe("CopyJobActionMenu", () => {
|
||||
const completeButton = screen.getByText("Complete");
|
||||
fireEvent.click(completeButton);
|
||||
|
||||
// Simulate dialog confirmation to trigger state update
|
||||
const [, , , onOkCallback] = mockShowOkCancelModalDialog.mock.calls[0];
|
||||
onOkCallback();
|
||||
|
||||
fireEvent.click(actionButton);
|
||||
const completeButtonAfterClick = screen.getByText("Complete").closest("button");
|
||||
expect(completeButtonAfterClick).toBeInTheDocument();
|
||||
expect(completeButtonAfterClick).toHaveAttribute("aria-disabled", "true");
|
||||
});
|
||||
|
||||
it("should disable complete action when any other action is being performed", () => {
|
||||
const job = createMockJob({
|
||||
Status: CopyJobStatusType.InProgress,
|
||||
Mode: CopyJobMigrationType.Online,
|
||||
});
|
||||
|
||||
render(<TestComponentWrapper job={job} />);
|
||||
|
||||
const actionButton = screen.getByRole("button", { name: "Actions" });
|
||||
fireEvent.click(actionButton);
|
||||
|
||||
const pauseButton = screen.getByText("Pause");
|
||||
fireEvent.click(pauseButton);
|
||||
fireEvent.click(actionButton);
|
||||
|
||||
const completeButtonAfterClick = screen.getByText("Complete").closest("button");
|
||||
expect(completeButtonAfterClick).toBeInTheDocument();
|
||||
expect(completeButtonAfterClick).toHaveAttribute("aria-disabled", "true");
|
||||
expect(screen.getByText("Complete")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ const CopyJobActionMenu: React.FC<CopyJobActionMenuProps> = ({ job, handleClick
|
||||
|
||||
const getMenuItems = (): IContextualMenuProps["items"] => {
|
||||
const isThisJobUpdating = updatingJobAction?.jobName === job.Name;
|
||||
const updatingAction = updatingJobAction?.action;
|
||||
|
||||
const baseItems = [
|
||||
{
|
||||
@@ -104,7 +105,7 @@ const CopyJobActionMenu: React.FC<CopyJobActionMenuProps> = ({ job, handleClick
|
||||
text: ContainerCopyMessages.MonitorJobs.Actions.complete,
|
||||
iconProps: { iconName: "CheckMark" },
|
||||
onClick: () => showActionConfirmationDialog(job, CopyJobActions.complete),
|
||||
disabled: isThisJobUpdating,
|
||||
disabled: isThisJobUpdating && updatingAction === CopyJobActions.complete,
|
||||
});
|
||||
}
|
||||
return filteredItems;
|
||||
|
||||
@@ -105,12 +105,9 @@ const App = (): JSX.Element => {
|
||||
// Scenario-based health tracking: start ApplicationLoad and complete phases.
|
||||
const { startScenario, completePhase } = useMetricScenario();
|
||||
React.useEffect(() => {
|
||||
// Only start scenario after config is initialized to avoid race conditions
|
||||
// with message handlers that depend on configContext.platform
|
||||
if (config) {
|
||||
startScenario(MetricScenario.ApplicationLoad);
|
||||
}
|
||||
}, [config, startScenario]);
|
||||
startScenario(MetricScenario.ApplicationLoad);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (explorer) {
|
||||
|
||||
88
src/NotebookViewer/NotebookViewer.tsx
Normal file
88
src/NotebookViewer/NotebookViewer.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import { initializeIcons } from "@fluentui/react";
|
||||
import "bootstrap/dist/css/bootstrap.css";
|
||||
import React from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
import { configContext, initializeConfiguration } from "../ConfigContext";
|
||||
import { GalleryHeaderComponent } from "../Explorer/Controls/Header/GalleryHeaderComponent";
|
||||
import { GalleryTab } from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent";
|
||||
import {
|
||||
NotebookViewerComponent,
|
||||
NotebookViewerComponentProps,
|
||||
} from "../Explorer/Controls/NotebookViewer/NotebookViewerComponent";
|
||||
import * as FileSystemUtil from "../Explorer/Notebook/FileSystemUtil";
|
||||
import { IGalleryItem, JunoClient } from "../Juno/JunoClient";
|
||||
import * as GalleryUtils from "../Utils/GalleryUtils";
|
||||
|
||||
const onInit = async () => {
|
||||
initializeIcons();
|
||||
await initializeConfiguration();
|
||||
const galleryViewerProps = GalleryUtils.getGalleryViewerProps(window.location.search);
|
||||
const notebookViewerProps = GalleryUtils.getNotebookViewerProps(window.location.search);
|
||||
let backNavigationText: string;
|
||||
let onBackClick: () => void;
|
||||
if (galleryViewerProps.selectedTab !== undefined) {
|
||||
backNavigationText = GalleryUtils.getTabTitle(galleryViewerProps.selectedTab);
|
||||
onBackClick = () =>
|
||||
(window.location.href = `${configContext.hostedExplorerURL}gallery.html?tab=${
|
||||
GalleryTab[galleryViewerProps.selectedTab]
|
||||
}`);
|
||||
}
|
||||
const hideInputs = notebookViewerProps.hideInputs;
|
||||
|
||||
const notebookUrl = decodeURIComponent(notebookViewerProps.notebookUrl);
|
||||
|
||||
const galleryItemId = notebookViewerProps.galleryItemId;
|
||||
let galleryItem: IGalleryItem;
|
||||
|
||||
if (galleryItemId) {
|
||||
const junoClient = new JunoClient();
|
||||
const galleryItemJunoResponse = await junoClient.getNotebookInfo(galleryItemId);
|
||||
galleryItem = galleryItemJunoResponse.data;
|
||||
}
|
||||
|
||||
// The main purpose of hiding the prompt is to hide everything when hiding inputs.
|
||||
// It is generally not very useful to just hide the prompt.
|
||||
const hidePrompts = hideInputs;
|
||||
|
||||
render(notebookUrl, backNavigationText, hideInputs, hidePrompts, galleryItem, onBackClick);
|
||||
};
|
||||
|
||||
const render = (
|
||||
notebookUrl: string,
|
||||
backNavigationText: string,
|
||||
hideInputs?: boolean,
|
||||
hidePrompts?: boolean,
|
||||
galleryItem?: IGalleryItem,
|
||||
onBackClick?: () => void,
|
||||
) => {
|
||||
const props: NotebookViewerComponentProps = {
|
||||
junoClient: galleryItem ? new JunoClient() : undefined,
|
||||
notebookUrl,
|
||||
galleryItem,
|
||||
backNavigationText,
|
||||
hideInputs,
|
||||
hidePrompts,
|
||||
onBackClick: onBackClick,
|
||||
onTagClick: undefined,
|
||||
};
|
||||
|
||||
if (galleryItem) {
|
||||
document.title = FileSystemUtil.stripExtension(galleryItem.name, "ipynb");
|
||||
}
|
||||
|
||||
const element = (
|
||||
<>
|
||||
<header>
|
||||
<GalleryHeaderComponent />
|
||||
</header>
|
||||
<div style={{ marginLeft: 120, marginRight: 120 }}>
|
||||
<NotebookViewerComponent {...props} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
ReactDOM.render(element, document.getElementById("notebookContent"));
|
||||
};
|
||||
|
||||
// Entry point
|
||||
window.addEventListener("load", onInit);
|
||||
@@ -10,7 +10,7 @@ let CONTAINER_ID: string;
|
||||
|
||||
// Set up test database and container with data before all tests
|
||||
test.beforeAll(async () => {
|
||||
testContainer = await createTestSQLContainer({ includeTestData: true });
|
||||
testContainer = await createTestSQLContainer(true);
|
||||
DATABASE_ID = testContainer.database.id;
|
||||
CONTAINER_ID = testContainer.container.id;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user