mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2024-11-25 15:06:55 +00:00
Move tabs state out into React (#621)
This PR is just about moving the tabs array. I'm hoping to let it bake for a bit before merging the rest of the tabs in react work. Preview here: https://ms.portal.azure.com/?dataExplorerSource=https%3A%2F%2Fcosmos-explorer-preview.azurewebsites.net%2Fcommit%2Fda809beb82bb54dc82da18eda41caaf7b9b6597f%2Fexplorer.html#@microsoft.onmicrosoft.com/resource/subscriptions/b9c77f10-b438-4c32-9819-eef8a654e478/resourceGroups/stfaul/providers/Microsoft.DocumentDb/databaseAccounts/stfaul-sql/dataExplorer
This commit is contained in:
parent
9c6178d0ed
commit
4f22d308b3
@ -93,6 +93,7 @@ export interface ExplorerParams {
|
|||||||
closeSidePanel: () => void;
|
closeSidePanel: () => void;
|
||||||
closeDialog: () => void;
|
closeDialog: () => void;
|
||||||
openDialog: (props: DialogProps) => void;
|
openDialog: (props: DialogProps) => void;
|
||||||
|
tabsManager: TabsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Explorer {
|
export default class Explorer {
|
||||||
@ -600,7 +601,7 @@ export default class Explorer {
|
|||||||
container: this,
|
container: this,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.tabsManager = new TabsManager();
|
this.tabsManager = params?.tabsManager ?? new TabsManager();
|
||||||
|
|
||||||
this._panes = [
|
this._panes = [
|
||||||
this.addDatabasePane,
|
this.addDatabasePane,
|
||||||
|
@ -50,10 +50,6 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
|||||||
this.subscriptions = [];
|
this.subscriptions = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public shouldComponentUpdate() {
|
|
||||||
return this.container.tabsManager.openedTabs.length === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
while (this.subscriptions.length) {
|
while (this.subscriptions.length) {
|
||||||
this.subscriptions.pop().dispose();
|
this.subscriptions.pop().dispose();
|
||||||
@ -62,7 +58,6 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
|||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
this.subscriptions.push(
|
this.subscriptions.push(
|
||||||
this.container.tabsManager.openedTabs.subscribe(() => this.setState({})),
|
|
||||||
this.container.selectedNode.subscribe(() => this.setState({})),
|
this.container.selectedNode.subscribe(() => this.setState({})),
|
||||||
this.container.isNotebookEnabled.subscribe(() => this.setState({}))
|
this.container.isNotebookEnabled.subscribe(() => this.setState({}))
|
||||||
);
|
);
|
||||||
@ -80,7 +75,13 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
|||||||
const tipsItems = this.createTipsItems();
|
const tipsItems = this.createTipsItems();
|
||||||
const onClearRecent = this.clearMostRecent;
|
const onClearRecent = this.clearMostRecent;
|
||||||
|
|
||||||
return (
|
const formContainer = (jsx: JSX.Element) => (
|
||||||
|
<div className="connectExplorerContainer">
|
||||||
|
<form className="connectExplorerFormContainer">{jsx}</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return formContainer(
|
||||||
<div className="splashScreenContainer">
|
<div className="splashScreenContainer">
|
||||||
<div className="splashScreen">
|
<div className="splashScreen">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
|
10
src/Main.tsx
10
src/Main.tsx
@ -53,6 +53,7 @@ import "./Explorer/Tabs/QueryTab.less";
|
|||||||
import { useConfig } from "./hooks/useConfig";
|
import { useConfig } from "./hooks/useConfig";
|
||||||
import { useKnockoutExplorer } from "./hooks/useKnockoutExplorer";
|
import { useKnockoutExplorer } from "./hooks/useKnockoutExplorer";
|
||||||
import { useSidePanel } from "./hooks/useSidePanel";
|
import { useSidePanel } from "./hooks/useSidePanel";
|
||||||
|
import { useTabs } from "./hooks/useTabs";
|
||||||
import { KOCommentEnd, KOCommentIfStart } from "./koComment";
|
import { KOCommentEnd, KOCommentIfStart } from "./koComment";
|
||||||
import "./Libs/jquery";
|
import "./Libs/jquery";
|
||||||
import "./Shared/appInsights";
|
import "./Shared/appInsights";
|
||||||
@ -78,6 +79,7 @@ const App: React.FunctionComponent = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { isPanelOpen, panelContent, headerText, openSidePanel, closeSidePanel } = useSidePanel();
|
const { isPanelOpen, panelContent, headerText, openSidePanel, closeSidePanel } = useSidePanel();
|
||||||
|
const { tabs, tabsManager } = useTabs();
|
||||||
|
|
||||||
const explorerParams: ExplorerParams = {
|
const explorerParams: ExplorerParams = {
|
||||||
setIsNotificationConsoleExpanded,
|
setIsNotificationConsoleExpanded,
|
||||||
@ -87,7 +89,9 @@ const App: React.FunctionComponent = () => {
|
|||||||
closeSidePanel,
|
closeSidePanel,
|
||||||
openDialog,
|
openDialog,
|
||||||
closeDialog,
|
closeDialog,
|
||||||
|
tabsManager,
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const explorer = useKnockoutExplorer(config?.platform, explorerParams);
|
const explorer = useKnockoutExplorer(config?.platform, explorerParams);
|
||||||
|
|
||||||
@ -200,11 +204,7 @@ const App: React.FunctionComponent = () => {
|
|||||||
{/* Splitter - End */}
|
{/* Splitter - End */}
|
||||||
</div>
|
</div>
|
||||||
{/* Collections Tree - End */}
|
{/* Collections Tree - End */}
|
||||||
<div className="connectExplorerContainer" data-bind="visible: tabsManager.openedTabs().length === 0">
|
{tabs.length === 0 && <SplashScreen explorer={explorer} />}
|
||||||
<form className="connectExplorerFormContainer">
|
|
||||||
<SplashScreen explorer={explorer} />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div className="tabsManagerContainer" data-bind='component: { name: "tabs-manager", params: tabsManager }' />
|
<div className="tabsManagerContainer" data-bind='component: { name: "tabs-manager", params: tabsManager }' />
|
||||||
</div>
|
</div>
|
||||||
{/* Collections Tree and Tabs - End */}
|
{/* Collections Tree and Tabs - End */}
|
||||||
|
16
src/hooks/useObservableState.ts
Normal file
16
src/hooks/useObservableState.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { isObservableArray, Observable, ObservableArray } from "knockout";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
export function useObservableState<T>(observable: Observable<T>): [T, (s: T) => void];
|
||||||
|
export function useObservableState<T>(observable: ObservableArray<T>): [T[], (s: T[]) => void];
|
||||||
|
export function useObservableState<T>(observable: ObservableArray<T> | Observable<T>): [T | T[], (s: T | T[]) => void] {
|
||||||
|
const [value, setValue] = useState(observable());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isObservableArray(observable)
|
||||||
|
? observable.subscribe((values) => setValue([...values]))
|
||||||
|
: observable.subscribe(setValue);
|
||||||
|
}, [observable]);
|
||||||
|
|
||||||
|
return [value, observable];
|
||||||
|
}
|
16
src/hooks/useTabs.ts
Normal file
16
src/hooks/useTabs.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import TabsBase from "../Explorer/Tabs/TabsBase";
|
||||||
|
import { TabsManager } from "../Explorer/Tabs/TabsManager";
|
||||||
|
import { useObservableState } from "./useObservableState";
|
||||||
|
|
||||||
|
export type UseTabs = {
|
||||||
|
tabs: readonly TabsBase[];
|
||||||
|
tabsManager: TabsManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useTabs(): UseTabs {
|
||||||
|
const [tabsManager] = useState(() => new TabsManager());
|
||||||
|
const [tabs] = useObservableState(tabsManager.openedTabs);
|
||||||
|
|
||||||
|
return { tabs, tabsManager };
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user