Skip to content
This repository was archived by the owner on Mar 18, 2026. It is now read-only.

Commit 74c1f2c

Browse files
authored
Merge pull request #277 from X2bee/main
fix user info in ml
2 parents 295843e + d9d2265 commit 74c1f2c

8 files changed

Lines changed: 93 additions & 4 deletions

File tree

src/app/admin/components/AdminPageContent.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import MCPStation from '@/app/admin/components/mcp/MCPStation';
2727
import AdminNodeManage from '@/app/admin/components/workflows/AdminNodeManage';
2828
import AdminPromptStore from '@/app/admin/components/workflows/AdminPromptStore/AdminPromptStore';
2929
import AdminWorkflowStore from '@/app/admin/components/workflows/AdminWorkflowStore';
30+
import { MlModelWorkspaceProvider } from '@/app/ml-inference/components/MlModelWorkspaceContext';
31+
import MlModelWorkspacePage from '@/app/ml-inference/components/MlModelWorkspacePage';
3032
import {
3133
getUserSidebarItems,
3234
getWorkflowSidebarItems,
@@ -36,6 +38,7 @@ import {
3638
getSecuritySidebarItems,
3739
getMCPSidebarItems,
3840
createAdminItemClickHandler,
41+
getMLSidebarItems,
3942
} from '@/app/admin/components/adminSidebarConfig';
4043
import styles from '@/app/admin/assets/AdminPage.module.scss';
4144

@@ -117,6 +120,7 @@ const AdminPageContent: React.FC = () => {
117120
const dataItems = filterItemsByPermission(getDataSidebarItems());
118121
const securityItems = filterItemsByPermission(getSecuritySidebarItems());
119122
const mcpItems = filterItemsByPermission(getMCPSidebarItems());
123+
const MLItems = filterItemsByPermission(getMLSidebarItems())
120124

121125
// 아이템 클릭 핸들러
122126
const handleItemClick = createAdminItemClickHandler(router);
@@ -155,6 +159,8 @@ const AdminPageContent: React.FC = () => {
155159
'security-settings', 'audit-logs', 'error-logs',
156160
// MCP Items
157161
'mcp-market', 'mcp-station',
162+
// ML Items
163+
'ml-model-control', //'ml-model-healthcheck'
158164
];
159165
return validSections.includes(section);
160166
};
@@ -409,6 +415,17 @@ const AdminPageContent: React.FC = () => {
409415
<MCPStation />
410416
</AdminContentArea>
411417
);
418+
case 'ml-model-control':
419+
return (
420+
<AdminContentArea
421+
title="머신러닝 모델 관리"
422+
description="배포된 머신러닝 모델을 버전을 관리합니다."
423+
>
424+
<MlModelWorkspaceProvider admin={true}>
425+
<MlModelWorkspacePage view='inference' admin={true}/>
426+
</MlModelWorkspaceProvider>
427+
</AdminContentArea>
428+
);
412429
default:
413430
return (
414431
<AdminContentArea
@@ -435,6 +452,7 @@ const AdminPageContent: React.FC = () => {
435452
dataItems={dataItems}
436453
securityItems={securityItems}
437454
mcpItems={mcpItems}
455+
MLItems={MLItems}
438456
activeItem={activeSection}
439457
onItemClick={(itemId: string) => setActiveSection(itemId)}
440458
initialUserExpanded={['users', 'user-create', 'group-permissions'].includes(activeSection)}
@@ -444,6 +462,7 @@ const AdminPageContent: React.FC = () => {
444462
initialDataExpanded={['database', 'data-scraper', 'storage', 'backup'].includes(activeSection)}
445463
initialSecurityExpanded={['security-settings', 'audit-logs', 'error-logs', 'access-logs'].includes(activeSection)}
446464
initialMCPExpanded={['mcp-market', 'mcp-station'].includes(activeSection)}
465+
initialMLExpanded={['ml-model-control'].includes(activeSection)}
447466
/>
448467
{!isSidebarOpen && (
449468
<motion.button

src/app/admin/components/AdminSidebar.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const AdminSidebar: React.FC<AdminSidebarProps> = ({
2020
dataItems = [],
2121
securityItems = [],
2222
mcpItems = [],
23+
MLItems = [],
2324
activeItem,
2425
onItemClick,
2526
className = '',
@@ -30,6 +31,7 @@ const AdminSidebar: React.FC<AdminSidebarProps> = ({
3031
initialDataExpanded = false,
3132
initialSecurityExpanded = false,
3233
initialMCPExpanded = false,
34+
initialMLExpanded = false,
3335
}) => {
3436
const router = useRouter();
3537
const pathname = usePathname();
@@ -40,6 +42,7 @@ const AdminSidebar: React.FC<AdminSidebarProps> = ({
4042
const [isDataExpanded, setIsDataExpanded] = useState(initialDataExpanded);
4143
const [isSecurityExpanded, setIsSecurityExpanded] = useState(initialSecurityExpanded);
4244
const [isMCPExpanded, setIsMCPExpanded] = useState(initialMCPExpanded);
45+
const [isMLExpanded, setIsMLExpanded] = useState(initialMLExpanded);
4346

4447
// CookieProvider의 useAuth 훅 사용 (AuthGuard에서 이미 인증 검증을 수행하므로 refreshAuth 호출 불필요)
4548
const { user, isAuthenticated } = useAuth();
@@ -72,6 +75,7 @@ const AdminSidebar: React.FC<AdminSidebarProps> = ({
7275
const toggleDataExpanded = () => setIsDataExpanded(!isDataExpanded);
7376
const toggleSecurityExpanded = () => setIsSecurityExpanded(!isSecurityExpanded);
7477
const toggleMCPExpanded = () => setIsMCPExpanded(!isMCPExpanded);
78+
const toggleMLExpanded = () => setIsMLExpanded(!isMLExpanded);
7579

7680
const handleLogoClick = () => {
7781
onItemClick('dashboard');
@@ -346,6 +350,39 @@ const AdminSidebar: React.FC<AdminSidebarProps> = ({
346350
</nav>
347351
</>
348352
)}
353+
354+
{/* ML 섹션 */}
355+
{MLItems && MLItems.length > 0 && (
356+
<>
357+
<button
358+
className={styles.sidebarToggle}
359+
onClick={toggleMLExpanded}
360+
>
361+
<span>머신러닝</span>
362+
<span className={`${styles.toggleIcon} ${isMLExpanded ? styles.expanded : ''}`}>
363+
364+
</span>
365+
</button>
366+
367+
<nav className={`${styles.sidebarNav} ${isMLExpanded ? styles.expanded : ''}`}>
368+
{MLItems.map((item: any) => (
369+
<button
370+
key={item.id}
371+
onClick={() => onItemClick(item.id)}
372+
className={`${styles.navItem} ${activeItem === item.id ? styles.active : ''}`}
373+
>
374+
{item.icon}
375+
<div className={styles.navText}>
376+
<div className={styles.navTitle}>{item.title}</div>
377+
<div className={styles.navDescription}>
378+
{item.description}
379+
</div>
380+
</div>
381+
</button>
382+
))}
383+
</nav>
384+
</>
385+
)}
349386
</div>
350387
</motion.aside>
351388
);

src/app/admin/components/adminSidebarConfig.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
FiPieChart,
2121
FiGrid,
2222
FiLayers,
23+
FiCpu,
2324
} from 'react-icons/fi';
2425
import { AdminSidebarItem } from '@/app/admin/components/types';
2526

@@ -202,6 +203,17 @@ export const getMCPSidebarItems = (): AdminSidebarItem[] => [
202203
},
203204
];
204205

206+
export const getMLItems = ['ml-model-control'];
207+
208+
export const getMLSidebarItems = (): AdminSidebarItem[] => [
209+
{
210+
id: 'ml-model-control',
211+
title: '머신러닝 모델 관리',
212+
description: '배포된 ML 모델 관리',
213+
icon: React.createElement(FiCpu),
214+
},
215+
];
216+
205217
// 공통 아이템 클릭 핸들러 (localStorage 사용)
206218
export const createAdminItemClickHandler = (router: any) => {
207219
return (itemId: string) => {

src/app/admin/components/ml/MLModelController.tsx

Whitespace-only changes.

src/app/admin/components/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface AdminSidebarProps {
1717
dataItems?: AdminSidebarItem[];
1818
securityItems?: AdminSidebarItem[];
1919
mcpItems?: AdminSidebarItem[];
20+
MLItems?: AdminSidebarItem[];
2021
activeItem: string;
2122
onItemClick: (itemId: string) => void;
2223
className?: string;
@@ -27,6 +28,7 @@ export interface AdminSidebarProps {
2728
initialDataExpanded?: boolean;
2829
initialSecurityExpanded?: boolean;
2930
initialMCPExpanded?: boolean;
31+
initialMLExpanded?: boolean;
3032
}
3133

3234
export interface AdminContentAreaProps {

src/app/admin/components/user/AdminUserEditModal.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ const AdminUserEditModal: React.FC<AdminUserEditModalProps> = ({
8686
"security-settings", "audit-logs", "error-logs",
8787
// MCP
8888
"mcp-market", "mcp-station",
89+
// ML
90+
"ml-model-control",
8991
];
9092

9193
const availableUserSectionOptions = [
@@ -131,6 +133,9 @@ const AdminUserEditModal: React.FC<AdminUserEditModalProps> = ({
131133
// MCP
132134
"mcp-market": "MCP마켓",
133135
"mcp-station": "MCP스테이션",
136+
// ML
137+
"ml-model-control" : "머신러닝 모델 관리",
138+
//"ml-model-healthcheck" : "머신러닝 모델 헬스체크"
134139
};
135140

136141
// 유저 섹션 이름 한국어 매핑

src/app/ml-inference/components/MlModelWorkspaceContext.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ interface DeleteState {
126126
}
127127

128128
interface MlModelWorkspaceContextValue {
129+
admin: boolean;
129130
baseUrl: string;
130131
uploadEndpoint: string;
131132
inferenceEndpoint: string;
@@ -164,7 +165,12 @@ export const useMlModelWorkspace = () => {
164165
return context;
165166
};
166167

167-
export const MlModelWorkspaceProvider: React.FC<React.PropsWithChildren> = ({ children }) => {
168+
interface MlModelWorkspaceProviderProps {
169+
admin?: boolean;
170+
children?: React.ReactNode;
171+
}
172+
173+
export const MlModelWorkspaceProvider: React.FC<MlModelWorkspaceProviderProps> = ({ admin = false, children }) => {
168174
const baseUrl = API_BASE_URL ?? '';
169175
const uploadEndpoint = useMemo(() => joinUrl(baseUrl, '/api/models/upload'), [baseUrl]);
170176
const inferenceEndpoint = useMemo(() => joinUrl(baseUrl, '/api/models/infer'), [baseUrl]);
@@ -245,7 +251,12 @@ export const MlModelWorkspaceProvider: React.FC<React.PropsWithChildren> = ({ ch
245251
setSyncError(null);
246252

247253
try {
248-
const response = await apiClient(joinUrl(baseUrl, '/api/models?limit=100&offset=0'), {
254+
const queryParams = new URLSearchParams({
255+
limit: '100',
256+
offset: '0',
257+
admin: admin.toString(),
258+
});
259+
const response = await apiClient(joinUrl(baseUrl, `/api/models?${queryParams.toString()}`), {
249260
method: 'GET',
250261
});
251262

@@ -282,7 +293,7 @@ export const MlModelWorkspaceProvider: React.FC<React.PropsWithChildren> = ({ ch
282293
} finally {
283294
setIsLoadingList(false);
284295
}
285-
}, [baseUrl, mapListItemToRegisteredModel]);
296+
}, [admin, baseUrl, mapListItemToRegisteredModel]);
286297

287298
const fetchModelDetail = useCallback(async (modelId: number, options?: { silent?: boolean }) => {
288299
if (!options?.silent) {
@@ -534,6 +545,7 @@ export const MlModelWorkspaceProvider: React.FC<React.PropsWithChildren> = ({ ch
534545
}, [fetchModelDetail, selectedModelId]);
535546

536547
const contextValue = useMemo<MlModelWorkspaceContextValue>(() => ({
548+
admin,
537549
baseUrl,
538550
uploadEndpoint,
539551
inferenceEndpoint,
@@ -561,6 +573,7 @@ export const MlModelWorkspaceProvider: React.FC<React.PropsWithChildren> = ({ ch
561573
syncMessage,
562574
syncError,
563575
}), [
576+
admin,
564577
baseUrl,
565578
uploadEndpoint,
566579
inferenceEndpoint,

src/app/ml-inference/components/MlModelWorkspacePage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ const VIEW_CONFIG: Record<WorkspaceView, { title: string; description: string }>
3232

3333
interface MlModelWorkspacePageProps {
3434
view: WorkspaceView;
35+
admin?: boolean;
3536
}
3637

37-
const MlModelWorkspacePage: React.FC<MlModelWorkspacePageProps> = ({ view }) => {
38+
const MlModelWorkspacePage: React.FC<MlModelWorkspacePageProps> = ({ view, admin }) => {
3839
const { title, description } = VIEW_CONFIG[view];
3940
const headerButtons = (view === 'hub' || view === 'inference') ? null : <MlModelHeaderActions />;
4041

0 commit comments

Comments
 (0)