mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-10-13 23:38:45 +01:00
First dark theme commit for command bar
This commit is contained in:
parent
32576f50d3
commit
f2d6bbf54e
@ -5,7 +5,7 @@ import {
|
|||||||
TriggerDefinition,
|
TriggerDefinition,
|
||||||
UserDefinedFunctionDefinition,
|
UserDefinedFunctionDefinition,
|
||||||
} from "@azure/cosmos";
|
} from "@azure/cosmos";
|
||||||
import Explorer from "../Explorer/Explorer";
|
import type Explorer from "../Explorer/Explorer";
|
||||||
import { ConsoleData } from "../Explorer/Menus/NotificationConsole/ConsoleData";
|
import { ConsoleData } from "../Explorer/Menus/NotificationConsole/ConsoleData";
|
||||||
import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient";
|
import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient";
|
||||||
import ConflictId from "../Explorer/Tree/ConflictId";
|
import ConflictId from "../Explorer/Tree/ConflictId";
|
||||||
@ -462,3 +462,6 @@ export interface DropdownOption<T> {
|
|||||||
value: T;
|
value: T;
|
||||||
disable?: boolean;
|
disable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove the duplicate Explorer interface and export the type
|
||||||
|
export type { Explorer };
|
||||||
|
29
src/Explorer/DataExplorer.tsx
Normal file
29
src/Explorer/DataExplorer.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { makeStyles } from "@fluentui/react-components";
|
||||||
|
import React from "react";
|
||||||
|
import type { Explorer } from "../Contracts/ViewModels";
|
||||||
|
import { useTheme } from "../hooks/useTheme";
|
||||||
|
|
||||||
|
interface DataExplorerProps {
|
||||||
|
dataExplorer: Explorer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
root: {
|
||||||
|
backgroundColor: "var(--colorNeutralBackground1)",
|
||||||
|
color: "var(--colorNeutralForeground1)",
|
||||||
|
height: "100%",
|
||||||
|
width: "100%"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const DataExplorer: React.FC<DataExplorerProps> = ({ dataExplorer }) => {
|
||||||
|
const { isDarkMode } = useTheme();
|
||||||
|
const styles = useStyles();
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`dataExplorerContainer ${styles.root}`}>
|
||||||
|
<div>Data Explorer Content</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
37
src/Explorer/ErrorBoundary.tsx
Normal file
37
src/Explorer/ErrorBoundary.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import React, { Component, ErrorInfo, ReactNode } from "react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
hasError: boolean;
|
||||||
|
error: Error | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ErrorBoundary extends Component<Props, State> {
|
||||||
|
public state: State = {
|
||||||
|
hasError: false,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static getDerivedStateFromError(error: Error): State {
|
||||||
|
return { hasError: true, error };
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
return (
|
||||||
|
<div style={{ padding: "20px", color: "red" }}>
|
||||||
|
<h2>Something went wrong.</h2>
|
||||||
|
<details style={{ whiteSpace: "pre-wrap" }}>{this.state.error && this.state.error.toString()}</details>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,10 @@
|
|||||||
padding: @SmallSpace 0px @SmallSpace 0px;
|
padding: @SmallSpace 0px @SmallSpace 0px;
|
||||||
.flex-display();
|
.flex-display();
|
||||||
span {
|
span {
|
||||||
border-left: @ButtonBorderWidth solid @BaseMediumHigh;
|
|
||||||
margin: 0 10px 0 10px;
|
margin: 0 10px 0 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.commandBarContainer {
|
.commandBarContainer {
|
||||||
border-bottom: 1px solid @BaseMedium;
|
border-bottom: 1px solid var(--colorNeutralStroke1);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* and update any knockout observables passed from the parent.
|
* and update any knockout observables passed from the parent.
|
||||||
*/
|
*/
|
||||||
import { CommandBar as FluentCommandBar, ICommandBarItemProps } from "@fluentui/react";
|
import { CommandBar as FluentCommandBar, ICommandBarItemProps } from "@fluentui/react";
|
||||||
|
import { makeStyles, useFluent } from "@fluentui/react-components";
|
||||||
import { useNotebook } from "Explorer/Notebook/useNotebook";
|
import { useNotebook } from "Explorer/Notebook/useNotebook";
|
||||||
import { KeyboardActionGroup, useKeyboardActionGroup } from "KeyboardShortcuts";
|
import { KeyboardActionGroup, useKeyboardActionGroup } from "KeyboardShortcuts";
|
||||||
import { isFabric } from "Platform/Fabric/FabricUtil";
|
import { isFabric } from "Platform/Fabric/FabricUtil";
|
||||||
@ -11,7 +12,6 @@ import { userContext } from "UserContext";
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import create, { UseStore } from "zustand";
|
import create, { UseStore } from "zustand";
|
||||||
import { ConnectionStatusType, PoolIdType } from "../../../Common/Constants";
|
import { ConnectionStatusType, PoolIdType } from "../../../Common/Constants";
|
||||||
import { StyleConstants } from "../../../Common/StyleConstants";
|
|
||||||
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
|
||||||
import Explorer from "../../Explorer";
|
import Explorer from "../../Explorer";
|
||||||
import { useSelectedNode } from "../../useSelectedNode";
|
import { useSelectedNode } from "../../useSelectedNode";
|
||||||
@ -30,18 +30,26 @@ export interface CommandBarStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useCommandBar: UseStore<CommandBarStore> = create((set) => ({
|
export const useCommandBar: UseStore<CommandBarStore> = create((set) => ({
|
||||||
contextButtons: [],
|
contextButtons: [] as CommandButtonComponentProps[],
|
||||||
setContextButtons: (contextButtons: CommandButtonComponentProps[]) => set((state) => ({ ...state, contextButtons })),
|
setContextButtons: (contextButtons: CommandButtonComponentProps[]) => set((state) => ({ ...state, contextButtons })),
|
||||||
isHidden: false,
|
isHidden: false,
|
||||||
setIsHidden: (isHidden: boolean) => set((state) => ({ ...state, isHidden })),
|
setIsHidden: (isHidden: boolean) => set((state) => ({ ...state, isHidden })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
commandBarContainer: {
|
||||||
|
borderBottom: "1px solid var(--colorNeutralStroke1)"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export const CommandBar: React.FC<Props> = ({ container }: Props) => {
|
export const CommandBar: React.FC<Props> = ({ container }: Props) => {
|
||||||
const selectedNodeState = useSelectedNode();
|
const selectedNodeState = useSelectedNode();
|
||||||
const buttons = useCommandBar((state) => state.contextButtons);
|
const buttons = useCommandBar((state) => state.contextButtons);
|
||||||
const isHidden = useCommandBar((state) => state.isHidden);
|
const isHidden = useCommandBar((state) => state.isHidden);
|
||||||
const backgroundColor = StyleConstants.BaseLight;
|
const { targetDocument } = useFluent();
|
||||||
|
// const isDarkMode = targetDocument?.body.classList.contains("isDarkMode");
|
||||||
const setKeyboardHandlers = useKeyboardActionGroup(KeyboardActionGroup.COMMAND_BAR);
|
const setKeyboardHandlers = useKeyboardActionGroup(KeyboardActionGroup.COMMAND_BAR);
|
||||||
|
const styles = useStyles();
|
||||||
|
|
||||||
if (userContext.apiType === "Postgres" || userContext.apiType === "VCoreMongo") {
|
if (userContext.apiType === "Postgres" || userContext.apiType === "VCoreMongo") {
|
||||||
const buttons =
|
const buttons =
|
||||||
@ -49,12 +57,15 @@ export const CommandBar: React.FC<Props> = ({ container }: Props) => {
|
|||||||
? CommandBarComponentButtonFactory.createPostgreButtons(container)
|
? CommandBarComponentButtonFactory.createPostgreButtons(container)
|
||||||
: CommandBarComponentButtonFactory.createVCoreMongoButtons(container);
|
: CommandBarComponentButtonFactory.createVCoreMongoButtons(container);
|
||||||
return (
|
return (
|
||||||
<div className="commandBarContainer" style={{ display: isHidden ? "none" : "initial" }}>
|
<div className={styles.commandBarContainer} style={{ display: isHidden ? "none" : "initial" }}>
|
||||||
<FluentCommandBar
|
<FluentCommandBar
|
||||||
ariaLabel="Use left and right arrow keys to navigate between commands"
|
ariaLabel="Use left and right arrow keys to navigate between commands"
|
||||||
items={CommandBarUtil.convertButton(buttons, backgroundColor)}
|
items={CommandBarUtil.convertButton(buttons, "var(--colorNeutralBackground1)")}
|
||||||
styles={{
|
styles={{
|
||||||
root: { backgroundColor: backgroundColor },
|
root: {
|
||||||
|
backgroundColor: "var(--colorNeutralBackground1)",
|
||||||
|
color: "var(--colorNeutralForeground1)"
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
overflowButtonProps={{ ariaLabel: "More commands" }}
|
overflowButtonProps={{ ariaLabel: "More commands" }}
|
||||||
/>
|
/>
|
||||||
@ -68,18 +79,18 @@ export const CommandBar: React.FC<Props> = ({ container }: Props) => {
|
|||||||
);
|
);
|
||||||
const controlButtons = CommandBarComponentButtonFactory.createControlCommandBarButtons(container);
|
const controlButtons = CommandBarComponentButtonFactory.createControlCommandBarButtons(container);
|
||||||
|
|
||||||
const uiFabricStaticButtons = CommandBarUtil.convertButton(staticButtons, backgroundColor);
|
const uiFabricStaticButtons = CommandBarUtil.convertButton(staticButtons, "var(--colorNeutralBackground1)");
|
||||||
if (buttons && buttons.length > 0) {
|
if (buttons && buttons.length > 0) {
|
||||||
uiFabricStaticButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
|
uiFabricStaticButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
|
||||||
}
|
}
|
||||||
|
|
||||||
const uiFabricTabsButtons: ICommandBarItemProps[] = CommandBarUtil.convertButton(contextButtons, backgroundColor);
|
const uiFabricTabsButtons: ICommandBarItemProps[] = CommandBarUtil.convertButton(contextButtons, "var(--colorNeutralBackground1)");
|
||||||
|
|
||||||
if (uiFabricTabsButtons.length > 0) {
|
if (uiFabricTabsButtons.length > 0) {
|
||||||
uiFabricStaticButtons.push(CommandBarUtil.createDivider("commandBarDivider"));
|
uiFabricStaticButtons.push(CommandBarUtil.createDivider("commandBarDivider"));
|
||||||
}
|
}
|
||||||
|
|
||||||
const uiFabricControlButtons = CommandBarUtil.convertButton(controlButtons, backgroundColor);
|
const uiFabricControlButtons = CommandBarUtil.convertButton(controlButtons, "var(--colorNeutralBackground1)");
|
||||||
uiFabricControlButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
|
uiFabricControlButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
|
||||||
|
|
||||||
const connectionInfo = useNotebook((state) => state.connectionInfo);
|
const connectionInfo = useNotebook((state) => state.connectionInfo);
|
||||||
@ -96,14 +107,16 @@ export const CommandBar: React.FC<Props> = ({ container }: Props) => {
|
|||||||
const rootStyle = isFabric()
|
const rootStyle = isFabric()
|
||||||
? {
|
? {
|
||||||
root: {
|
root: {
|
||||||
backgroundColor: "transparent",
|
backgroundColor: "var(--colorNeutralBackground1)",
|
||||||
padding: "2px 8px 0px 8px",
|
padding: "2px 8px 0px 8px",
|
||||||
},
|
color: "var(--colorNeutralForeground1)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
root: {
|
root: {
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: "var(--colorNeutralBackground1)",
|
||||||
},
|
color: "var(--colorNeutralForeground1)"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const allButtons = staticButtons.concat(contextButtons).concat(controlButtons);
|
const allButtons = staticButtons.concat(contextButtons).concat(controlButtons);
|
||||||
@ -111,7 +124,7 @@ export const CommandBar: React.FC<Props> = ({ container }: Props) => {
|
|||||||
setKeyboardHandlers(keyboardHandlers);
|
setKeyboardHandlers(keyboardHandlers);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="commandBarContainer" style={{ display: isHidden ? "none" : "initial" }}>
|
<div className={styles.commandBarContainer} style={{ display: isHidden ? "none" : "initial" }}>
|
||||||
<FluentCommandBar
|
<FluentCommandBar
|
||||||
ariaLabel="Use left and right arrow keys to navigate between commands"
|
ariaLabel="Use left and right arrow keys to navigate between commands"
|
||||||
items={uiFabricStaticButtons.concat(uiFabricTabsButtons)}
|
items={uiFabricStaticButtons.concat(uiFabricTabsButtons)}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
Dropdown,
|
Dropdown,
|
||||||
ICommandBarItemProps,
|
ICommandBarItemProps,
|
||||||
IComponentAsProps,
|
IComponentAsProps,
|
||||||
IconType,
|
IconType,
|
||||||
IDropdownOption,
|
IDropdownOption,
|
||||||
IDropdownStyles,
|
IDropdownStyles,
|
||||||
} from "@fluentui/react";
|
} from "@fluentui/react";
|
||||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||||
import { KeyboardHandlerMap } from "KeyboardShortcuts";
|
import { KeyboardHandlerMap } from "KeyboardShortcuts";
|
||||||
@ -53,7 +53,7 @@ export const convertButton = (btns: CommandButtonComponentProps[], backgroundCol
|
|||||||
const result: ICommandBarItemProps = {
|
const result: ICommandBarItemProps = {
|
||||||
iconProps: {
|
iconProps: {
|
||||||
style: {
|
style: {
|
||||||
width: StyleConstants.CommandBarIconWidth, // 16
|
width: StyleConstants.CommandBarIconWidth,
|
||||||
alignSelf: btn.iconName ? "baseline" : undefined,
|
alignSelf: btn.iconName ? "baseline" : undefined,
|
||||||
filter: getFilter(btn.disabled),
|
filter: getFilter(btn.disabled),
|
||||||
},
|
},
|
||||||
@ -79,7 +79,7 @@ export const convertButton = (btns: CommandButtonComponentProps[], backgroundCol
|
|||||||
"data-test": `CommandBar/Button:${label}`,
|
"data-test": `CommandBar/Button:${label}`,
|
||||||
buttonStyles: {
|
buttonStyles: {
|
||||||
root: {
|
root: {
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: "var(--colorNeutralBackground1)",
|
||||||
height: buttonHeightPx,
|
height: buttonHeightPx,
|
||||||
paddingRight: 0,
|
paddingRight: 0,
|
||||||
paddingLeft: 0,
|
paddingLeft: 0,
|
||||||
@ -87,15 +87,29 @@ export const convertButton = (btns: CommandButtonComponentProps[], backgroundCol
|
|||||||
minWidth: 24,
|
minWidth: 24,
|
||||||
marginLeft: isSplit ? 0 : 5,
|
marginLeft: isSplit ? 0 : 5,
|
||||||
marginRight: isSplit ? 0 : 5,
|
marginRight: isSplit ? 0 : 5,
|
||||||
|
color: "var(--colorNeutralForeground1)",
|
||||||
|
selectors: {
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "var(--colorNeutralBackground1Hover)",
|
||||||
|
color: "var(--colorNeutralForeground1)"
|
||||||
|
},
|
||||||
|
"&:active": {
|
||||||
|
backgroundColor: "var(--colorNeutralBackground1Pressed)",
|
||||||
|
color: "var(--colorNeutralForeground1)"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
rootDisabled: {
|
rootDisabled: {
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: "var(--colorNeutralBackground1)",
|
||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
|
color: "var(--colorNeutralForegroundDisabled)"
|
||||||
},
|
},
|
||||||
splitButtonMenuButton: {
|
splitButtonMenuButton: {
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: "var(--colorNeutralBackground1)",
|
||||||
selectors: {
|
selectors: {
|
||||||
":hover": { backgroundColor: hoverColor },
|
":hover": {
|
||||||
|
backgroundColor: "var(--colorNeutralBackground1Hover)"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
width: 16,
|
width: 16,
|
||||||
},
|
},
|
||||||
@ -104,13 +118,22 @@ export const convertButton = (btns: CommandButtonComponentProps[], backgroundCol
|
|||||||
configContext.platform == Platform.Fabric
|
configContext.platform == Platform.Fabric
|
||||||
? StyleConstants.DefaultFontSize
|
? StyleConstants.DefaultFontSize
|
||||||
: StyleConstants.mediumFontSize,
|
: StyleConstants.mediumFontSize,
|
||||||
|
color: "var(--colorNeutralForeground1)"
|
||||||
|
},
|
||||||
|
rootHovered: {
|
||||||
|
backgroundColor: "var(--colorNeutralBackground1Hover)",
|
||||||
|
color: "var(--colorNeutralForeground1)"
|
||||||
|
},
|
||||||
|
rootPressed: {
|
||||||
|
backgroundColor: "var(--colorNeutralBackground1Pressed)",
|
||||||
|
color: "var(--colorNeutralForeground1)"
|
||||||
},
|
},
|
||||||
rootHovered: { backgroundColor: hoverColor },
|
|
||||||
rootPressed: { backgroundColor: hoverColor },
|
|
||||||
splitButtonMenuButtonExpanded: {
|
splitButtonMenuButtonExpanded: {
|
||||||
backgroundColor: StyleConstants.AccentExtra,
|
backgroundColor: "var(--colorNeutralBackground1Pressed)",
|
||||||
selectors: {
|
selectors: {
|
||||||
":hover": { backgroundColor: hoverColor },
|
":hover": {
|
||||||
|
backgroundColor: "var(--colorNeutralBackground1Hover)"
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
splitButtonDivider: {
|
splitButtonDivider: {
|
||||||
@ -119,6 +142,7 @@ export const convertButton = (btns: CommandButtonComponentProps[], backgroundCol
|
|||||||
icon: {
|
icon: {
|
||||||
paddingLeft: 0,
|
paddingLeft: 0,
|
||||||
paddingRight: 0,
|
paddingRight: 0,
|
||||||
|
color: "var(--colorNeutralForeground1)"
|
||||||
},
|
},
|
||||||
splitButtonContainer: {
|
splitButtonContainer: {
|
||||||
marginLeft: 5,
|
marginLeft: 5,
|
||||||
|
@ -40,6 +40,14 @@ export const Tabs = ({ explorer }: TabsProps): JSX.Element => {
|
|||||||
});
|
});
|
||||||
}, [setKeyboardHandlers]);
|
}, [setKeyboardHandlers]);
|
||||||
|
|
||||||
|
// Add useEffect to handle context buttons
|
||||||
|
useEffect(() => {
|
||||||
|
if (activeReactTab !== undefined) {
|
||||||
|
// React tabs have no context buttons
|
||||||
|
useCommandBar.getState().setContextButtons([]);
|
||||||
|
}
|
||||||
|
}, [activeReactTab]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tabsManagerContainer">
|
<div className="tabsManagerContainer">
|
||||||
<div className="nav-tabs-margin">
|
<div className="nav-tabs-margin">
|
||||||
@ -259,9 +267,6 @@ const isQueryErrorThrown = (tab?: Tab, tabKind?: ReactTabKind): boolean => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getReactTabContent = (activeReactTab: ReactTabKind, explorer: Explorer): JSX.Element => {
|
const getReactTabContent = (activeReactTab: ReactTabKind, explorer: Explorer): JSX.Element => {
|
||||||
// React tabs have no context buttons.
|
|
||||||
useCommandBar.getState().setContextButtons([]);
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
switch (activeReactTab) {
|
switch (activeReactTab) {
|
||||||
case ReactTabKind.Connect:
|
case ReactTabKind.Connect:
|
||||||
|
105
src/Main.tsx
105
src/Main.tsx
@ -3,6 +3,8 @@ import "./ReactDevTools";
|
|||||||
|
|
||||||
// CSS Dependencies
|
// CSS Dependencies
|
||||||
import { initializeIcons, loadTheme } from "@fluentui/react";
|
import { initializeIcons, loadTheme } from "@fluentui/react";
|
||||||
|
import { FluentProvider, makeStyles, webDarkTheme, webLightTheme } from "@fluentui/react-components";
|
||||||
|
import { Platform } from "ConfigContext";
|
||||||
import { QuickstartCarousel } from "Explorer/Quickstart/QuickstartCarousel";
|
import { QuickstartCarousel } from "Explorer/Quickstart/QuickstartCarousel";
|
||||||
import { MongoQuickstartTutorial } from "Explorer/Quickstart/Tutorials/MongoQuickstartTutorial";
|
import { MongoQuickstartTutorial } from "Explorer/Quickstart/Tutorials/MongoQuickstartTutorial";
|
||||||
import { SQLQuickstartTutorial } from "Explorer/Quickstart/Tutorials/SQLQuickstartTutorial";
|
import { SQLQuickstartTutorial } from "Explorer/Quickstart/Tutorials/SQLQuickstartTutorial";
|
||||||
@ -19,7 +21,7 @@ import "../externals/jquery.dataTables.min.css";
|
|||||||
import "../externals/jquery.typeahead.min.css";
|
import "../externals/jquery.typeahead.min.css";
|
||||||
import "../externals/jquery.typeahead.min.js";
|
import "../externals/jquery.typeahead.min.js";
|
||||||
// Image Dependencies
|
// Image Dependencies
|
||||||
import { Platform } from "ConfigContext";
|
import { SidePanel } from "Explorer/Panes/PanelContainerComponent";
|
||||||
import { QueryCopilotCarousel } from "Explorer/QueryCopilot/CopilotCarousel";
|
import { QueryCopilotCarousel } from "Explorer/QueryCopilot/CopilotCarousel";
|
||||||
import { SidebarContainer } from "Explorer/Sidebar";
|
import { SidebarContainer } from "Explorer/Sidebar";
|
||||||
import { KeyboardShortcutRoot } from "KeyboardShortcuts";
|
import { KeyboardShortcutRoot } from "KeyboardShortcuts";
|
||||||
@ -46,6 +48,7 @@ import "./Explorer/Controls/ErrorDisplayComponent/ErrorDisplayComponent.less";
|
|||||||
import "./Explorer/Controls/JsonEditor/JsonEditorComponent.less";
|
import "./Explorer/Controls/JsonEditor/JsonEditorComponent.less";
|
||||||
import "./Explorer/Controls/Notebook/NotebookTerminalComponent.less";
|
import "./Explorer/Controls/Notebook/NotebookTerminalComponent.less";
|
||||||
import "./Explorer/Controls/TreeComponent/treeComponent.less";
|
import "./Explorer/Controls/TreeComponent/treeComponent.less";
|
||||||
|
import { ErrorBoundary } from "./Explorer/ErrorBoundary";
|
||||||
import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less";
|
import "./Explorer/Graph/GraphExplorerComponent/graphExplorer.less";
|
||||||
import "./Explorer/Menus/CommandBar/CommandBarComponent.less";
|
import "./Explorer/Menus/CommandBar/CommandBarComponent.less";
|
||||||
import { CommandBar } from "./Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
import { CommandBar } from "./Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
||||||
@ -54,7 +57,6 @@ import "./Explorer/Menus/CommandBar/MemoryTrackerComponent.less";
|
|||||||
import "./Explorer/Menus/NotificationConsole/NotificationConsole.less";
|
import "./Explorer/Menus/NotificationConsole/NotificationConsole.less";
|
||||||
import { NotificationConsole } from "./Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
|
import { NotificationConsole } from "./Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
import "./Explorer/Panes/PanelComponent.less";
|
import "./Explorer/Panes/PanelComponent.less";
|
||||||
import { SidePanel } from "./Explorer/Panes/PanelContainerComponent";
|
|
||||||
import "./Explorer/SplashScreen/SplashScreen.less";
|
import "./Explorer/SplashScreen/SplashScreen.less";
|
||||||
import "./Libs/jquery";
|
import "./Libs/jquery";
|
||||||
import { appThemeFabric } from "./Platform/Fabric/FabricTheme";
|
import { appThemeFabric } from "./Platform/Fabric/FabricTheme";
|
||||||
@ -62,13 +64,26 @@ import "./Shared/appInsights";
|
|||||||
import { useConfig } from "./hooks/useConfig";
|
import { useConfig } from "./hooks/useConfig";
|
||||||
import { useKnockoutExplorer } from "./hooks/useKnockoutExplorer";
|
import { useKnockoutExplorer } from "./hooks/useKnockoutExplorer";
|
||||||
|
|
||||||
initializeIcons();
|
// Initialize icons before React is loaded
|
||||||
|
initializeIcons(undefined, { disableWarnings: true });
|
||||||
|
|
||||||
const App: React.FunctionComponent = () => {
|
const useStyles = makeStyles({
|
||||||
|
root: {
|
||||||
|
height: "100vh",
|
||||||
|
width: "100vw",
|
||||||
|
backgroundColor: "var(--colorNeutralBackground1)",
|
||||||
|
color: "var(--colorNeutralForeground1)"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const App = (): JSX.Element => {
|
||||||
|
const config = useConfig();
|
||||||
const isCarouselOpen = useCarousel((state) => state.shouldOpen);
|
const isCarouselOpen = useCarousel((state) => state.shouldOpen);
|
||||||
const isCopilotCarouselOpen = useCarousel((state) => state.showCopilotCarousel);
|
const isCopilotCarouselOpen = useCarousel((state) => state.showCopilotCarousel);
|
||||||
|
const styles = useStyles();
|
||||||
|
|
||||||
|
console.log("App - Current theme: Dark");
|
||||||
|
|
||||||
const config = useConfig();
|
|
||||||
if (config?.platform === Platform.Fabric) {
|
if (config?.platform === Platform.Fabric) {
|
||||||
loadTheme(appThemeFabric);
|
loadTheme(appThemeFabric);
|
||||||
import("../less/documentDBFabric.less");
|
import("../less/documentDBFabric.less");
|
||||||
@ -81,37 +96,71 @@ const App: React.FunctionComponent = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardShortcutRoot>
|
<div id="Main" className={styles.root}>
|
||||||
<div className="flexContainer" aria-hidden="false" data-test="DataExplorerRoot">
|
<KeyboardShortcutRoot>
|
||||||
<div id="divExplorer" className="flexContainer hideOverflows">
|
<div
|
||||||
<div id="freeTierTeachingBubble"> </div>
|
className="flexContainer"
|
||||||
{/* Main Command Bar - Start */}
|
style={{ flex: 1, display: "flex", flexDirection: "column" }}
|
||||||
<CommandBar container={explorer} />
|
aria-hidden="false"
|
||||||
{/* Collections Tree and Tabs - Begin */}
|
data-test="DataExplorerRoot"
|
||||||
<SidebarContainer explorer={explorer} />
|
>
|
||||||
{/* Collections Tree and Tabs - End */}
|
|
||||||
<div
|
<div
|
||||||
className="dataExplorerErrorConsoleContainer"
|
id="divExplorer"
|
||||||
role="contentinfo"
|
className="flexContainer hideOverflows"
|
||||||
aria-label="Notification console"
|
style={{ flex: 1, display: "flex", flexDirection: "column" }}
|
||||||
id="explorerNotificationConsole"
|
|
||||||
>
|
>
|
||||||
<NotificationConsole />
|
<div id="freeTierTeachingBubble"> </div>
|
||||||
|
{/* Main Command Bar - Start */}
|
||||||
|
<CommandBar container={explorer} />
|
||||||
|
{/* Collections Tree and Tabs - Begin */}
|
||||||
|
<SidebarContainer explorer={explorer} />
|
||||||
|
{/* Collections Tree and Tabs - End */}
|
||||||
|
<div
|
||||||
|
className="dataExplorerErrorConsoleContainer"
|
||||||
|
role="contentinfo"
|
||||||
|
aria-label="Notification console"
|
||||||
|
id="explorerNotificationConsole"
|
||||||
|
>
|
||||||
|
<NotificationConsole />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<SidePanel />
|
||||||
|
<Dialog />
|
||||||
|
{<QuickstartCarousel isOpen={isCarouselOpen} />}
|
||||||
|
{<SQLQuickstartTutorial />}
|
||||||
|
{<MongoQuickstartTutorial />}
|
||||||
|
{<QueryCopilotCarousel isOpen={isCopilotCarouselOpen} explorer={explorer} />}
|
||||||
</div>
|
</div>
|
||||||
<SidePanel />
|
</KeyboardShortcutRoot>
|
||||||
<Dialog />
|
</div>
|
||||||
{<QuickstartCarousel isOpen={isCarouselOpen} />}
|
);
|
||||||
{<SQLQuickstartTutorial />}
|
};
|
||||||
{<MongoQuickstartTutorial />}
|
|
||||||
{<QueryCopilotCarousel isOpen={isCopilotCarouselOpen} explorer={explorer} />}
|
const Root: React.FC = () => {
|
||||||
</div>
|
// Force dark theme
|
||||||
</KeyboardShortcutRoot>
|
const isDarkMode = true;
|
||||||
|
const currentTheme = isDarkMode ? webDarkTheme : webLightTheme;
|
||||||
|
const theme = "Dark";
|
||||||
|
|
||||||
|
console.log("Root component - Theme state:", {
|
||||||
|
isDarkMode,
|
||||||
|
currentTheme,
|
||||||
|
theme
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ErrorBoundary>
|
||||||
|
<FluentProvider theme={currentTheme}>
|
||||||
|
<App />
|
||||||
|
</FluentProvider>
|
||||||
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const mainElement = document.getElementById("Main");
|
const mainElement = document.getElementById("Main");
|
||||||
ReactDOM.render(<App />, mainElement);
|
if (mainElement) {
|
||||||
|
ReactDOM.render(<Root />, mainElement);
|
||||||
|
}
|
||||||
|
|
||||||
function LoadingExplorer(): JSX.Element {
|
function LoadingExplorer(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
51
src/hooks/useTheme.tsx
Normal file
51
src/hooks/useTheme.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { useFluent } from "@fluentui/react-components";
|
||||||
|
import React, { createContext, FC, ReactNode, useEffect, useState } from "react";
|
||||||
|
|
||||||
|
interface ThemeContextType {
|
||||||
|
theme: "Light" | "Dark";
|
||||||
|
isDarkMode: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
|
||||||
|
|
||||||
|
interface ThemeProviderProps {
|
||||||
|
children: ReactNode;
|
||||||
|
theme: "Light" | "Dark";
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CustomThemeProvider: FC<ThemeProviderProps> = ({ children, theme }) => {
|
||||||
|
const isDarkMode = theme === "Dark";
|
||||||
|
return <ThemeContext.Provider value={{ theme, isDarkMode }}>{children}</ThemeContext.Provider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useTheme = () => {
|
||||||
|
const { targetDocument } = useFluent();
|
||||||
|
const [isDarkMode, setIsDarkMode] = useState(() => {
|
||||||
|
const hasDarkMode = targetDocument?.body.classList.contains("isDarkMode") ?? true;
|
||||||
|
return hasDarkMode;
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!targetDocument) return;
|
||||||
|
|
||||||
|
const checkTheme = () => {
|
||||||
|
const hasDarkMode = targetDocument.body.classList.contains("isDarkMode");
|
||||||
|
setIsDarkMode(hasDarkMode);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initial check
|
||||||
|
checkTheme();
|
||||||
|
|
||||||
|
// Create a MutationObserver to watch for class changes
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
checkTheme();
|
||||||
|
});
|
||||||
|
observer.observe(targetDocument.body, { attributes: true, attributeFilter: ["class"] });
|
||||||
|
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, [targetDocument]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
isDarkMode
|
||||||
|
};
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user