mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-23 04:35:40 +00:00
add: manage workspace (#6424)
* add: manage workspace * fixes * replace dropdown to MenuDropdown * rm: refs
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import { IconCheck, IconChevronDown, IconFolder, IconHome, IconPin, IconPinned, IconPlus, IconUpload } from '@tabler/icons';
|
||||
import { IconCheck, IconChevronDown, IconFolder, IconHome, IconPin, IconPinned, IconPlus, IconUpload, IconSettings } from '@tabler/icons';
|
||||
import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { savePreferences, showHomePage, toggleSidebarCollapse } from 'providers/ReduxStore/slices/app';
|
||||
import { savePreferences, showHomePage, showManageWorkspacePage, toggleSidebarCollapse } from 'providers/ReduxStore/slices/app';
|
||||
import { closeConsole, openConsole } from 'providers/ReduxStore/slices/logs';
|
||||
import { openWorkspaceDialog, switchWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
||||
import { sortWorkspaces, toggleWorkspacePin } from 'utils/workspaces';
|
||||
@@ -90,6 +90,10 @@ const AppTitleBar = () => {
|
||||
setCreateWorkspaceModalOpen(true);
|
||||
};
|
||||
|
||||
const handleManageWorkspaces = () => {
|
||||
dispatch(showManageWorkspacePage());
|
||||
};
|
||||
|
||||
const handleImportWorkspace = () => {
|
||||
setImportWorkspaceModalOpen(true);
|
||||
};
|
||||
@@ -166,6 +170,12 @@ const AppTitleBar = () => {
|
||||
leftSection: IconUpload,
|
||||
label: 'Import workspace',
|
||||
onClick: handleImportWorkspace
|
||||
},
|
||||
{
|
||||
id: 'manage-workspaces',
|
||||
leftSection: IconSettings,
|
||||
label: 'Manage workspaces',
|
||||
onClick: handleManageWorkspaces
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import React, { useState } from 'react';
|
||||
import Portal from 'components/Portal/index';
|
||||
import Modal from 'components/Modal/index';
|
||||
import toast from 'react-hot-toast';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { IconFolder } from '@tabler/icons';
|
||||
import { closeWorkspaceAction } from 'providers/ReduxStore/slices/workspaces/actions';
|
||||
|
||||
const DeleteWorkspace = ({ onClose, workspace }) => {
|
||||
const dispatch = useDispatch();
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
|
||||
const onConfirm = async () => {
|
||||
if (isDeleting) return;
|
||||
|
||||
try {
|
||||
setIsDeleting(true);
|
||||
await dispatch(closeWorkspaceAction(workspace.uid));
|
||||
onClose();
|
||||
} catch (error) {
|
||||
toast.error(error?.message || 'An error occurred while removing the workspace');
|
||||
setIsDeleting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Portal>
|
||||
<Modal
|
||||
size="sm"
|
||||
title="Remove Workspace"
|
||||
confirmText={isDeleting ? 'Removing...' : 'Remove'}
|
||||
handleConfirm={onConfirm}
|
||||
handleCancel={onClose}
|
||||
confirmDisabled={isDeleting}
|
||||
confirmButtonClass="btn-danger"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<IconFolder size={18} strokeWidth={1.5} />
|
||||
<span className="ml-2 mr-4 font-semibold">{workspace?.name}</span>
|
||||
</div>
|
||||
{workspace?.pathname && (
|
||||
<div className="break-words text-xs mt-1">{workspace.pathname}</div>
|
||||
)}
|
||||
<div className="mt-4">
|
||||
Are you sure you want to remove workspace <span className="font-semibold">{workspace?.name}</span>?
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
The workspace will still be available in the file system and can be re-opened later.
|
||||
</div>
|
||||
</Modal>
|
||||
</Portal>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteWorkspace;
|
||||
@@ -0,0 +1,95 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import Portal from 'components/Portal/index';
|
||||
import Modal from 'components/Modal/index';
|
||||
import toast from 'react-hot-toast';
|
||||
import { useFormik } from 'formik';
|
||||
import * as Yup from 'yup';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { renameWorkspaceAction } from 'providers/ReduxStore/slices/workspaces/actions';
|
||||
|
||||
const RenameWorkspace = ({ onClose, workspace }) => {
|
||||
const dispatch = useDispatch();
|
||||
const { workspaces } = useSelector((state) => state.workspaces);
|
||||
const inputRef = useRef();
|
||||
|
||||
const formik = useFormik({
|
||||
enableReinitialize: true,
|
||||
initialValues: {
|
||||
name: workspace.name
|
||||
},
|
||||
validationSchema: Yup.object({
|
||||
name: Yup.string()
|
||||
.min(1, 'must be at least 1 character')
|
||||
.max(255, 'must be 255 characters or less')
|
||||
.required('name is required')
|
||||
.test('unique-name', 'A workspace with this name already exists', function (value) {
|
||||
if (!value) return true;
|
||||
return !workspaces.some((w) =>
|
||||
w.uid !== workspace.uid && w.name.toLowerCase() === value.toLowerCase()
|
||||
);
|
||||
})
|
||||
}),
|
||||
onSubmit: (values) => {
|
||||
if (values.name === workspace.name) {
|
||||
onClose();
|
||||
return;
|
||||
}
|
||||
dispatch(renameWorkspaceAction(workspace.uid, values.name))
|
||||
.then(() => {
|
||||
onClose();
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error(error?.message || 'An error occurred while renaming the workspace');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (inputRef && inputRef.current) {
|
||||
inputRef.current.focus();
|
||||
inputRef.current.select();
|
||||
}
|
||||
}, [inputRef]);
|
||||
|
||||
const onSubmit = () => {
|
||||
formik.handleSubmit();
|
||||
};
|
||||
|
||||
return (
|
||||
<Portal>
|
||||
<Modal
|
||||
size="sm"
|
||||
title="Rename Workspace"
|
||||
confirmText="Rename"
|
||||
handleConfirm={onSubmit}
|
||||
handleCancel={onClose}
|
||||
>
|
||||
<form className="bruno-form" onSubmit={(e) => e.preventDefault()}>
|
||||
<div>
|
||||
<label htmlFor="workspace-name" className="block font-semibold">
|
||||
Workspace Name
|
||||
</label>
|
||||
<input
|
||||
id="workspace-name"
|
||||
type="text"
|
||||
name="name"
|
||||
ref={inputRef}
|
||||
className="block textbox mt-2 w-full"
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
autoCapitalize="off"
|
||||
spellCheck="false"
|
||||
onChange={formik.handleChange}
|
||||
value={formik.values.name || ''}
|
||||
/>
|
||||
{formik.touched.name && formik.errors.name ? (
|
||||
<div className="text-red-500">{formik.errors.name}</div>
|
||||
) : null}
|
||||
</div>
|
||||
</form>
|
||||
</Modal>
|
||||
</Portal>
|
||||
);
|
||||
};
|
||||
|
||||
export default RenameWorkspace;
|
||||
@@ -0,0 +1,175 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.manage-workspace-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid ${(props) => props.theme.workspace.border};
|
||||
}
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
color: ${(props) => props.theme.text};
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: ${(props) => props.theme.text};
|
||||
}
|
||||
|
||||
.create-workspace-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 12px;
|
||||
border-radius: ${(props) => props.theme.border.radius.base};
|
||||
background: ${(props) => props.theme.workspace.accent};
|
||||
color: white;
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.workspace-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.workspace-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid ${(props) => props.theme.workspace.border};
|
||||
}
|
||||
|
||||
.workspace-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.workspace-name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.workspace-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
&.default {
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
}
|
||||
|
||||
&.regular {
|
||||
color: ${(props) => props.theme.workspace.accent};
|
||||
}
|
||||
}
|
||||
|
||||
.workspace-name {
|
||||
font-size: ${(props) => props.theme.font.size.md};
|
||||
font-weight: 500;
|
||||
color: ${(props) => props.theme.text};
|
||||
}
|
||||
|
||||
.default-badge {
|
||||
padding: 1px 6px;
|
||||
border-radius: ${(props) => props.theme.border.radius.sm};
|
||||
background: ${(props) => props.theme.sidebar.badge.bg};
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.workspace-path {
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.workspace-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 4px 8px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: ${(props) => props.theme.text};
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.more-actions-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: ${(props) => props.theme.text};
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
color: ${(props) => props.theme.text};
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
|
||||
&.danger {
|
||||
color: ${(props) => props.theme.colors.text.danger};
|
||||
}
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 200px;
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
162
packages/bruno-app/src/components/ManageWorkspace/index.js
Normal file
162
packages/bruno-app/src/components/ManageWorkspace/index.js
Normal file
@@ -0,0 +1,162 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { IconArrowLeft, IconPlus, IconFolder, IconLock, IconDots, IconCategory, IconLogin } from '@tabler/icons';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
import { showHomePage } from 'providers/ReduxStore/slices/app';
|
||||
import { switchWorkspace } from 'providers/ReduxStore/slices/workspaces/actions';
|
||||
import { showInFolder } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import { sortWorkspaces } from 'utils/workspaces';
|
||||
|
||||
import CreateWorkspace from 'components/WorkspaceSidebar/CreateWorkspace';
|
||||
import RenameWorkspace from './RenameWorkspace';
|
||||
import DeleteWorkspace from './DeleteWorkspace';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import MenuDropdown from 'ui/MenuDropdown/index';
|
||||
|
||||
const ManageWorkspace = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { workspaces, activeWorkspaceUid } = useSelector((state) => state.workspaces);
|
||||
const preferences = useSelector((state) => state.app.preferences);
|
||||
|
||||
const [createWorkspaceModalOpen, setCreateWorkspaceModalOpen] = useState(false);
|
||||
const [renameWorkspaceModal, setRenameWorkspaceModal] = useState({ open: false, workspace: null });
|
||||
const [deleteWorkspaceModal, setDeleteWorkspaceModal] = useState({ open: false, workspace: null });
|
||||
|
||||
const sortedWorkspaces = useMemo(() => {
|
||||
return sortWorkspaces(workspaces, preferences);
|
||||
}, [workspaces, preferences]);
|
||||
|
||||
const handleBack = () => {
|
||||
dispatch(showHomePage());
|
||||
};
|
||||
|
||||
const handleOpenWorkspace = (workspace) => {
|
||||
dispatch(switchWorkspace(workspace.uid));
|
||||
dispatch(showHomePage());
|
||||
toast.success(`Switched to ${workspace.name}`);
|
||||
};
|
||||
|
||||
const handleShowInFolder = (workspace) => {
|
||||
if (workspace.pathname) {
|
||||
dispatch(showInFolder(workspace.pathname)).catch(() => {
|
||||
toast.error('Error opening the folder');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleRenameClick = (workspace) => {
|
||||
setRenameWorkspaceModal({ open: true, workspace });
|
||||
};
|
||||
|
||||
const handleCloseClick = (workspace) => {
|
||||
if (workspace.type === 'default') {
|
||||
toast.error('Cannot remove the default workspace');
|
||||
return;
|
||||
}
|
||||
setDeleteWorkspaceModal({ open: true, workspace });
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
{createWorkspaceModalOpen && (
|
||||
<CreateWorkspace onClose={() => setCreateWorkspaceModalOpen(false)} />
|
||||
)}
|
||||
|
||||
{renameWorkspaceModal.open && renameWorkspaceModal.workspace && (
|
||||
<RenameWorkspace
|
||||
workspace={renameWorkspaceModal.workspace}
|
||||
onClose={() => setRenameWorkspaceModal({ open: false, workspace: null })}
|
||||
/>
|
||||
)}
|
||||
|
||||
{deleteWorkspaceModal.open && deleteWorkspaceModal.workspace && (
|
||||
<DeleteWorkspace
|
||||
workspace={deleteWorkspaceModal.workspace}
|
||||
onClose={() => setDeleteWorkspaceModal({ open: false, workspace: null })}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="manage-workspace-header">
|
||||
<div className="header-left">
|
||||
<div className="back-button" onClick={handleBack}>
|
||||
<IconArrowLeft size={18} strokeWidth={1.5} />
|
||||
</div>
|
||||
<span className="header-title">Manage Workspace</span>
|
||||
</div>
|
||||
<button className="create-workspace-btn" onClick={() => setCreateWorkspaceModalOpen(true)}>
|
||||
<IconPlus size={14} strokeWidth={2} />
|
||||
<span>Create Workspace</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="workspace-list">
|
||||
{sortedWorkspaces.length === 0 ? (
|
||||
<div className="empty-state">
|
||||
<span>No workspaces found</span>
|
||||
</div>
|
||||
) : (
|
||||
sortedWorkspaces.map((workspace) => {
|
||||
const isDefault = workspace.type === 'default';
|
||||
const isActive = workspace.uid === activeWorkspaceUid;
|
||||
|
||||
return (
|
||||
<div key={workspace.uid} className="workspace-item">
|
||||
<div className="workspace-info">
|
||||
<div className="workspace-name-row">
|
||||
<span className={`workspace-icon ${isDefault ? 'default' : 'regular'}`}>
|
||||
{isDefault ? (
|
||||
<IconLock size={14} strokeWidth={1.5} />
|
||||
) : (
|
||||
<IconCategory size={14} strokeWidth={1.5} />
|
||||
)}
|
||||
</span>
|
||||
<span className="workspace-name">{workspace.name}</span>
|
||||
{isDefault && <span className="default-badge">Default</span>}
|
||||
</div>
|
||||
{workspace.pathname && (
|
||||
<div className="workspace-path">{workspace.pathname}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="workspace-actions">
|
||||
<button
|
||||
className="action-btn"
|
||||
onClick={() => handleOpenWorkspace(workspace)}
|
||||
>
|
||||
<IconLogin size={14} strokeWidth={1.5} />
|
||||
<span>Open</span>
|
||||
</button>
|
||||
{workspace.pathname && workspace.type !== 'default' && (
|
||||
<button
|
||||
className="action-btn"
|
||||
onClick={() => handleShowInFolder(workspace)}
|
||||
>
|
||||
<IconFolder size={14} strokeWidth={1.5} />
|
||||
<span>Show in folder</span>
|
||||
</button>
|
||||
)}
|
||||
{!isDefault && (
|
||||
<MenuDropdown
|
||||
placement="bottom-end"
|
||||
items={[
|
||||
{ id: 'rename', label: 'Rename', onClick: () => handleRenameClick(workspace) },
|
||||
{ id: 'remove', label: 'Remove', onClick: () => handleCloseClick(workspace) }
|
||||
]}
|
||||
>
|
||||
<button className="more-actions-btn">
|
||||
<IconDots size={14} strokeWidth={1.5} />
|
||||
</button>
|
||||
</MenuDropdown>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default ManageWorkspace;
|
||||
@@ -69,7 +69,7 @@ const CreateEnvironment = ({ onClose, onEnvironmentCreated }) => {
|
||||
>
|
||||
<form className="bruno-form" onSubmit={(e) => e.preventDefault()}>
|
||||
<div>
|
||||
<label htmlFor="name" className="block font-semibold">
|
||||
<label htmlFor="environment-name" className="block font-semibold">
|
||||
Environment Name
|
||||
</label>
|
||||
<div className="flex items-center mt-2">
|
||||
|
||||
@@ -73,7 +73,7 @@ const RenameEnvironment = ({ onClose, environment }) => {
|
||||
>
|
||||
<form className="bruno-form" onSubmit={(e) => e.preventDefault()}>
|
||||
<div>
|
||||
<label htmlFor="name" className="block font-semibold">
|
||||
<label htmlFor="environment-name" className="block font-semibold">
|
||||
Environment Name
|
||||
</label>
|
||||
<input
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import WorkspaceHome from 'components/WorkspaceHome';
|
||||
import ManageWorkspace from 'components/ManageWorkspace';
|
||||
import RequestTabs from 'components/RequestTabs';
|
||||
import RequestTabPanel from 'components/RequestTabPanel';
|
||||
import Sidebar from 'components/Sidebar';
|
||||
@@ -58,6 +59,7 @@ export default function Main() {
|
||||
const isDragging = useSelector((state) => state.app.isDragging);
|
||||
const showHomePage = useSelector((state) => state.app.showHomePage);
|
||||
const showApiSpecPage = useSelector((state) => state.app.showApiSpecPage);
|
||||
const showManageWorkspacePage = useSelector((state) => state.app.showManageWorkspacePage);
|
||||
const isConsoleOpen = useSelector((state) => state.logs.isConsoleOpen);
|
||||
const mainSectionRef = useRef(null);
|
||||
const [showRosettaBanner, setShowRosettaBanner] = useState(false);
|
||||
@@ -119,6 +121,8 @@ export default function Main() {
|
||||
<section className="flex flex-grow flex-col overflow-hidden">
|
||||
{showApiSpecPage && activeApiSpecUid ? (
|
||||
<ApiSpecPanel key={activeApiSpecUid} />
|
||||
) : showManageWorkspacePage ? (
|
||||
<ManageWorkspace />
|
||||
) : showHomePage ? (
|
||||
<WorkspaceHome />
|
||||
) : (
|
||||
|
||||
@@ -11,6 +11,7 @@ const initialState = {
|
||||
showHomePage: false,
|
||||
showPreferences: false,
|
||||
showApiSpecPage: false,
|
||||
showManageWorkspacePage: false,
|
||||
isEnvironmentSettingsModalOpen: false,
|
||||
isGlobalEnvironmentSettingsModalOpen: false,
|
||||
preferences: {
|
||||
@@ -77,10 +78,19 @@ export const appSlice = createSlice({
|
||||
showHomePage: (state) => {
|
||||
state.showHomePage = true;
|
||||
state.showApiSpecPage = false;
|
||||
state.showManageWorkspacePage = false;
|
||||
},
|
||||
hideHomePage: (state) => {
|
||||
state.showHomePage = false;
|
||||
},
|
||||
showManageWorkspacePage: (state) => {
|
||||
state.showManageWorkspacePage = true;
|
||||
state.showHomePage = false;
|
||||
state.showApiSpecPage = false;
|
||||
},
|
||||
hideManageWorkspacePage: (state) => {
|
||||
state.showManageWorkspacePage = false;
|
||||
},
|
||||
showApiSpecPage: (state) => {
|
||||
state.showHomePage = false;
|
||||
state.showPreferences = false;
|
||||
@@ -135,6 +145,8 @@ export const {
|
||||
updateGlobalEnvironmentSettingsModalVisibility,
|
||||
showHomePage,
|
||||
hideHomePage,
|
||||
showManageWorkspacePage,
|
||||
hideManageWorkspacePage,
|
||||
showApiSpecPage,
|
||||
hideApiSpecPage,
|
||||
showPreferences,
|
||||
|
||||
Reference in New Issue
Block a user