(Partial) removal of WrapperProps (#4431)

This commit is contained in:
Dimitri Mitropoulos 2022-02-02 09:54:05 -06:00 committed by GitHub
parent aa2dc2e2de
commit 3556a20f85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 255 additions and 264 deletions

View File

@ -1,5 +1,5 @@
import { isDesign, Workspace } from '../models/workspace';
import { strings } from './strings';
export const getWorkspaceLabel = (w: Workspace) =>
isDesign(w) ? strings.document : strings.collection;
export const getWorkspaceLabel = (workspace: Workspace) =>
isDesign(workspace) ? strings.document : strings.collection;

View File

@ -1,17 +1,18 @@
import { MultiSwitch } from 'insomnia-components';
import React, { FunctionComponent } from 'react';
import React, { FunctionComponent, useCallback } from 'react';
import { useSelector } from 'react-redux';
import type { GlobalActivity } from '../../common/constants';
import { ACTIVITY_DEBUG, ACTIVITY_SPEC, ACTIVITY_UNIT_TEST } from '../../common/constants';
import type { Workspace } from '../../models/workspace';
import { isDesign } from '../../models/workspace';
import { selectActiveActivity, selectActiveWorkspace } from '../redux/selectors';
import { HandleActivityChange } from './wrapper';
interface Props {
activity: GlobalActivity;
handleActivityChange: (options: {workspaceId?: string; nextActivity: GlobalActivity}) => Promise<void>;
workspace: Workspace;
handleActivityChange: HandleActivityChange;
}
export const ActivityToggle: FunctionComponent<Props> = ({ activity, handleActivityChange, workspace }) => {
export const ActivityToggle: FunctionComponent<Props> = ({ handleActivityChange }) => {
const choices = [
{
label: 'Design',
@ -27,12 +28,27 @@ export const ActivityToggle: FunctionComponent<Props> = ({ activity, handleActiv
},
];
const activeActivity = useSelector(selectActiveActivity);
const activeWorkspace = useSelector(selectActiveWorkspace);
const onChange = useCallback((nextActivity: GlobalActivity) => {
handleActivityChange({ workspaceId: activeWorkspace?._id, nextActivity });
}, [handleActivityChange, activeWorkspace]);
if (!activeActivity) {
return null;
}
if (!activeWorkspace || !isDesign(activeWorkspace)) {
return null;
}
return (
<MultiSwitch
name="activity-toggle"
onChange={(nextActivity: GlobalActivity) => handleActivityChange({ workspaceId: workspace._id, nextActivity })}
onChange={onChange}
choices={choices}
selectedValue={activity}
selectedValue={activeActivity}
/>
);
};

View File

@ -1,7 +1,7 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import classnames from 'classnames';
import { HotKeyRegistry } from 'insomnia-common';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { AUTOBIND_CFG } from '../../../common/constants';
import { database as db } from '../../../common/database';
@ -9,15 +9,15 @@ import { getWorkspaceLabel } from '../../../common/get-workspace-label';
import { hotKeyRefs } from '../../../common/hotkeys';
import { executeHotKey } from '../../../common/hotkeys-listener';
import { RENDER_PURPOSE_NO_RENDER } from '../../../common/render';
import { ApiSpec } from '../../../models/api-spec';
import type { Environment } from '../../../models/environment';
import { Project } from '../../../models/project';
import { isRequest } from '../../../models/request';
import { isRequestGroup } from '../../../models/request-group';
import { isDesign, Workspace } from '../../../models/workspace';
import type { WorkspaceAction } from '../../../plugins';
import { ConfigGenerator, getConfigGenerators, getWorkspaceActions } from '../../../plugins';
import * as pluginContexts from '../../../plugins/context';
import { RootState } from '../../redux/modules';
import { selectIsLoading } from '../../redux/modules/global';
import { selectActiveApiSpec, selectActiveEnvironment, selectActiveProject, selectActiveWorkspace, selectActiveWorkspaceName, selectSettings } from '../../redux/selectors';
import { Dropdown } from '../base/dropdown/dropdown';
import { DropdownButton } from '../base/dropdown/dropdown-button';
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
@ -29,13 +29,9 @@ import { showGenerateConfigModal } from '../modals/generate-config-modal';
import { SettingsModal, TAB_INDEX_EXPORT } from '../modals/settings-modal';
import { WorkspaceSettingsModal } from '../modals/workspace-settings-modal';
interface Props {
activeEnvironment: Environment | null;
activeWorkspace: Workspace;
activeWorkspaceName?: string;
activeApiSpec: ApiSpec;
activeProject: Project;
hotKeyRegistry: HotKeyRegistry;
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
isLoading: boolean;
className?: string;
}
@ -47,7 +43,7 @@ interface State {
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class WorkspaceDropdown extends PureComponent<Props, State> {
export class UnconnectedWorkspaceDropdown extends PureComponent<Props, State> {
_dropdown: Dropdown | null = null;
state: State = {
actionPlugins: [],
@ -55,31 +51,31 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
loadingActions: {},
};
async _handlePluginClick(p: WorkspaceAction) {
async _handlePluginClick({ action, plugin, label }: WorkspaceAction, workspace: Workspace) {
this.setState(state => ({
loadingActions: { ...state.loadingActions, [p.label]: true },
loadingActions: { ...state.loadingActions, [label]: true },
}));
const { activeEnvironment, activeWorkspace, activeProject } = this.props;
const { activeEnvironment, activeProject } = this.props;
try {
const activeEnvironmentId = activeEnvironment ? activeEnvironment._id : null;
const context = {
...(pluginContexts.app.init(RENDER_PURPOSE_NO_RENDER) as Record<string, any>),
...pluginContexts.data.init(activeProject._id),
...(pluginContexts.store.init(p.plugin) as Record<string, any>),
...(pluginContexts.store.init(plugin) as Record<string, any>),
...(pluginContexts.network.init(activeEnvironmentId) as Record<string, any>),
};
const docs = await db.withDescendants(activeWorkspace);
const docs = await db.withDescendants(workspace);
const requests = docs
.filter(isRequest)
.filter(doc => (
!doc.isPrivate
));
const requestGroups = docs.filter(isRequestGroup);
await p.action(context, {
await action(context, {
requestGroups,
requests,
workspace: activeWorkspace,
workspace,
});
} catch (err) {
showError({
@ -89,7 +85,7 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
}
this.setState(state => ({
loadingActions: { ...state.loadingActions, [p.label]: false },
loadingActions: { ...state.loadingActions, [label]: false },
}));
this._dropdown?.hide();
}
@ -123,6 +119,9 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
async _handleGenerateConfig(label: string) {
const { activeApiSpec } = this.props;
if (!activeApiSpec) {
return;
}
showGenerateConfigModal({
apiSpec: activeApiSpec,
activeTabLabel: label,
@ -140,6 +139,11 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
} = this.props;
const classes = classnames(className, 'wide', 'workspace-dropdown');
const { actionPlugins, loadingActions, configGeneratorPlugins } = this.state;
if (!activeWorkspace) {
console.error('warning: tried to render WorkspaceDropdown without an activeWorkspace');
return null;
}
return (
<KeydownBinder onKeydown={this._handleKeydown}>
<Dropdown
@ -177,7 +181,7 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
{actionPlugins.map((p: WorkspaceAction) => (
<DropdownItem
key={p.label}
onClick={() => this._handlePluginClick(p)}
onClick={() => this._handlePluginClick(p, activeWorkspace)}
stayOpenAfterClick
>
{loadingActions[p.label] ? (
@ -210,3 +214,15 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
);
}
}
const mapStateToProps = (state: RootState) => ({
activeEnvironment: selectActiveEnvironment(state),
activeWorkspace: selectActiveWorkspace(state),
activeWorkspaceName: selectActiveWorkspaceName(state),
activeApiSpec: selectActiveApiSpec(state),
activeProject: selectActiveProject(state),
hotKeyRegistry: selectSettings(state).hotKeyRegistry,
isLoading: selectIsLoading(state),
});
export const WorkspaceDropdown = connect(mapStateToProps)(UnconnectedWorkspaceDropdown);

View File

@ -1,8 +1,9 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import classnames from 'classnames';
import React, { forwardRef, PureComponent, ReactNode } from 'react';
import React, { FC, forwardRef, ReactNode, useCallback } from 'react';
import { useSelector } from 'react-redux';
import { AUTOBIND_CFG } from '../../common/constants';
import { selectIsLoading } from '../redux/modules/global';
import { selectActiveEnvironment, selectActiveGitRepository, selectSettings, selectUnseenWorkspaces, selectWorkspacesForActiveProject } from '../redux/selectors';
import { ErrorBoundary } from './error-boundary';
import { Sidebar } from './sidebar/sidebar';
import type { WrapperProps } from './wrapper';
@ -26,168 +27,164 @@ interface Props {
renderPaneTwo?: () => ReactNode;
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class PageLayout extends PureComponent<Props> {
// Special request updaters
_handleStartDragSidebar(e: React.MouseEvent<HTMLDivElement>) {
e.preventDefault();
const { handleStartDragSidebar } = this.props.wrapperProps;
handleStartDragSidebar(e);
}
export const PageLayout: FC<Props> = ({
renderPaneOne,
renderPaneTwo,
renderPageBody,
renderPageHeader,
renderPageSidebar,
wrapperProps,
}) => {
const activeEnvironment = useSelector(selectActiveEnvironment);
const activeGitRepository = useSelector(selectActiveGitRepository);
const isLoading = useSelector(selectIsLoading);
const settings = useSelector(selectSettings);
const unseenWorkspaces = useSelector(selectUnseenWorkspaces);
const workspaces = useSelector(selectWorkspacesForActiveProject);
render() {
const {
renderPaneOne,
renderPaneTwo,
renderPageBody,
renderPageHeader,
renderPageSidebar,
wrapperProps,
} = this.props;
const {
activeEnvironment,
activeGitRepository,
gitVCS,
handleInitializeEntities,
handleResetDragSidebar,
handleSetActiveEnvironment,
sidebarRef,
requestPaneRef,
responsePaneRef,
handleStartDragPaneHorizontal,
handleResetDragPaneHorizontal,
handleStartDragPaneVertical,
handleResetDragPaneVertical,
isLoading,
paneHeight,
paneWidth,
settings,
sidebarHidden,
sidebarWidth,
unseenWorkspaces,
workspaces,
} = wrapperProps;
const realSidebarWidth = sidebarHidden ? 0 : sidebarWidth;
const paneTwo = renderPaneTwo?.();
const gridRows = paneTwo
? `auto minmax(0, ${paneHeight}fr) 0 minmax(0, ${1 - paneHeight}fr)`
: 'auto 1fr';
const gridColumns =
const {
gitVCS,
handleInitializeEntities,
handleResetDragSidebar,
handleStartDragSidebar,
handleSetActiveEnvironment,
sidebarRef,
requestPaneRef,
responsePaneRef,
handleStartDragPaneHorizontal,
handleResetDragPaneHorizontal,
handleStartDragPaneVertical,
handleResetDragPaneVertical,
paneHeight,
paneWidth,
sidebarHidden,
sidebarWidth,
} = wrapperProps;
// Special request updaters
const startDragSidebar = useCallback((event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault();
handleStartDragSidebar(event);
}, [handleStartDragSidebar]);
const realSidebarWidth = sidebarHidden ? 0 : sidebarWidth;
const paneTwo = renderPaneTwo?.();
const gridRows = paneTwo
? `auto minmax(0, ${paneHeight}fr) 0 minmax(0, ${1 - paneHeight}fr)`
: 'auto 1fr';
const gridColumns =
`auto ${realSidebarWidth}rem 0 ` +
`${paneTwo ? `minmax(0, ${paneWidth}fr) 0 minmax(0, ${1 - paneWidth}fr)` : '1fr'}`;
return (
<div
key="wrapper"
id="wrapper"
className={classnames('wrapper', {
'wrapper--vertical': settings.forceVerticalLayout,
})}
style={{
gridTemplateColumns: gridColumns,
gridTemplateRows: gridRows,
boxSizing: 'border-box',
borderTop:
return (
<div
key="wrapper"
id="wrapper"
className={classnames('wrapper', {
'wrapper--vertical': settings.forceVerticalLayout,
})}
style={{
gridTemplateColumns: gridColumns,
gridTemplateRows: gridRows,
boxSizing: 'border-box',
borderTop:
activeEnvironment &&
activeEnvironment.color &&
settings.environmentHighlightColorStyle === 'window-top'
? '5px solid ' + activeEnvironment.color
: undefined,
borderBottom:
borderBottom:
activeEnvironment &&
activeEnvironment.color &&
settings.environmentHighlightColorStyle === 'window-bottom'
? '5px solid ' + activeEnvironment.color
: undefined,
borderLeft:
borderLeft:
activeEnvironment &&
activeEnvironment.color &&
settings.environmentHighlightColorStyle === 'window-left'
? '5px solid ' + activeEnvironment.color
: undefined,
borderRight:
borderRight:
activeEnvironment &&
activeEnvironment.color &&
settings.environmentHighlightColorStyle === 'window-right'
? '5px solid ' + activeEnvironment.color
: undefined,
}}
>
{renderPageHeader && <ErrorBoundary showAlert>{renderPageHeader()}</ErrorBoundary>}
}}
>
{renderPageHeader && <ErrorBoundary showAlert>{renderPageHeader()}</ErrorBoundary>}
{renderPageSidebar && (
<ErrorBoundary showAlert>
<Sidebar
ref={sidebarRef}
activeEnvironment={activeEnvironment}
// @ts-expect-error -- TSCONVERSION
activeGitRepository={activeGitRepository}
environmentHighlightColorStyle={settings.environmentHighlightColorStyle}
handleInitializeEntities={handleInitializeEntities}
handleSetActiveEnvironment={handleSetActiveEnvironment}
hidden={sidebarHidden || false}
hotKeyRegistry={settings.hotKeyRegistry}
isLoading={isLoading}
// @ts-expect-error -- TSCONVERSION appears to be a genuine error, or is it that it comes from Wrapper?
showEnvironmentsModal={this._handleShowEnvironmentsModal}
unseenWorkspaces={unseenWorkspaces}
gitVCS={gitVCS}
width={sidebarWidth}
workspaces={workspaces}
>
{renderPageSidebar()}
</Sidebar>
{renderPageSidebar && (
<ErrorBoundary showAlert>
<Sidebar
ref={sidebarRef}
activeEnvironment={activeEnvironment}
// @ts-expect-error -- TSCONVERSION
activeGitRepository={activeGitRepository}
environmentHighlightColorStyle={settings.environmentHighlightColorStyle}
handleInitializeEntities={handleInitializeEntities}
handleSetActiveEnvironment={handleSetActiveEnvironment}
hidden={sidebarHidden || false}
hotKeyRegistry={settings.hotKeyRegistry}
isLoading={isLoading}
unseenWorkspaces={unseenWorkspaces}
gitVCS={gitVCS}
width={sidebarWidth}
workspaces={workspaces}
>
{renderPageSidebar()}
</Sidebar>
<div className="drag drag--sidebar">
<div
onDoubleClick={handleResetDragSidebar}
onMouseDown={startDragSidebar}
/>
</div>
</ErrorBoundary>
)}
{renderPageBody ? (
<ErrorBoundary showAlert>{renderPageBody()}</ErrorBoundary>
) : (
<>
{renderPaneOne && (
<ErrorBoundary showAlert>
<Pane
position="one"
ref={requestPaneRef}
>
{renderPaneOne()}
</Pane>
</ErrorBoundary>
)}
{paneTwo && (
<>
<div className="drag drag--pane-horizontal">
<div
onMouseDown={handleStartDragPaneHorizontal}
onDoubleClick={handleResetDragPaneHorizontal}
/>
</div>
<div className="drag drag--pane-vertical">
<div
onMouseDown={handleStartDragPaneVertical}
onDoubleClick={handleResetDragPaneVertical}
/>
</div>
<div className="drag drag--sidebar">
<div
onDoubleClick={handleResetDragSidebar}
onMouseDown={this._handleStartDragSidebar}
/>
</div>
</ErrorBoundary>
)}
{renderPageBody ? (
<ErrorBoundary showAlert>{renderPageBody()}</ErrorBoundary>
) : (
<>
{renderPaneOne && (
<ErrorBoundary showAlert>
<Pane
position="one"
ref={requestPaneRef}
position="two"
ref={responsePaneRef}
>
{renderPaneOne()}
{paneTwo}
</Pane>
</ErrorBoundary>
)}
{paneTwo && (
<>
<div className="drag drag--pane-horizontal">
<div
onMouseDown={handleStartDragPaneHorizontal}
onDoubleClick={handleResetDragPaneHorizontal}
/>
</div>
<div className="drag drag--pane-vertical">
<div
onMouseDown={handleStartDragPaneVertical}
onDoubleClick={handleResetDragPaneVertical}
/>
</div>
<ErrorBoundary showAlert>
<Pane
position="two"
ref={responsePaneRef}
>
{paneTwo}
</Pane>
</ErrorBoundary>
</>
)}
</>
)}
</div>
);
}
}
</>
)}
</>
)}
</div>
);
};

View File

@ -17,7 +17,6 @@ interface Props {
hidden: boolean;
hotKeyRegistry: HotKeyRegistry;
isLoading: boolean;
showEnvironmentsModal: (...args: any[]) => any;
unseenWorkspaces: Workspace[];
width: number;
workspaces: Workspace[];

View File

@ -1,74 +1,44 @@
import React, { FunctionComponent, ReactNode, useCallback } from 'react';
import { useSelector } from 'react-redux';
import { ACTIVITY_HOME, GlobalActivity } from '../../common/constants';
import { isDesign } from '../../models/workspace';
import { selectActiveProjectName } from '../redux/selectors';
import { ACTIVITY_HOME } from '../../common/constants';
import { selectActiveActivity, selectActiveApiSpec, selectActiveProjectName, selectActiveWorkspace } from '../redux/selectors';
import { ActivityToggle } from './activity-toggle';
import { AppHeader } from './app-header';
import { WorkspaceDropdown } from './dropdowns/workspace-dropdown';
import type { WrapperProps } from './wrapper';
import { HandleActivityChange } from './wrapper';
interface Props {
wrapperProps: WrapperProps;
handleActivityChange: (options: {workspaceId?: string; nextActivity: GlobalActivity}) => Promise<void>;
handleActivityChange: HandleActivityChange;
gridRight: ReactNode;
}
export const WorkspacePageHeader: FunctionComponent<Props> = ({
gridRight,
handleActivityChange,
wrapperProps: {
activeApiSpec,
activeWorkspace,
activeWorkspaceName,
activeProject,
activeEnvironment,
settings,
activity,
isLoading,
},
}) => {
const homeCallback = useCallback(
() => handleActivityChange({ workspaceId: activeWorkspace?._id, nextActivity: ACTIVITY_HOME }),
[activeWorkspace, handleActivityChange],
);
const activeApiSpec = useSelector(selectActiveApiSpec);
const activeWorkspace = useSelector(selectActiveWorkspace);
const activity = useSelector(selectActiveActivity);
const homeCallback = useCallback(() => {
handleActivityChange({ workspaceId: activeWorkspace?._id, nextActivity: ACTIVITY_HOME });
}, [activeWorkspace, handleActivityChange]);
const activeProjectName = useSelector(selectActiveProjectName);
if (!activeWorkspace || !activeApiSpec || !activity) {
return null;
}
const workspace = (
<WorkspaceDropdown
key="workspace-dd"
activeEnvironment={activeEnvironment}
activeWorkspace={activeWorkspace}
activeWorkspaceName={activeWorkspaceName}
activeApiSpec={activeApiSpec}
activeProject={activeProject}
hotKeyRegistry={settings.hotKeyRegistry}
isLoading={isLoading}
/>
);
const crumbs = [
{ id: 'project', node: activeProjectName, onClick: homeCallback },
{ id: 'workspace', node: workspace },
{ id: 'workspace', node: <WorkspaceDropdown key="workspace-dd" /> },
];
return (
<AppHeader
breadcrumbProps={{ crumbs }}
gridCenter={
isDesign(activeWorkspace) && (
<ActivityToggle
activity={activity}
handleActivityChange={handleActivityChange}
workspace={activeWorkspace}
/>
)
}
gridCenter={<ActivityToggle handleActivityChange={handleActivityChange} />}
gridRight={gridRight}
/>
);

View File

@ -1,7 +1,7 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import React, { Fragment, PureComponent, ReactNode } from 'react';
import { AUTOBIND_CFG, GlobalActivity, SortOrder } from '../../common/constants';
import { AUTOBIND_CFG, SortOrder } from '../../common/constants';
import { isGrpcRequest } from '../../models/grpc-request';
import { isRemoteProject } from '../../models/project';
import { Request, RequestAuthentication, RequestBody, RequestHeader, RequestParameter } from '../../models/request';
@ -19,12 +19,12 @@ import { ResponsePane } from './panes/response-pane';
import { SidebarChildren } from './sidebar/sidebar-children';
import { SidebarFilter } from './sidebar/sidebar-filter';
import { WorkspacePageHeader } from './workspace-page-header';
import type { WrapperProps } from './wrapper';
import type { HandleActivityChange, WrapperProps } from './wrapper';
interface Props {
forceRefreshKey: number;
gitSyncDropdown: ReactNode;
handleActivityChange: (options: {workspaceId?: string; nextActivity: GlobalActivity}) => Promise<void>;
handleActivityChange: HandleActivityChange;
handleChangeEnvironment: Function;
handleDeleteResponse: Function;
handleDeleteResponses: Function;
@ -54,18 +54,22 @@ interface Props {
@autoBindMethodsForReact(AUTOBIND_CFG)
export class WrapperDebug extends PureComponent<Props> {
_renderPageHeader() {
const { wrapperProps, gitSyncDropdown, handleActivityChange } = this.props;
const { vcs, activeWorkspace, activeWorkspaceMeta, activeProject, syncItems, isLoggedIn } = this.props.wrapperProps;
const { gitSyncDropdown, handleActivityChange, wrapperProps: {
vcs,
activeWorkspace,
activeWorkspaceMeta,
activeProject,
syncItems,
isLoggedIn,
} } = this.props;
if (!activeWorkspace) {
return null;
}
const collection = isCollection(activeWorkspace);
const design = isDesign(activeWorkspace);
let insomniaSync: ReactNode = null;
if (isLoggedIn && collection && isRemoteProject(activeProject) && vcs) {
insomniaSync = <SyncDropdown
workspace={activeWorkspace}
@ -76,12 +80,11 @@ export class WrapperDebug extends PureComponent<Props> {
/>;
}
const gitSync = design && gitSyncDropdown;
const gitSync = isDesign(activeWorkspace) && gitSyncDropdown;
const sync = insomniaSync || gitSync;
return (
<WorkspacePageHeader
wrapperProps={wrapperProps}
handleActivityChange={handleActivityChange}
gridRight={sync}
/>

View File

@ -1,23 +1,24 @@
import { IRuleResult } from '@stoplight/spectral';
import { Button, Notice, NoticeTable } from 'insomnia-components';
import React, { createRef, FC, Fragment, ReactNode, RefObject, useCallback, useState } from 'react';
import { useSelector } from 'react-redux';
import { useAsync, useDebounce } from 'react-use';
import styled from 'styled-components';
import SwaggerUI from 'swagger-ui-react';
import { parseApiSpec, ParsedApiSpec } from '../../common/api-specs';
import type { GlobalActivity } from '../../common/constants';
import { initializeSpectral, isLintError } from '../../common/spectral';
import * as models from '../../models/index';
import { superFaint } from '../css/css-in-js';
import previewIcon from '../images/icn-eye.svg';
import { selectActiveApiSpec, selectActiveWorkspace, selectActiveWorkspaceMeta } from '../redux/selectors';
import { CodeEditor, UnconnectedCodeEditor } from './codemirror/code-editor';
import { DesignEmptyState } from './design-empty-state';
import { ErrorBoundary } from './error-boundary';
import { PageLayout } from './page-layout';
import { SpecEditorSidebar } from './spec-editor/spec-editor-sidebar';
import { WorkspacePageHeader } from './workspace-page-header';
import type { WrapperProps } from './wrapper';
import type { HandleActivityChange, WrapperProps } from './wrapper';
const EmptySpaceHelper = styled.div({
...superFaint,
@ -33,13 +34,12 @@ const spectral = initializeSpectral();
const RenderPageHeader: FC<Pick<Props,
| 'gitSyncDropdown'
| 'handleActivityChange'
| 'wrapperProps'
>> = ({
gitSyncDropdown,
handleActivityChange,
wrapperProps,
}) => {
const { activeWorkspace, activeWorkspaceMeta } = wrapperProps;
const activeWorkspace = useSelector(selectActiveWorkspace);
const activeWorkspaceMeta = useSelector(selectActiveWorkspaceMeta);
const previewHidden = Boolean(activeWorkspaceMeta?.previewHidden);
const handleTogglePreview = useCallback(async () => {
@ -53,7 +53,6 @@ const RenderPageHeader: FC<Pick<Props,
return (
<WorkspacePageHeader
wrapperProps={wrapperProps}
handleActivityChange={handleActivityChange}
gridRight={
<Fragment>
@ -75,13 +74,8 @@ interface LintMessage {
range: IRuleResult['range'];
}
const RenderEditor: FC<Pick<Props, 'wrapperProps'> & {
editor: RefObject<UnconnectedCodeEditor>;
}> = ({
editor,
wrapperProps,
}) => {
const { activeApiSpec } = wrapperProps;
const RenderEditor: FC<{ editor: RefObject<UnconnectedCodeEditor> }> = ({ editor }) => {
const activeApiSpec = useSelector(selectActiveApiSpec);
const [forceRefreshCounter, setForceRefreshCounter] = useState(0);
const [lintMessages, setLintMessages] = useState<LintMessage[]>([]);
const contents = activeApiSpec?.contents ?? '';
@ -160,8 +154,9 @@ const RenderEditor: FC<Pick<Props, 'wrapperProps'> & {
);
};
const RenderPreview: FC<Pick<Props, 'wrapperProps'>> = ({ wrapperProps }) => {
const { activeApiSpec, activeWorkspaceMeta } = wrapperProps;
const RenderPreview: FC = () => {
const activeWorkspaceMeta = useSelector(selectActiveWorkspaceMeta);
const activeApiSpec = useSelector(selectActiveApiSpec);
if (!activeApiSpec || activeWorkspaceMeta?.previewHidden) {
return null;
@ -217,10 +212,8 @@ const RenderPreview: FC<Pick<Props, 'wrapperProps'>> = ({ wrapperProps }) => {
);
};
const RenderPageSidebar: FC<Pick<Props, 'wrapperProps'> & { editor: RefObject<UnconnectedCodeEditor>}> = ({
editor,
wrapperProps: { activeApiSpec },
}) => {
const RenderPageSidebar: FC<{ editor: RefObject<UnconnectedCodeEditor>}> = ({ editor }) => {
const activeApiSpec = useSelector(selectActiveApiSpec);
const handleScrollToSelection = useCallback((chStart: number, chEnd: number, lineStart: number, lineEnd: number) => {
if (!editor.current) {
return;
@ -263,7 +256,7 @@ const RenderPageSidebar: FC<Pick<Props, 'wrapperProps'> & { editor: RefObject<Un
interface Props {
gitSyncDropdown: ReactNode;
handleActivityChange: (options: {workspaceId?: string; nextActivity: GlobalActivity}) => Promise<void>;
handleActivityChange: HandleActivityChange;
wrapperProps: WrapperProps;
}
@ -278,29 +271,20 @@ export const WrapperDesign: FC<Props> = ({
<RenderPageHeader
gitSyncDropdown={gitSyncDropdown}
handleActivityChange={handleActivityChange}
wrapperProps={wrapperProps}
/>
), [gitSyncDropdown, handleActivityChange, wrapperProps]);
), [gitSyncDropdown, handleActivityChange]);
const renderEditor = useCallback(() => (
<RenderEditor
editor={editor}
wrapperProps={wrapperProps}
/>
), [editor, wrapperProps]);
<RenderEditor editor={editor} />
), [editor]);
const renderPreview = useCallback(() => (
<RenderPreview
wrapperProps={wrapperProps}
/>
), [wrapperProps]);
<RenderPreview />
), []);
const renderPageSidebar = useCallback(() => (
<RenderPageSidebar
editor={editor}
wrapperProps={wrapperProps}
/>
), [editor, wrapperProps]);
<RenderPageSidebar editor={editor} />
), [editor]);
return (
<PageLayout

View File

@ -14,7 +14,6 @@ import { isEmpty } from 'ramda';
import React, { PureComponent, ReactNode } from 'react';
import { SegmentEvent, trackSegmentEvent } from '../../common/analytics';
import type { GlobalActivity } from '../../common/constants';
import { AUTOBIND_CFG } from '../../common/constants';
import { documentationLinks } from '../../common/documentation';
import { getSendRequestCallback } from '../../common/send-request';
@ -33,12 +32,12 @@ import { EmptyStatePane } from './panes/empty-state-pane';
import type { SidebarChildObjects } from './sidebar/sidebar-children';
import { UnitTestEditable } from './unit-test-editable';
import { WorkspacePageHeader } from './workspace-page-header';
import type { WrapperProps } from './wrapper';
import type { HandleActivityChange, WrapperProps } from './wrapper';
interface Props {
children: SidebarChildObjects;
gitSyncDropdown: ReactNode;
handleActivityChange: (options: {workspaceId?: string; nextActivity: GlobalActivity}) => Promise<void>;
handleActivityChange: HandleActivityChange;
wrapperProps: WrapperProps;
}
@ -546,10 +545,9 @@ export class WrapperUnitTest extends PureComponent<Props, State> {
}
_renderPageHeader() {
const { wrapperProps, gitSyncDropdown, handleActivityChange } = this.props;
const { gitSyncDropdown, handleActivityChange } = this.props;
return (
<WorkspacePageHeader
wrapperProps={wrapperProps}
handleActivityChange={handleActivityChange}
gridRight={gitSyncDropdown}
/>

View File

@ -122,6 +122,11 @@ export type WrapperProps = AppProps & {
gitVCS: GitVCS | null;
};
export type HandleActivityChange = (options: {
workspaceId?: string;
nextActivity: GlobalActivity;
}) => Promise<void>;
interface State {
forceRefreshKey: number;
activeGitBranch: string;
@ -213,7 +218,7 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
return null;
}
async _handleWorkspaceActivityChange({ workspaceId, nextActivity }: {workspaceId?: string; nextActivity: GlobalActivity}) {
async _handleWorkspaceActivityChange({ workspaceId, nextActivity }: Parameters<HandleActivityChange>[0]): ReturnType<HandleActivityChange> {
const { activity, activeApiSpec, handleSetActiveActivity } = this.props;
// Remember last activity on workspace for later, but only if it isn't HOME

View File

@ -44,6 +44,7 @@ import {
TAB_INDEX_THEMES,
} from '../../components/modals/settings-modal';
import { selectActiveProjectName, selectStats, selectWorkspacesForActiveProject } from '../selectors';
import { RootState } from '.';
import { importUri } from './import';
import { activateWorkspace } from './workspace';
@ -180,6 +181,8 @@ export const reducer = combineReducers<GlobalState>({
isLoggedIn: loginStateChangeReducer,
});
export const selectIsLoading = (state: RootState) => state.global.isLoading;
// ~~~~~~~ //
// ACTIONS //
// ~~~~~~~ //