menubar 위치 이동

This commit is contained in:
현성필
2025-01-27 09:35:56 +09:00
parent ef11d6eaa4
commit e410aa3e92
3 changed files with 159 additions and 162 deletions
+128
View File
@@ -5,6 +5,7 @@ import APITester from './components/APITester';
import LoadTestManager from './components/LoadTestManager';
import {monacoConfig} from '@/config/monaco.js';
import LoginDialog from '@/components/LoginDialog.jsx';
import {Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarTrigger} from '@/components/ui/menubar.jsx';
window.MonacoEnvironment = monacoConfig;
@@ -18,6 +19,104 @@ const App = ({ options = { type: 'api', contextPath: '/' } }) => {
);
};
const menuConfig = [
{
id: 'response',
label: '응답관리',
items: [
{id: 'response-list', label: '응답목록', action: 'response-list'},
{id: 'response-add', label: '응답추가', action: 'response-add'}
]
},
{
id: 'request',
label: '요청관리',
items: [
{id: 'collection-add', label: '컬렉션 추가', action: 'collection-add'},
{id: 'request-add', label: '요청 추가', action: 'request-add'},
{id: 'scenario-add', label: '시나리오 추가', action: 'scenario-add'},
{id: 'variables-show', label: '변수 보기', action: 'variables-show'},
]
},
{
id: 'queue',
label: '큐관리',
items: [
{id: 'queue-status', label: '큐상태', action: 'queue-status'},
{id: 'queue-settings', label: '큐설정', action: 'queue-settings'}
]
},
{
id: 'loadtest',
label: '부하테스트',
items: [
{id: 'load-test-new', label: '새 테스트', action: 'load-test-new'},
{id: 'load-test-history', label: '테스트 이력', action: 'load-test-history'},
{id: 'load-test-reports', label: '결과 리포트', action: 'load-test-reports'}
]
},
{
id: 'system',
label: '시스템관리',
items: [
{id: 'system-settings', label: '시스템설정', action: 'system-settings'},
{id: 'user-management', label: '사용자관리', action: 'user-management'},
{type: 'separator'},
{id: 'system-logs', label: '시스템로그', action: 'system-logs'}
]
},
{
id: 'account',
label: '계정',
items: [
{id: 'change-password', label: '비밀번호변경', action: 'change-password'},
{type: 'separator'},
{id: 'logout', label: '로그아웃', action: 'logout'}
]
}
];
const MenuItem = ({item, onMenuClick}) => {
if (item.type === 'separator') {
return <MenubarSeparator/>;
}
return (
<MenubarItem onClick={() => onMenuClick(item.action)}>
{item.label}
</MenubarItem>
);
};
const handleMenuClick = async (action) => {
// Handle menu item clicks
console.log('Menu action:', action);
switch (action) {
case 'request-add':
setShowAddApi(true);
break;
case 'collection-add':
setShowAddCollection(true);
break;
case 'scenario-add':
setShowAddScenario(true);
break;
case 'variables-show':
setShowVariableModal(true);
break;
case 'logout':
const success = await handleLogout();
if (success) {
window.location.href = "/actionLogout.do";
}
break;
case 'change-password':
// Handle password change
break;
// Add other cases as needed
}
};
const AppContent = ({ options, showLogin, setShowLogin }) => {
const { isAuthenticated, setIsAuthenticated } = useAPI();
const [isInitialized, setIsInitialized] = useState(false);
@@ -59,6 +158,35 @@ const AppContent = ({ options, showLogin, setShowLogin }) => {
return (
<LoadTestProvider contextPath={options.contextPath}>
<div className="flex flex-col h-screen bg-background">
<div className="fixed top-0 left-0 right-0 z-50 bg-background border-b">
<div className="flex items-center h-14">
<div className="px-4 py-2 border-r h-full flex items-center">
<img
src="/img/logo.png"
alt="testmaster"
className="h-8 w-auto"
/>
</div>
<Menubar className="border-none flex-1">
{menuConfig.map((menu) => (
<MenubarMenu key={menu.id}>
<MenubarTrigger className="font-bold">
{menu.label}
</MenubarTrigger>
<MenubarContent>
{menu.items.map((item, index) => (
<MenuItem
key={item.id || `separator-${index}`}
item={item}
onMenuClick={handleMenuClick}
/>
))}
</MenubarContent>
</MenubarMenu>
))}
</Menubar>
</div>
</div>
{options.type === 'api' ? (
<APITester />
) : (
-130
View File
@@ -1,5 +1,4 @@
import React, {useState} from 'react';
import {Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarTrigger} from '@/components/ui/menubar';
import MainContentArea from '@/components/MainContentArea.jsx';
import {useAPI} from '@/providers/APIProvider.jsx';
import AddCollectionDialog from '@/components/api-tester/AddCollectionDialog.jsx';
@@ -8,75 +7,6 @@ import AddScenarioDialog from '@/components/api-tester/AddScenarioDialog.jsx';
import {useLoadTest} from '@/providers/LoadTestProvider.jsx';
import VariableModal from '@/components/api-tester/VariableModal.jsx';
const menuConfig = [
{
id: 'response',
label: '응답관리',
items: [
{id: 'response-list', label: '응답목록', action: 'response-list'},
{id: 'response-add', label: '응답추가', action: 'response-add'}
]
},
{
id: 'request',
label: '요청관리',
items: [
{id: 'collection-add', label: '컬렉션 추가', action: 'collection-add'},
{id: 'request-add', label: '요청 추가', action: 'request-add'},
{id: 'scenario-add', label: '시나리오 추가', action: 'scenario-add'},
{id: 'variables-show', label: '변수 보기', action: 'variables-show'},
]
},
{
id: 'queue',
label: '큐관리',
items: [
{id: 'queue-status', label: '큐상태', action: 'queue-status'},
{id: 'queue-settings', label: '큐설정', action: 'queue-settings'}
]
},
{
id: 'loadtest',
label: '부하테스트',
items: [
{id: 'load-test-new', label: '새 테스트', action: 'load-test-new'},
{id: 'load-test-history', label: '테스트 이력', action: 'load-test-history'},
{id: 'load-test-reports', label: '결과 리포트', action: 'load-test-reports'}
]
},
{
id: 'system',
label: '시스템관리',
items: [
{id: 'system-settings', label: '시스템설정', action: 'system-settings'},
{id: 'user-management', label: '사용자관리', action: 'user-management'},
{type: 'separator'},
{id: 'system-logs', label: '시스템로그', action: 'system-logs'}
]
},
{
id: 'account',
label: '계정',
items: [
{id: 'change-password', label: '비밀번호변경', action: 'change-password'},
{type: 'separator'},
{id: 'logout', label: '로그아웃', action: 'logout'}
]
}
];
const MenuItem = ({item, onMenuClick}) => {
if (item.type === 'separator') {
return <MenubarSeparator/>;
}
return (
<MenubarItem onClick={() => onMenuClick(item.action)}>
{item.label}
</MenubarItem>
);
};
const APITester = () => {
// API 모드와 시나리오 모드 상태를 관리
const [isApiMode, setIsApiMode] = useState(true);
@@ -120,68 +50,8 @@ const APITester = () => {
}
}
const handleMenuClick = async (action) => {
// Handle menu item clicks
console.log('Menu action:', action);
switch (action) {
case 'request-add':
setShowAddApi(true);
break;
case 'collection-add':
setShowAddCollection(true);
break;
case 'scenario-add':
setShowAddScenario(true);
break;
case 'variables-show':
setShowVariableModal(true);
break;
case 'logout':
const success = await handleLogout();
if (success) {
window.location.href = "/actionLogout.do";
}
break;
case 'change-password':
// Handle password change
break;
// Add other cases as needed
}
};
return (
<div className="flex flex-col h-screen">
{/* Fixed Menubar */}
<div className="fixed top-0 left-0 right-0 z-50 bg-background border-b">
<div className="flex items-center h-14">
<div className="px-4 py-2 border-r h-full flex items-center">
<img
src="/img/logo.png"
alt="testmaster"
className="h-8 w-auto"
/>
</div>
<Menubar className="border-none flex-1">
{menuConfig.map((menu) => (
<MenubarMenu key={menu.id}>
<MenubarTrigger className="font-bold">
{menu.label}
</MenubarTrigger>
<MenubarContent>
{menu.items.map((item, index) => (
<MenuItem
key={item.id || `separator-${index}`}
item={item}
onMenuClick={handleMenuClick}
/>
))}
</MenubarContent>
</MenubarMenu>
))}
</Menubar>
</div>
</div>
{/* Main content area with top padding for menubar */}
<div className="flex-1 pt-14">
+31 -32
View File
@@ -19,11 +19,10 @@ const MainContentArea = ({isApiMode, toggleMode}) => {
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [toggleMode]);
return (
<div className="h-[calc(100vh-57px)] w-full overflow-hidden">
{isApiMode ? (
@@ -107,7 +106,7 @@ const APIMode = ({
collectionName: collection.name,
server: api.server || null,
description: api.description || '',
layout: api.layout || {},
layout: api.layout || {}
};
const existingIndex = apiRequests.findIndex(
@@ -132,35 +131,35 @@ const APIMode = ({
);
return (
<SidebarProvider cookieName="sidebar-right:state" shortcut="/">
<div className="api-mode flex flex-1 h-[calc(100vh-57px)]">
<div className="navigation-sidebar min-w-[0px] border-r bg-gray-100">
<APINavigation
contextPath="/"
collections={collections} // Pass collections to APINavigation
side="left"
onApiSelect={handleOpenApi}
onNewCollection={() => {
// Handle new collection creation
}}
isApiMode={isApiMode}
onToggleMode={onToggleMode}
/>
<SidebarProvider cookieName="sidebar-right:state" shortcut="/">
<div className="api-mode flex flex-1 h-[calc(100vh-57px)]">
<div className="navigation-sidebar min-w-[0px] border-r bg-gray-100">
<APINavigation
contextPath="/"
collections={collections} // Pass collections to APINavigation
side="left"
onApiSelect={handleOpenApi}
onNewCollection={() => {
// Handle new collection creation
}}
isApiMode={isApiMode}
onToggleMode={onToggleMode}
/>
</div>
<div className="editor flex-1 h-[calc(100vh-57px)] overflow-hidden">
{apiRequests.length === 0 ? (
renderFallback() // Render fallback when no tabs exist
) : (
<APITabs
apiRequests={apiRequests}
currentIndex={currentIndex}
onTabChange={handleTabChange}
onCloseTab={handleCloseTab}
/>
)}
</div>
</div>
<div className="editor flex-1 h-[calc(100vh-57px)] overflow-hidden">
{apiRequests.length === 0 ? (
renderFallback() // Render fallback when no tabs exist
) : (
<APITabs
apiRequests={apiRequests}
currentIndex={currentIndex}
onTabChange={handleTabChange}
onCloseTab={handleCloseTab}
/>
)}
</div>
</div>
</SidebarProvider>
</SidebarProvider>
);
};