mirror of
https://github.com/Kong/insomnia
synced 2024-11-12 17:26:32 +00:00
02c65a852d
Co-authored-by: Opender Singh <opender94@gmail.com>
123 lines
4.4 KiB
TypeScript
123 lines
4.4 KiB
TypeScript
import { Dropdown, DropdownDivider, DropdownItem, SvgIcon, SvgIconProps, Tooltip } from 'insomnia-components';
|
|
import { partition } from 'ramda';
|
|
import React, { FC, useCallback, useMemo } from 'react';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import styled from 'styled-components';
|
|
|
|
import { strings } from '../../../common/strings';
|
|
import { isDefaultProject, isRemoteProject, Project, projectHasSettings } from '../../../models/project';
|
|
import { VCS } from '../../../sync/vcs/vcs';
|
|
import { useRemoteProjects } from '../../hooks/project';
|
|
import { setActiveProject } from '../../redux/modules/global';
|
|
import { createProject } from '../../redux/modules/project';
|
|
import { selectActiveProject, selectProjects } from '../../redux/selectors';
|
|
import { showModal } from '../modals';
|
|
import ProjectSettingsModal from '../modals/project-settings-modal';
|
|
import { svgPlacementHack, tooltipIconPlacementHack } from './dropdown-placement-hacks';
|
|
|
|
const Checkmark = styled(SvgIcon)({
|
|
...svgPlacementHack,
|
|
'& svg': {
|
|
fill: 'var(--color-surprise)',
|
|
},
|
|
});
|
|
|
|
const StyledSvgIcon = styled(SvgIcon)({
|
|
...svgPlacementHack,
|
|
'& svg': {
|
|
fill: 'var(--hl)',
|
|
},
|
|
});
|
|
|
|
const StyledTooltip = styled(Tooltip)({
|
|
...tooltipIconPlacementHack,
|
|
});
|
|
|
|
const TooltipIcon = ({ message, icon }: { message: string; icon: SvgIconProps['icon'] }) => (
|
|
<StyledTooltip message={message}>
|
|
<StyledSvgIcon icon={icon} />
|
|
</StyledTooltip>
|
|
);
|
|
|
|
const spinner = <i className="fa fa-spin fa-refresh" />;
|
|
const home = <TooltipIcon message={`${strings.defaultProject.singular} ${strings.project.singular} (Always ${strings.localProject.singular})`} icon="home" />;
|
|
const remoteProject = <TooltipIcon message={`${strings.remoteProject.singular} ${strings.project.singular}`} icon="globe" />;
|
|
const localProject = <TooltipIcon message={`${strings.localProject.singular} ${strings.project.singular}`} icon="laptop" />;
|
|
|
|
interface Props {
|
|
vcs?: VCS;
|
|
}
|
|
|
|
const ProjectDropdownItem: FC<{
|
|
project: Project;
|
|
isActive: boolean;
|
|
setActive: (projectId: string) => void;
|
|
}> = ({ isActive, project, setActive }) => {
|
|
const { _id, name } = project;
|
|
const isDefault = isDefaultProject(project);
|
|
const isRemote = isRemoteProject(project);
|
|
|
|
return (
|
|
<DropdownItem
|
|
key={_id}
|
|
icon={isDefault ? home : isRemote ? remoteProject : localProject}
|
|
right={isActive && <Checkmark icon="checkmark" />}
|
|
value={_id}
|
|
onClick={setActive}
|
|
>
|
|
{name}
|
|
</DropdownItem>
|
|
);
|
|
};
|
|
ProjectDropdownItem.displayName = DropdownItem.name; // This is required because the Dropdown component will otherwise silently disregard this component.
|
|
|
|
export const ProjectDropdown: FC<Props> = ({ vcs }) => {
|
|
const { loading, refresh } = useRemoteProjects(vcs);
|
|
|
|
const projects = useSelector(selectProjects);
|
|
|
|
const activeProject = useSelector(selectActiveProject);
|
|
const dispatch = useDispatch();
|
|
const setActive = useCallback((projectId: string) => dispatch(setActiveProject(projectId)), [dispatch]);
|
|
const createNew = useCallback(() => dispatch(createProject()), [dispatch]);
|
|
const showSettings = useCallback(() => showModal(ProjectSettingsModal), []);
|
|
|
|
// dropdown button
|
|
const button = useMemo(() => (
|
|
<button type="button" className="row" title={activeProject.name}>
|
|
{activeProject.name}
|
|
<i className="fa fa-caret-down space-left" />
|
|
</button>
|
|
), [activeProject]);
|
|
|
|
const renderProject = useCallback((project: Project) => (
|
|
<ProjectDropdownItem
|
|
key={project._id}
|
|
isActive={project._id === activeProject._id}
|
|
setActive={setActive}
|
|
project={project}
|
|
/>
|
|
), [setActive, activeProject._id]);
|
|
|
|
const [defaultProjects, userProjects] = partition(isDefaultProject, projects);
|
|
|
|
return (
|
|
<Dropdown renderButton={button} onOpen={refresh}>
|
|
{defaultProjects.map(renderProject)}
|
|
<DropdownDivider>All {strings.project.plural.toLowerCase()}{' '}{loading && spinner}</DropdownDivider>
|
|
{userProjects.map(renderProject)}
|
|
{projectHasSettings(activeProject) && <>
|
|
<DropdownDivider />
|
|
<DropdownItem icon={<StyledSvgIcon icon="gear" />} onClick={showSettings}>
|
|
{strings.project.singular} Settings
|
|
</DropdownItem>
|
|
</>}
|
|
|
|
<DropdownDivider />
|
|
<DropdownItem icon={<StyledSvgIcon icon="plus" />} onClick={createNew}>
|
|
Create new {strings.project.singular.toLowerCase()}
|
|
</DropdownItem>
|
|
</Dropdown>
|
|
);
|
|
};
|