mirror of
https://github.com/Kong/insomnia
synced 2024-11-08 06:39:48 +00:00
unifies getting of workspace name in displayment (#4060)
This commit is contained in:
parent
615287ccfc
commit
e793e6f166
@ -1,19 +0,0 @@
|
|||||||
import * as models from '../../../models';
|
|
||||||
import { WorkspaceScopeKeys } from '../../workspace';
|
|
||||||
import getWorkspaceName from '../get-workspace-name';
|
|
||||||
|
|
||||||
describe('getWorkspaceName', () => {
|
|
||||||
it('returns workspace name', () => {
|
|
||||||
const w = models.workspace.init();
|
|
||||||
const s = models.apiSpec.init();
|
|
||||||
w.scope = WorkspaceScopeKeys.collection;
|
|
||||||
expect(getWorkspaceName(w, s)).toBe(w.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns api spec name', () => {
|
|
||||||
const w = models.workspace.init();
|
|
||||||
const s = models.apiSpec.init();
|
|
||||||
w.scope = WorkspaceScopeKeys.design;
|
|
||||||
expect(getWorkspaceName(w, s)).toBe(s.fileName);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,6 +0,0 @@
|
|||||||
import type { ApiSpec } from '../api-spec';
|
|
||||||
import { isDesign, Workspace } from '../workspace';
|
|
||||||
|
|
||||||
export default function getWorkspaceName(w: Workspace, s: ApiSpec) {
|
|
||||||
return isDesign(w) ? s.fileName : w.name;
|
|
||||||
}
|
|
@ -3,20 +3,23 @@ import type { ApiSpec } from '../api-spec';
|
|||||||
import * as models from '../index';
|
import * as models from '../index';
|
||||||
import { isDesign, Workspace } from '../workspace';
|
import { isDesign, Workspace } from '../workspace';
|
||||||
|
|
||||||
export async function rename(w: Workspace, s: ApiSpec, name: string) {
|
export async function rename(workspace: Workspace, apiSpec: ApiSpec, name: string) {
|
||||||
if (isDesign(w)) {
|
if (isDesign(workspace)) {
|
||||||
await models.apiSpec.update(s, {
|
await models.apiSpec.update(apiSpec, {
|
||||||
fileName: name,
|
fileName: name,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await models.workspace.update(w, {
|
await models.workspace.update(workspace, {
|
||||||
name,
|
name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function duplicate(w: Workspace, { name, parentId }: Pick<Workspace, 'name' | 'parentId'>) {
|
export async function duplicate(
|
||||||
const newWorkspace = await db.duplicate(w, {
|
workspace: Workspace,
|
||||||
|
{ name, parentId }: Pick<Workspace, 'name' | 'parentId'>,
|
||||||
|
) {
|
||||||
|
const newWorkspace = await db.duplicate(workspace, {
|
||||||
name,
|
name,
|
||||||
parentId,
|
parentId,
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { SvgIcon } from 'insomnia-components';
|
import { SvgIcon } from 'insomnia-components';
|
||||||
import React, { FC, useCallback, useState } from 'react';
|
import React, { FC, useCallback, useState } from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import { parseApiSpec } from '../../../common/api-specs';
|
import { parseApiSpec } from '../../../common/api-specs';
|
||||||
import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
||||||
import { RENDER_PURPOSE_NO_RENDER } from '../../../common/render';
|
import { RENDER_PURPOSE_NO_RENDER } from '../../../common/render';
|
||||||
import * as models from '../../../models';
|
import * as models from '../../../models';
|
||||||
import type { ApiSpec } from '../../../models/api-spec';
|
import type { ApiSpec } from '../../../models/api-spec';
|
||||||
import getWorkspaceName from '../../../models/helpers/get-workspace-name';
|
|
||||||
import * as workspaceOperations from '../../../models/helpers/workspace-operations';
|
import * as workspaceOperations from '../../../models/helpers/workspace-operations';
|
||||||
import { Project } from '../../../models/project';
|
import { Project } from '../../../models/project';
|
||||||
import type { Workspace } from '../../../models/workspace';
|
import type { Workspace } from '../../../models/workspace';
|
||||||
@ -15,6 +15,7 @@ import type { DocumentAction } from '../../../plugins';
|
|||||||
import { getDocumentActions } from '../../../plugins';
|
import { getDocumentActions } from '../../../plugins';
|
||||||
import * as pluginContexts from '../../../plugins/context';
|
import * as pluginContexts from '../../../plugins/context';
|
||||||
import { useLoadingRecord } from '../../hooks/use-loading-record';
|
import { useLoadingRecord } from '../../hooks/use-loading-record';
|
||||||
|
import { selectActiveWorkspaceName } from '../../redux/selectors';
|
||||||
import { Dropdown } from '../base/dropdown/dropdown';
|
import { Dropdown } from '../base/dropdown/dropdown';
|
||||||
import { DropdownButton } from '../base/dropdown/dropdown-button';
|
import { DropdownButton } from '../base/dropdown/dropdown-button';
|
||||||
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
|
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
|
||||||
@ -33,13 +34,15 @@ const spinner = <i className="fa fa-refresh fa-spin" />;
|
|||||||
|
|
||||||
const useWorkspaceHandlers = ({ workspace, apiSpec }: Props) => {
|
const useWorkspaceHandlers = ({ workspace, apiSpec }: Props) => {
|
||||||
const handleDuplicate = useCallback(() => {
|
const handleDuplicate = useCallback(() => {
|
||||||
showWorkspaceDuplicateModal({ workspace, apiSpec });
|
showWorkspaceDuplicateModal({ workspace });
|
||||||
}, [apiSpec, workspace]);
|
}, [workspace]);
|
||||||
|
|
||||||
|
const activeWorkspaceName = useSelector(selectActiveWorkspaceName);
|
||||||
|
|
||||||
const handleRename = useCallback(() => {
|
const handleRename = useCallback(() => {
|
||||||
showPrompt({
|
showPrompt({
|
||||||
title: `Rename ${getWorkspaceLabel(workspace).singular}`,
|
title: `Rename ${getWorkspaceLabel(workspace).singular}`,
|
||||||
defaultValue: getWorkspaceName(workspace, apiSpec),
|
defaultValue: activeWorkspaceName,
|
||||||
submitName: 'Rename',
|
submitName: 'Rename',
|
||||||
selectText: true,
|
selectText: true,
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
@ -47,13 +50,13 @@ const useWorkspaceHandlers = ({ workspace, apiSpec }: Props) => {
|
|||||||
await workspaceOperations.rename(workspace, apiSpec, name);
|
await workspaceOperations.rename(workspace, apiSpec, name);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, [apiSpec, workspace]);
|
}, [apiSpec, workspace, activeWorkspaceName]);
|
||||||
|
|
||||||
const handleDelete = useCallback(() => {
|
const handleDelete = useCallback(() => {
|
||||||
const label = getWorkspaceLabel(workspace);
|
const label = getWorkspaceLabel(workspace);
|
||||||
showModal(AskModal, {
|
showModal(AskModal, {
|
||||||
title: `Delete ${label.singular}`,
|
title: `Delete ${label.singular}`,
|
||||||
message: `Do you really want to delete "${getWorkspaceName(workspace, apiSpec)}"?`,
|
message: `Do you really want to delete "${activeWorkspaceName}"?`,
|
||||||
yesText: 'Yes',
|
yesText: 'Yes',
|
||||||
noText: 'Cancel',
|
noText: 'Cancel',
|
||||||
onDone: async (isYes: boolean) => {
|
onDone: async (isYes: boolean) => {
|
||||||
@ -65,7 +68,7 @@ const useWorkspaceHandlers = ({ workspace, apiSpec }: Props) => {
|
|||||||
await models.workspace.remove(workspace);
|
await models.workspace.remove(workspace);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, [apiSpec, workspace]);
|
}, [workspace, activeWorkspaceName]);
|
||||||
|
|
||||||
return { handleDelete, handleDuplicate, handleRename };
|
return { handleDelete, handleDuplicate, handleRename };
|
||||||
};
|
};
|
||||||
|
@ -30,9 +30,9 @@ import { SettingsModal, TAB_INDEX_EXPORT } from '../modals/settings-modal';
|
|||||||
import { WorkspaceSettingsModal } from '../modals/workspace-settings-modal';
|
import { WorkspaceSettingsModal } from '../modals/workspace-settings-modal';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
displayName: string;
|
|
||||||
activeEnvironment: Environment | null;
|
activeEnvironment: Environment | null;
|
||||||
activeWorkspace: Workspace;
|
activeWorkspace: Workspace;
|
||||||
|
activeWorkspaceName: string;
|
||||||
activeApiSpec: ApiSpec;
|
activeApiSpec: ApiSpec;
|
||||||
activeProject: Project;
|
activeProject: Project;
|
||||||
hotKeyRegistry: HotKeyRegistry;
|
hotKeyRegistry: HotKeyRegistry;
|
||||||
@ -131,7 +131,7 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
displayName,
|
activeWorkspaceName,
|
||||||
className,
|
className,
|
||||||
activeWorkspace,
|
activeWorkspace,
|
||||||
isLoading,
|
isLoading,
|
||||||
@ -157,9 +157,9 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
|
|||||||
style={{
|
style={{
|
||||||
maxWidth: '400px',
|
maxWidth: '400px',
|
||||||
}}
|
}}
|
||||||
title={displayName}
|
title={activeWorkspaceName}
|
||||||
>
|
>
|
||||||
{displayName}
|
{activeWorkspaceName}
|
||||||
</div>
|
</div>
|
||||||
<i className="fa fa-caret-down space-left" />
|
<i className="fa fa-caret-down space-left" />
|
||||||
{isLoading ? <i className="fa fa-refresh fa-spin space-left" /> : null}
|
{isLoading ? <i className="fa fa-refresh fa-spin space-left" /> : null}
|
||||||
|
@ -8,15 +8,13 @@ import { AUTOBIND_CFG } from '../../../common/constants';
|
|||||||
import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
||||||
import { strings } from '../../../common/strings';
|
import { strings } from '../../../common/strings';
|
||||||
import * as models from '../../../models';
|
import * as models from '../../../models';
|
||||||
import { ApiSpec } from '../../../models/api-spec';
|
|
||||||
import getWorkspaceName from '../../../models/helpers/get-workspace-name';
|
|
||||||
import * as workspaceOperations from '../../../models/helpers/workspace-operations';
|
import * as workspaceOperations from '../../../models/helpers/workspace-operations';
|
||||||
import { isDefaultProject, isLocalProject, isRemoteProject, Project } from '../../../models/project';
|
import { isDefaultProject, isLocalProject, isRemoteProject, Project } from '../../../models/project';
|
||||||
import { Workspace } from '../../../models/workspace';
|
import { Workspace } from '../../../models/workspace';
|
||||||
import { initializeLocalBackendProjectAndMarkForSync } from '../../../sync/vcs/initialize-backend-project';
|
import { initializeLocalBackendProjectAndMarkForSync } from '../../../sync/vcs/initialize-backend-project';
|
||||||
import { VCS } from '../../../sync/vcs/vcs';
|
import { VCS } from '../../../sync/vcs/vcs';
|
||||||
import { activateWorkspace } from '../../redux/modules/workspace';
|
import { activateWorkspace } from '../../redux/modules/workspace';
|
||||||
import { selectActiveProject, selectIsLoggedIn, selectProjects } from '../../redux/selectors';
|
import { selectActiveProject, selectActiveWorkspaceName, selectIsLoggedIn, selectProjects } from '../../redux/selectors';
|
||||||
import { Modal } from '../base/modal';
|
import { Modal } from '../base/modal';
|
||||||
import { ModalBody } from '../base/modal-body';
|
import { ModalBody } from '../base/modal-body';
|
||||||
import { ModalFooter } from '../base/modal-footer';
|
import { ModalFooter } from '../base/modal-footer';
|
||||||
@ -25,7 +23,6 @@ import { showModal } from '.';
|
|||||||
|
|
||||||
interface Options {
|
interface Options {
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
apiSpec: ApiSpec;
|
|
||||||
onDone?: () => void;
|
onDone?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +41,7 @@ const ProjectOption: FC<Project> = project => (
|
|||||||
</option>
|
</option>
|
||||||
);
|
);
|
||||||
|
|
||||||
const WorkspaceDuplicateModalInternalWithRef: ForwardRefRenderFunction<Modal, InnerProps> = ({ workspace, apiSpec, onDone, hide, vcs }, ref) => {
|
const WorkspaceDuplicateModalInternalWithRef: ForwardRefRenderFunction<Modal, InnerProps> = ({ workspace, onDone, hide, vcs }, ref) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const projects = useSelector(selectProjects);
|
const projects = useSelector(selectProjects);
|
||||||
@ -52,7 +49,7 @@ const WorkspaceDuplicateModalInternalWithRef: ForwardRefRenderFunction<Modal, In
|
|||||||
const isLoggedIn = useSelector(selectIsLoggedIn);
|
const isLoggedIn = useSelector(selectIsLoggedIn);
|
||||||
|
|
||||||
const title = `Duplicate ${getWorkspaceLabel(workspace).singular}`;
|
const title = `Duplicate ${getWorkspaceLabel(workspace).singular}`;
|
||||||
const defaultWorkspaceName = getWorkspaceName(workspace, apiSpec);
|
const activeWorkspaceName = useSelector(selectActiveWorkspaceName);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
@ -62,7 +59,7 @@ const WorkspaceDuplicateModalInternalWithRef: ForwardRefRenderFunction<Modal, In
|
|||||||
errors,
|
errors,
|
||||||
} } = useForm<FormFields>({
|
} } = useForm<FormFields>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
newName: defaultWorkspaceName,
|
newName: activeWorkspaceName,
|
||||||
projectId: activeProject._id,
|
projectId: activeProject._id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { autoBindMethodsForReact } from 'class-autobind-decorator';
|
import { autoBindMethodsForReact } from 'class-autobind-decorator';
|
||||||
import React, { FC, PureComponent, ReactNode } from 'react';
|
import React, { FC, PureComponent, ReactNode } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import { Tab, TabList, TabPanel, Tabs } from 'react-tabs';
|
import { Tab, TabList, TabPanel, Tabs } from 'react-tabs';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
@ -8,10 +9,11 @@ import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
|||||||
import { HandleGetRenderContext, HandleRender } from '../../../common/render';
|
import { HandleGetRenderContext, HandleRender } from '../../../common/render';
|
||||||
import type { ApiSpec } from '../../../models/api-spec';
|
import type { ApiSpec } from '../../../models/api-spec';
|
||||||
import type { ClientCertificate } from '../../../models/client-certificate';
|
import type { ClientCertificate } from '../../../models/client-certificate';
|
||||||
import getWorkspaceName from '../../../models/helpers/get-workspace-name';
|
|
||||||
import * as workspaceOperations from '../../../models/helpers/workspace-operations';
|
import * as workspaceOperations from '../../../models/helpers/workspace-operations';
|
||||||
import * as models from '../../../models/index';
|
import * as models from '../../../models/index';
|
||||||
import type { Workspace } from '../../../models/workspace';
|
import type { Workspace } from '../../../models/workspace';
|
||||||
|
import { RootState } from '../../redux/modules';
|
||||||
|
import { selectActiveWorkspaceName } from '../../redux/selectors';
|
||||||
import { DebouncedInput } from '../base/debounced-input';
|
import { DebouncedInput } from '../base/debounced-input';
|
||||||
import { FileInputButton } from '../base/file-input-button';
|
import { FileInputButton } from '../base/file-input-button';
|
||||||
import { Modal } from '../base/modal';
|
import { Modal } from '../base/modal';
|
||||||
@ -58,7 +60,9 @@ const CertificateField: FC<{
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Props {
|
type ReduxProps = ReturnType<typeof mapStateToProps>;
|
||||||
|
|
||||||
|
interface Props extends ReduxProps {
|
||||||
clientCertificates: ClientCertificate[];
|
clientCertificates: ClientCertificate[];
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
apiSpec: ApiSpec;
|
apiSpec: ApiSpec;
|
||||||
@ -87,7 +91,7 @@ interface State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@autoBindMethodsForReact(AUTOBIND_CFG)
|
@autoBindMethodsForReact(AUTOBIND_CFG)
|
||||||
export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
export class UnconnectedWorkspaceSettingsModal extends PureComponent<Props, State> {
|
||||||
modal: Modal | null = null;
|
modal: Modal | null = null;
|
||||||
|
|
||||||
state: State = {
|
state: State = {
|
||||||
@ -127,8 +131,8 @@ export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_handleDuplicateWorkspace() {
|
_handleDuplicateWorkspace() {
|
||||||
const { workspace, apiSpec } = this.props;
|
const { workspace } = this.props;
|
||||||
showWorkspaceDuplicateModal({ workspace, apiSpec, onDone: this.hide });
|
showWorkspaceDuplicateModal({ workspace, onDone: this.hide });
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleToggleCertificateForm() {
|
_handleToggleCertificateForm() {
|
||||||
@ -292,7 +296,7 @@ export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
|||||||
const {
|
const {
|
||||||
clientCertificates,
|
clientCertificates,
|
||||||
workspace,
|
workspace,
|
||||||
apiSpec,
|
activeWorkspaceName,
|
||||||
editorLineWrapping,
|
editorLineWrapping,
|
||||||
editorFontSize,
|
editorFontSize,
|
||||||
editorIndentSize,
|
editorIndentSize,
|
||||||
@ -333,7 +337,7 @@ export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
|||||||
type="text"
|
type="text"
|
||||||
delay={500}
|
delay={500}
|
||||||
placeholder="Awesome API"
|
placeholder="Awesome API"
|
||||||
defaultValue={getWorkspaceName(workspace, apiSpec)}
|
defaultValue={activeWorkspaceName}
|
||||||
onChange={this._handleRename}
|
onChange={this._handleRename}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
@ -539,3 +543,9 @@ export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state: RootState) => ({
|
||||||
|
activeWorkspaceName: selectActiveWorkspaceName(state),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const WorkspaceSettingsModal = connect(mapStateToProps, null, null, { forwardRef: true })(UnconnectedWorkspaceSettingsModal);
|
||||||
|
@ -8,7 +8,7 @@ import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
|||||||
import { strings } from '../../../common/strings';
|
import { strings } from '../../../common/strings';
|
||||||
import { exportAllToFile } from '../../redux/modules/global';
|
import { exportAllToFile } from '../../redux/modules/global';
|
||||||
import { importClipBoard, importFile, importUri } from '../../redux/modules/import';
|
import { importClipBoard, importFile, importUri } from '../../redux/modules/import';
|
||||||
import { selectActiveProjectName, selectActiveWorkspace } from '../../redux/selectors';
|
import { selectActiveProjectName, selectActiveWorkspace, selectActiveWorkspaceName } from '../../redux/selectors';
|
||||||
import { Dropdown } from '../base/dropdown/dropdown';
|
import { Dropdown } from '../base/dropdown/dropdown';
|
||||||
import { DropdownButton } from '../base/dropdown/dropdown-button';
|
import { DropdownButton } from '../base/dropdown/dropdown-button';
|
||||||
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
|
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
|
||||||
@ -64,6 +64,8 @@ export const ImportExport: FC<Props> = ({ hideSettingsModal }) => {
|
|||||||
hideSettingsModal();
|
hideSettingsModal();
|
||||||
}, [hideSettingsModal, activeWorkspace, dispatch]);
|
}, [hideSettingsModal, activeWorkspace, dispatch]);
|
||||||
|
|
||||||
|
const activeWorkspaceName = useSelector(selectActiveWorkspaceName);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="no-margin-top">
|
<div className="no-margin-top">
|
||||||
@ -83,7 +85,7 @@ export const ImportExport: FC<Props> = ({ hideSettingsModal }) => {
|
|||||||
<DropdownDivider>Choose Export Type</DropdownDivider>
|
<DropdownDivider>Choose Export Type</DropdownDivider>
|
||||||
{activeWorkspace && <DropdownItem onClick={showExportRequestsModal}>
|
{activeWorkspace && <DropdownItem onClick={showExportRequestsModal}>
|
||||||
<i className="fa fa-home" />
|
<i className="fa fa-home" />
|
||||||
Export the "{activeWorkspace.name}" {getWorkspaceLabel(activeWorkspace).singular}
|
Export the "{activeWorkspaceName}" {getWorkspaceLabel(activeWorkspace).singular}
|
||||||
</DropdownItem>}
|
</DropdownItem>}
|
||||||
<DropdownItem onClick={handleExportAllToFile}>
|
<DropdownItem onClick={handleExportAllToFile}>
|
||||||
<i className="fa fa-empty" />
|
<i className="fa fa-empty" />
|
||||||
|
@ -3,7 +3,7 @@ import React, { Fragment, FunctionComponent, ReactNode, useCallback } from 'reac
|
|||||||
|
|
||||||
import { ACTIVITY_HOME, GlobalActivity } from '../../common/constants';
|
import { ACTIVITY_HOME, GlobalActivity } from '../../common/constants';
|
||||||
import { strings } from '../../common/strings';
|
import { strings } from '../../common/strings';
|
||||||
import { isCollection, isDesign } from '../../models/workspace';
|
import { isDesign } from '../../models/workspace';
|
||||||
import coreLogo from '../images/insomnia-core-logo.png';
|
import coreLogo from '../images/insomnia-core-logo.png';
|
||||||
import { ActivityToggle } from './activity-toggle';
|
import { ActivityToggle } from './activity-toggle';
|
||||||
import SettingsButton from './buttons/settings-button';
|
import SettingsButton from './buttons/settings-button';
|
||||||
@ -23,6 +23,7 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
|
|||||||
wrapperProps: {
|
wrapperProps: {
|
||||||
activeApiSpec,
|
activeApiSpec,
|
||||||
activeWorkspace,
|
activeWorkspace,
|
||||||
|
activeWorkspaceName,
|
||||||
activeProject,
|
activeProject,
|
||||||
activeEnvironment,
|
activeEnvironment,
|
||||||
settings,
|
settings,
|
||||||
@ -35,18 +36,15 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
|
|||||||
[activeWorkspace, handleActivityChange],
|
[activeWorkspace, handleActivityChange],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!activeWorkspace || !activeApiSpec || !activity) {
|
if (!activeWorkspace || !activeWorkspaceName || !activeApiSpec || !activity) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const collection = isCollection(activeWorkspace);
|
|
||||||
const design = isDesign(activeWorkspace);
|
|
||||||
|
|
||||||
const workspace = (
|
const workspace = (
|
||||||
<WorkspaceDropdown
|
<WorkspaceDropdown
|
||||||
displayName={collection ? activeWorkspace.name : activeApiSpec.fileName}
|
|
||||||
activeEnvironment={activeEnvironment}
|
activeEnvironment={activeEnvironment}
|
||||||
activeWorkspace={activeWorkspace}
|
activeWorkspace={activeWorkspace}
|
||||||
|
activeWorkspaceName={activeWorkspaceName}
|
||||||
activeApiSpec={activeApiSpec}
|
activeApiSpec={activeApiSpec}
|
||||||
activeProject={activeProject}
|
activeProject={activeProject}
|
||||||
hotKeyRegistry={settings.hotKeyRegistry}
|
hotKeyRegistry={settings.hotKeyRegistry}
|
||||||
@ -69,7 +67,7 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
gridCenter={
|
gridCenter={
|
||||||
design && (
|
isDesign(activeWorkspace) && (
|
||||||
<ActivityToggle
|
<ActivityToggle
|
||||||
activity={activity}
|
activity={activity}
|
||||||
handleActivityChange={handleActivityChange}
|
handleActivityChange={handleActivityChange}
|
||||||
|
@ -52,7 +52,7 @@ import { Request, updateMimeType } from '../../models/request';
|
|||||||
import { isRequestGroup, RequestGroup } from '../../models/request-group';
|
import { isRequestGroup, RequestGroup } from '../../models/request-group';
|
||||||
import { RequestMeta } from '../../models/request-meta';
|
import { RequestMeta } from '../../models/request-meta';
|
||||||
import { Response } from '../../models/response';
|
import { Response } from '../../models/response';
|
||||||
import { isCollection, isWorkspace } from '../../models/workspace';
|
import { isWorkspace } from '../../models/workspace';
|
||||||
import { WorkspaceMeta } from '../../models/workspace-meta';
|
import { WorkspaceMeta } from '../../models/workspace-meta';
|
||||||
import * as network from '../../network/network';
|
import * as network from '../../network/network';
|
||||||
import * as plugins from '../../plugins';
|
import * as plugins from '../../plugins';
|
||||||
@ -97,6 +97,7 @@ import {
|
|||||||
} from '../redux/modules/global';
|
} from '../redux/modules/global';
|
||||||
import { importUri } from '../redux/modules/import';
|
import { importUri } from '../redux/modules/import';
|
||||||
import {
|
import {
|
||||||
|
selectActiveApiSpec,
|
||||||
selectActiveCookieJar,
|
selectActiveCookieJar,
|
||||||
selectActiveEnvironment,
|
selectActiveEnvironment,
|
||||||
selectActiveGitRepository,
|
selectActiveGitRepository,
|
||||||
@ -113,6 +114,7 @@ import {
|
|||||||
selectActiveWorkspace,
|
selectActiveWorkspace,
|
||||||
selectActiveWorkspaceClientCertificates,
|
selectActiveWorkspaceClientCertificates,
|
||||||
selectActiveWorkspaceMeta,
|
selectActiveWorkspaceMeta,
|
||||||
|
selectActiveWorkspaceName,
|
||||||
selectEntitiesLists,
|
selectEntitiesLists,
|
||||||
selectSettings,
|
selectSettings,
|
||||||
selectSyncItems,
|
selectSyncItems,
|
||||||
@ -1094,7 +1096,7 @@ class App extends PureComponent<AppProps, State> {
|
|||||||
const {
|
const {
|
||||||
activeWorkspace,
|
activeWorkspace,
|
||||||
activeProject,
|
activeProject,
|
||||||
activeApiSpec,
|
activeWorkspaceName,
|
||||||
activeEnvironment,
|
activeEnvironment,
|
||||||
activeRequest,
|
activeRequest,
|
||||||
activity,
|
activity,
|
||||||
@ -1103,9 +1105,9 @@ class App extends PureComponent<AppProps, State> {
|
|||||||
|
|
||||||
if (activity === ACTIVITY_HOME || activity === ACTIVITY_MIGRATION) {
|
if (activity === ACTIVITY_HOME || activity === ACTIVITY_MIGRATION) {
|
||||||
title = getAppName();
|
title = getAppName();
|
||||||
} else if (activeWorkspace && activeApiSpec) {
|
} else if (activeWorkspace && activeWorkspaceName) {
|
||||||
title = activeProject.name;
|
title = activeProject.name;
|
||||||
title += ` - ${isCollection(activeWorkspace) ? activeWorkspace.name : activeApiSpec.fileName}`;
|
title += ` - ${activeWorkspaceName}`;
|
||||||
|
|
||||||
if (activeEnvironment) {
|
if (activeEnvironment) {
|
||||||
title += ` (${activeEnvironment.name})`;
|
title += ` (${activeEnvironment.name})`;
|
||||||
@ -1590,6 +1592,7 @@ function mapStateToProps(state: RootState) {
|
|||||||
const workspaces = selectWorkspacesForActiveProject(state);
|
const workspaces = selectWorkspacesForActiveProject(state);
|
||||||
const activeWorkspaceMeta = selectActiveWorkspaceMeta(state);
|
const activeWorkspaceMeta = selectActiveWorkspaceMeta(state);
|
||||||
const activeWorkspace = selectActiveWorkspace(state);
|
const activeWorkspace = selectActiveWorkspace(state);
|
||||||
|
const activeWorkspaceName = selectActiveWorkspaceName(state);
|
||||||
const activeWorkspaceClientCertificates = selectActiveWorkspaceClientCertificates(state);
|
const activeWorkspaceClientCertificates = selectActiveWorkspaceClientCertificates(state);
|
||||||
const activeGitRepository = selectActiveGitRepository(state);
|
const activeGitRepository = selectActiveGitRepository(state);
|
||||||
|
|
||||||
@ -1631,7 +1634,7 @@ function mapStateToProps(state: RootState) {
|
|||||||
const syncItems = selectSyncItems(state);
|
const syncItems = selectSyncItems(state);
|
||||||
|
|
||||||
// Api spec stuff
|
// Api spec stuff
|
||||||
const activeApiSpec = apiSpecs.find(s => s.parentId === activeWorkspace?._id);
|
const activeApiSpec = selectActiveApiSpec(state);
|
||||||
|
|
||||||
// Test stuff
|
// Test stuff
|
||||||
const activeUnitTests = selectActiveUnitTests(state);
|
const activeUnitTests = selectActiveUnitTests(state);
|
||||||
@ -1643,6 +1646,7 @@ function mapStateToProps(state: RootState) {
|
|||||||
activity: activeActivity,
|
activity: activeActivity,
|
||||||
activeProject,
|
activeProject,
|
||||||
activeApiSpec,
|
activeApiSpec,
|
||||||
|
activeWorkspaceName,
|
||||||
activeCookieJar,
|
activeCookieJar,
|
||||||
activeEnvironment,
|
activeEnvironment,
|
||||||
activeGitRepository,
|
activeGitRepository,
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { globalBeforeEach } from '../../../__jest__/before-each';
|
import { globalBeforeEach } from '../../../__jest__/before-each';
|
||||||
import { reduxStateForTest } from '../../../__jest__/redux-state-for-test';
|
import { reduxStateForTest } from '../../../__jest__/redux-state-for-test';
|
||||||
|
import { ACTIVITY_DEBUG } from '../../../common/constants';
|
||||||
import * as models from '../../../models';
|
import * as models from '../../../models';
|
||||||
import { DEFAULT_PROJECT_ID, Project } from '../../../models/project';
|
import { DEFAULT_PROJECT_ID, Project } from '../../../models/project';
|
||||||
import { selectActiveProject } from '../selectors';
|
import { WorkspaceScopeKeys } from '../../../models/workspace';
|
||||||
|
import { selectActiveApiSpec, selectActiveProject, selectActiveWorkspaceName } from '../selectors';
|
||||||
|
|
||||||
describe('selectors', () => {
|
describe('selectors', () => {
|
||||||
beforeEach(globalBeforeEach);
|
beforeEach(globalBeforeEach);
|
||||||
@ -44,4 +46,98 @@ describe('selectors', () => {
|
|||||||
expect(project).toStrictEqual(expect.objectContaining<Partial<Project>>({ _id: DEFAULT_PROJECT_ID }));
|
expect(project).toStrictEqual(expect.objectContaining<Partial<Project>>({ _id: DEFAULT_PROJECT_ID }));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('selectActiveApiSpec', () => {
|
||||||
|
it('will return undefined when there is not an active workspace', async () => {
|
||||||
|
const state = await reduxStateForTest({
|
||||||
|
activeWorkspaceId: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(selectActiveApiSpec(state)).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will return throw when there is not an active apiSpec', async () => {
|
||||||
|
const workspace = await models.workspace.create({
|
||||||
|
name: 'workspace.name',
|
||||||
|
scope: WorkspaceScopeKeys.design,
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = await reduxStateForTest({
|
||||||
|
activeActivity: ACTIVITY_DEBUG,
|
||||||
|
activeWorkspaceId: workspace._id,
|
||||||
|
});
|
||||||
|
state.entities.apiSpecs = {};
|
||||||
|
|
||||||
|
const execute = () => selectActiveApiSpec(state);
|
||||||
|
expect(execute).toThrowError(`an api spec not found for the workspace ${workspace._id} (workspace.name)`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will return the apiSpec for a given workspace', async () => {
|
||||||
|
const workspace = await models.workspace.create({
|
||||||
|
name: 'workspace.name',
|
||||||
|
scope: WorkspaceScopeKeys.design,
|
||||||
|
});
|
||||||
|
const spec = await models.apiSpec.updateOrCreateForParentId(
|
||||||
|
workspace._id,
|
||||||
|
{ fileName: 'apiSpec.fileName' },
|
||||||
|
);
|
||||||
|
|
||||||
|
const state = await reduxStateForTest({
|
||||||
|
activeActivity: ACTIVITY_DEBUG,
|
||||||
|
activeWorkspaceId: workspace._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(selectActiveApiSpec(state)).toEqual(spec);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('selectActiveWorkspaceName', () => {
|
||||||
|
it('returns workspace name for collections', async () => {
|
||||||
|
const workspace = await models.workspace.create({
|
||||||
|
name: 'workspace.name',
|
||||||
|
scope: WorkspaceScopeKeys.collection,
|
||||||
|
});
|
||||||
|
// even though this shouldn't technically happen, we want to make sure the selector still makes the right decision (and ignores the api spec for collections)
|
||||||
|
await models.apiSpec.updateOrCreateForParentId(
|
||||||
|
workspace._id,
|
||||||
|
{ fileName: 'apiSpec.fileName' },
|
||||||
|
);
|
||||||
|
const state = await reduxStateForTest({
|
||||||
|
activeActivity: ACTIVITY_DEBUG,
|
||||||
|
activeWorkspaceId: workspace._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(selectActiveWorkspaceName(state)).toBe('workspace.name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns api spec name for design documents', async () => {
|
||||||
|
const workspace = await models.workspace.create({
|
||||||
|
name: 'workspace.name',
|
||||||
|
scope: WorkspaceScopeKeys.design,
|
||||||
|
});
|
||||||
|
await models.apiSpec.updateOrCreateForParentId(
|
||||||
|
workspace._id,
|
||||||
|
{ fileName: 'apiSpec.fileName' },
|
||||||
|
);
|
||||||
|
const state = await reduxStateForTest({
|
||||||
|
activeActivity: ACTIVITY_DEBUG,
|
||||||
|
activeWorkspaceId: workspace._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(selectActiveWorkspaceName(state)).toBe('apiSpec.fileName');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns undefined when there is not an active workspace', async () => {
|
||||||
|
await models.workspace.create({
|
||||||
|
name: 'workspace.name',
|
||||||
|
scope: WorkspaceScopeKeys.collection,
|
||||||
|
});
|
||||||
|
const state = await reduxStateForTest({
|
||||||
|
activeActivity: ACTIVITY_DEBUG,
|
||||||
|
activeWorkspaceId: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(selectActiveWorkspaceName(state)).toBe(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -10,6 +10,7 @@ import { DEFAULT_PROJECT_ID, isRemoteProject } from '../../models/project';
|
|||||||
import { isRequest, Request } from '../../models/request';
|
import { isRequest, Request } from '../../models/request';
|
||||||
import { isRequestGroup, RequestGroup } from '../../models/request-group';
|
import { isRequestGroup, RequestGroup } from '../../models/request-group';
|
||||||
import { UnitTestResult } from '../../models/unit-test-result';
|
import { UnitTestResult } from '../../models/unit-test-result';
|
||||||
|
import { isCollection } from '../../models/workspace';
|
||||||
import { RootState } from './modules';
|
import { RootState } from './modules';
|
||||||
|
|
||||||
type EntitiesLists = {
|
type EntitiesLists = {
|
||||||
@ -100,15 +101,10 @@ export const selectAllWorkspaces = createSelector(
|
|||||||
entities => entities.workspaces,
|
entities => entities.workspaces,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectAllApiSpecs = createSelector(
|
|
||||||
selectEntitiesLists,
|
|
||||||
entities => entities.apiSpecs,
|
|
||||||
);
|
|
||||||
|
|
||||||
export const selectWorkspacesForActiveProject = createSelector(
|
export const selectWorkspacesForActiveProject = createSelector(
|
||||||
selectAllWorkspaces,
|
selectAllWorkspaces,
|
||||||
selectActiveProject,
|
selectActiveProject,
|
||||||
(workspaces, activeProject) => workspaces.filter(w => w.parentId === activeProject._id),
|
(workspaces, activeProject) => workspaces.filter(workspace => workspace.parentId === activeProject._id),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectActiveWorkspace = createSelector(
|
export const selectActiveWorkspace = createSelector(
|
||||||
@ -118,7 +114,7 @@ export const selectActiveWorkspace = createSelector(
|
|||||||
(workspaces, activeWorkspaceId, activeActivity) => {
|
(workspaces, activeWorkspaceId, activeActivity) => {
|
||||||
// Only return an active workspace if we're in an activity
|
// Only return an active workspace if we're in an activity
|
||||||
if (activeActivity && isWorkspaceActivity(activeActivity)) {
|
if (activeActivity && isWorkspaceActivity(activeActivity)) {
|
||||||
const workspace = workspaces.find(w => w._id === activeWorkspaceId);
|
const workspace = workspaces.find(workspace => workspace._id === activeWorkspaceId);
|
||||||
return workspace;
|
return workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +131,43 @@ export const selectActiveWorkspaceMeta = createSelector(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const selectAllApiSpecs = createSelector(
|
||||||
|
selectEntitiesLists,
|
||||||
|
entities => entities.apiSpecs,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectActiveApiSpec = createSelector(
|
||||||
|
selectAllApiSpecs,
|
||||||
|
selectActiveWorkspace,
|
||||||
|
(apiSpecs, activeWorkspace) => {
|
||||||
|
if (!activeWorkspace) {
|
||||||
|
// There should never be an active api spec without an active workspace
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const activeSpec = apiSpecs.find(apiSpec => apiSpec.parentId === activeWorkspace._id);
|
||||||
|
|
||||||
|
if (!activeSpec) {
|
||||||
|
// This case should never be reached; an api spec should always exist for a given workspace.
|
||||||
|
throw new Error(`an api spec not found for the workspace ${activeWorkspace._id} (${activeWorkspace.name})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return activeSpec;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectActiveWorkspaceName = createSelector(
|
||||||
|
selectActiveWorkspace,
|
||||||
|
selectActiveApiSpec,
|
||||||
|
(activeWorkspace, activeApiSpec) => {
|
||||||
|
if (!activeWorkspace) {
|
||||||
|
// see above, but since the selectActiveWorkspace selector really can return undefined, we need to handle it here.
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isCollection(activeWorkspace) ? activeWorkspace.name : activeApiSpec?.fileName;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const selectActiveEnvironment = createSelector(
|
export const selectActiveEnvironment = createSelector(
|
||||||
selectActiveWorkspaceMeta,
|
selectActiveWorkspaceMeta,
|
||||||
selectEntitiesLists,
|
selectEntitiesLists,
|
||||||
|
Loading…
Reference in New Issue
Block a user