chore: access, endpoints to route targets

This commit is contained in:
jialin
2026-02-03 18:21:08 +08:00
parent 6d65797b4f
commit 051d9421b0
36 changed files with 411 additions and 435 deletions
+4 -4
View File
@@ -116,14 +116,14 @@ export default [
component: './maas-provider/index' component: './maas-provider/index'
}, },
{ {
name: 'accesses', name: 'routes',
path: '/models/accesses', path: '/models/routes',
key: 'accesses', key: 'routes',
icon: 'icon-captive_portal', icon: 'icon-captive_portal',
selectedIcon: 'icon-captive_portal', selectedIcon: 'icon-captive_portal',
defaultIcon: 'icon-captive_portal', defaultIcon: 'icon-captive_portal',
access: 'canSeeAdmin', access: 'canSeeAdmin',
component: './model-access/index' component: './model-routes/index'
}, },
{ {
name: 'userModels', name: 'userModels',
-25
View File
@@ -1,25 +0,0 @@
export default {
'accesses.title': 'Accesses',
'accesses.button.add': 'Add Access',
'accesses.table.accessPoints': 'Access Points',
'accesses.table.traffic': 'Traffic Share',
'accesses.table.setAsFallback': 'Set as Fallback',
'accesses.form.endpoint.title': 'Endpoints',
'accesses.form.endpoint.add': 'Add Endpoint',
'accesses.form.endpoint.fallback': 'Fallback Endpoint',
'accesses.form.endpoint.weight': 'Weight',
'accesses.form.endpoint.model': 'Model',
'accesses.form.metadata.title': 'Metadata',
'accesses.form.metadata.add': 'Add Metadata',
'accesses.table.label.fallback': 'Fallback',
'accesses.form.metadata.size': 'Size',
'accesses.form.metadata.activeSize': 'Active Size',
'accesses.form.metadata.tags': 'Tags',
'accesses.form.metadata.maxTokens': 'Max Tokens',
'accesses.form.metadata.dimension': 'Dimensions',
'accesses.form.metadata.license': 'Licenses',
'accesses.form.metadata.releaseDate': 'Release Date',
'accesses.form.metadata.languages': 'Languages',
'accesses.form.metadata.icons': 'Icon',
'accesses.form.metadata.uploadIcon': 'Upload Icon'
};
+1 -1
View File
@@ -17,7 +17,7 @@ export default {
'menu.models.benchmark': 'Benchmarks', 'menu.models.benchmark': 'Benchmarks',
'menu.models.benchmarkDetail': 'Benchmark Details', 'menu.models.benchmarkDetail': 'Benchmark Details',
'menu.models.providers': 'Providers', 'menu.models.providers': 'Providers',
'menu.models.accesses': 'Accesses', 'menu.models.routes': 'Routes',
'menu.modelCatalog': 'Catalog', 'menu.modelCatalog': 'Catalog',
'menu.resources': 'Resources', 'menu.resources': 'Resources',
'menu.apikeys': 'API Keys', 'menu.apikeys': 'API Keys',
+1 -1
View File
@@ -13,6 +13,6 @@ export default {
'providers.form.customConfig': 'Custom Configuration', 'providers.form.customConfig': 'Custom Configuration',
'providers.form.model.test': 'Test', 'providers.form.model.test': 'Test',
'providers.form.model.test.tips': 'Test Connection', 'providers.form.model.test.tips': 'Test Connection',
'providers.form.endpoint.placeholder': 'provider/models', 'providers.form.target.placeholder': 'provider/models',
'providers.form.fallback.token': 'Fallback API Keys' 'providers.form.fallback.token': 'Fallback API Keys'
}; };
+25
View File
@@ -0,0 +1,25 @@
export default {
'routes.title': 'Routes',
'routes.button.add': 'Add Route',
'routes.table.routeTargets': 'Route Targets',
'routes.table.traffic': 'Traffic Share',
'routes.table.setAsFallback': 'Set as Fallback',
'routes.form.target.title': 'Route Targets',
'routes.form.target.add': 'Add Route Target',
'routes.form.target.fallback': 'Fallback Route Target',
'routes.form.target.weight': 'Weight',
'routes.form.target.model': 'Model',
'routes.form.metadata.title': 'Metadata',
'routes.form.metadata.add': 'Add Metadata',
'routes.table.label.fallback': 'Fallback',
'routes.form.metadata.size': 'Size',
'routes.form.metadata.activeSize': 'Active Size',
'routes.form.metadata.tags': 'Tags',
'routes.form.metadata.maxTokens': 'Max Tokens',
'routes.form.metadata.dimension': 'Dimensions',
'routes.form.metadata.license': 'Licenses',
'routes.form.metadata.releaseDate': 'Release Date',
'routes.form.metadata.languages': 'Languages',
'routes.form.metadata.icons': 'Icon',
'routes.form.metadata.uploadIcon': 'Upload Icon'
};
-25
View File
@@ -1,25 +0,0 @@
export default {
'accesses.title': 'Accesses',
'accesses.button.add': 'Add Access',
'accesses.table.accessPoints': 'Access Points',
'accesses.table.traffic': 'Traffic Share',
'accesses.table.setAsFallback': 'Set as Fallback',
'accesses.form.endpoint.title': 'Endpoints',
'accesses.form.endpoint.add': 'Add Endpoint',
'accesses.form.endpoint.fallback': 'Fallback Endpoint',
'accesses.form.endpoint.weight': 'Weight',
'accesses.form.endpoint.model': 'Model',
'accesses.form.metadata.title': 'Metadata',
'accesses.form.metadata.add': 'Add Metadata',
'accesses.table.label.fallback': 'Fallback',
'accesses.form.metadata.size': 'Size',
'accesses.form.metadata.activeSize': 'Active Size',
'accesses.form.metadata.tags': 'Tags',
'accesses.form.metadata.maxTokens': 'Max Tokens',
'accesses.form.metadata.dimension': 'Dimensions',
'accesses.form.metadata.license': 'Licenses',
'accesses.form.metadata.releaseDate': 'Release Date',
'accesses.form.metadata.languages': 'Languages',
'accesses.form.metadata.icons': 'Icon',
'accesses.form.metadata.uploadIcon': 'Upload Icon'
};
+2 -1
View File
@@ -17,7 +17,7 @@ export default {
'menu.models.benchmarkDetail': 'Benchmark Details', 'menu.models.benchmarkDetail': 'Benchmark Details',
'menu.modelCatalog': 'カタログ', 'menu.modelCatalog': 'カタログ',
'menu.models.providers': 'Providers', 'menu.models.providers': 'Providers',
'menu.models.accesses': 'Accesses', 'menu.models.routes': 'Routes',
'menu.resources': 'リソース', 'menu.resources': 'リソース',
'menu.apikeys': 'APIキー', 'menu.apikeys': 'APIキー',
'menu.users': 'ユーザー', 'menu.users': 'ユーザー',
@@ -58,4 +58,5 @@ export default {
// 15. 'menu.models.benchmark': 'Benchmarks', // 15. 'menu.models.benchmark': 'Benchmarks',
// 15. 'menu.models.provider': 'Provider', // 15. 'menu.models.provider': 'Provider',
// 15. 'menu.models.providers': 'Provider', // 15. 'menu.models.providers': 'Provider',
// 16. 'menu.models.routes': 'Routes',
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+1 -1
View File
@@ -13,6 +13,6 @@ export default {
'providers.form.customConfig': 'Custom Configuration', 'providers.form.customConfig': 'Custom Configuration',
'providers.form.model.test': 'Test', 'providers.form.model.test': 'Test',
'providers.form.model.test.tips': 'Test Connection', 'providers.form.model.test.tips': 'Test Connection',
'providers.form.endpoint.placeholder': 'provider/models', 'providers.form.target.placeholder': 'provider/models',
'providers.form.fallback.token': 'Fallback API Keys' 'providers.form.fallback.token': 'Fallback API Keys'
}; };
+25
View File
@@ -0,0 +1,25 @@
export default {
'routes.title': 'Routes',
'routes.button.add': 'Add Route',
'routes.table.routeTargets': 'Route Targets',
'routes.table.traffic': 'Traffic Share',
'routes.table.setAsFallback': 'Set as Fallback',
'routes.form.target.title': 'Route Targets',
'routes.form.target.add': 'Add Route Target',
'routes.form.target.fallback': 'Fallback Route Target',
'routes.form.target.weight': 'Weight',
'routes.form.target.model': 'Model',
'routes.form.metadata.title': 'Metadata',
'routes.form.metadata.add': 'Add Metadata',
'routes.table.label.fallback': 'Fallback',
'routes.form.metadata.size': 'Size',
'routes.form.metadata.activeSize': 'Active Size',
'routes.form.metadata.tags': 'Tags',
'routes.form.metadata.maxTokens': 'Max Tokens',
'routes.form.metadata.dimension': 'Dimensions',
'routes.form.metadata.license': 'Licenses',
'routes.form.metadata.releaseDate': 'Release Date',
'routes.form.metadata.languages': 'Languages',
'routes.form.metadata.icons': 'Icon',
'routes.form.metadata.uploadIcon': 'Upload Icon'
};
-25
View File
@@ -1,25 +0,0 @@
export default {
'accesses.title': 'Accesses',
'accesses.button.add': 'Add Access',
'accesses.table.accessPoints': 'Access Points',
'accesses.table.traffic': 'Traffic Share',
'accesses.table.setAsFallback': 'Set as Fallback',
'accesses.form.endpoint.title': 'Endpoints',
'accesses.form.endpoint.add': 'Add Endpoint',
'accesses.form.endpoint.fallback': 'Fallback Endpoint',
'accesses.form.endpoint.weight': 'Weight',
'accesses.form.endpoint.model': 'Model',
'accesses.form.metadata.title': 'Metadata',
'accesses.form.metadata.add': 'Add Metadata',
'accesses.table.label.fallback': 'Fallback',
'accesses.form.metadata.size': 'Size',
'accesses.form.metadata.activeSize': 'Active Size',
'accesses.form.metadata.tags': 'Tags',
'accesses.form.metadata.maxTokens': 'Max Tokens',
'accesses.form.metadata.dimension': 'Dimensions',
'accesses.form.metadata.license': 'Licenses',
'accesses.form.metadata.releaseDate': 'Release Date',
'accesses.form.metadata.languages': 'Languages',
'accesses.form.metadata.icons': 'Icon',
'accesses.form.metadata.uploadIcon': 'Upload Icon'
};
+3 -11
View File
@@ -17,7 +17,7 @@ export default {
'menu.models.benchmarkDetail': 'Benchmark Details', 'menu.models.benchmarkDetail': 'Benchmark Details',
'menu.models.provider': 'Provider', 'menu.models.provider': 'Provider',
'menu.models.providers': 'Providers', 'menu.models.providers': 'Providers',
'menu.models.accesses': 'Accesses', 'menu.models.routes': 'Routes',
'menu.modelCatalog': 'Каталог', 'menu.modelCatalog': 'Каталог',
'menu.resources': 'Ресурсы', 'menu.resources': 'Ресурсы',
'menu.apikeys': 'API-ключи', 'menu.apikeys': 'API-ключи',
@@ -42,16 +42,8 @@ export default {
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
<<<<<<< HEAD
<<<<<<< HEAD
// 1. 'menu.models.benchmark': 'Benchmarks', // 1. 'menu.models.benchmark': 'Benchmarks',
// 2. 'menu.models.benchmarkDetail': 'Benchmark Details', // 2. 'menu.models.benchmarkDetail': 'Benchmark Details',
// 1. 'menu.models.provider': 'Provider', // 3. 'menu.models.providers': 'Providers',
======= // 4. 'menu.models.routes': 'Routes',
// 1. 'menu.models.providers': 'Provider',
>>>>>>> ddf1a270 (feat: provider lsit)
=======
// 1. 'menu.models.providers': 'Providers',
// 2. 'menu.models.accesses': 'Accesses',
>>>>>>> 11d2c02d (feat: add access list)
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+1 -1
View File
@@ -13,6 +13,6 @@ export default {
'providers.form.customConfig': 'Custom Configuration', 'providers.form.customConfig': 'Custom Configuration',
'providers.form.model.test': 'Test', 'providers.form.model.test': 'Test',
'providers.form.model.test.tips': 'Test Connection', 'providers.form.model.test.tips': 'Test Connection',
'providers.form.endpoint.placeholder': 'provider/models', 'providers.form.target.placeholder': 'provider/models',
'providers.form.fallback.token': 'Fallback API Keys' 'providers.form.fallback.token': 'Fallback API Keys'
}; };
+25
View File
@@ -0,0 +1,25 @@
export default {
'routes.title': 'Routes',
'routes.button.add': 'Add Route',
'routes.table.routeTargets': 'Route Targets',
'routes.table.traffic': 'Traffic Share',
'routes.table.setAsFallback': 'Set as Fallback',
'routes.form.target.title': 'Route Targets',
'routes.form.target.add': 'Add Route Target',
'routes.form.target.fallback': 'Fallback Route Target',
'routes.form.target.weight': 'Weight',
'routes.form.target.model': 'Model',
'routes.form.metadata.title': 'Metadata',
'routes.form.metadata.add': 'Add Metadata',
'routes.table.label.fallback': 'Fallback',
'routes.form.metadata.size': 'Size',
'routes.form.metadata.activeSize': 'Active Size',
'routes.form.metadata.tags': 'Tags',
'routes.form.metadata.maxTokens': 'Max Tokens',
'routes.form.metadata.dimension': 'Dimensions',
'routes.form.metadata.license': 'Licenses',
'routes.form.metadata.releaseDate': 'Release Date',
'routes.form.metadata.languages': 'Languages',
'routes.form.metadata.icons': 'Icon',
'routes.form.metadata.uploadIcon': 'Upload Icon'
};
-25
View File
@@ -1,25 +0,0 @@
export default {
'accesses.title': '接入',
'accesses.button.add': '添加接入',
'accesses.table.accessPoints': '接入点',
'accesses.table.traffic': '流量',
'accesses.table.setAsFallback': '降级',
'accesses.form.endpoint.title': '接入点',
'accesses.form.endpoint.add': '添加接入点',
'accesses.form.endpoint.fallback': '降级接入点',
'accesses.form.endpoint.weight': '权重',
'accesses.form.endpoint.model': '模型',
'accesses.form.metadata.title': '元数据',
'accesses.form.metadata.add': '添加元数据',
'accesses.table.label.fallback': '降级',
'accesses.form.metadata.size': '参数量',
'accesses.form.metadata.activeSize': '激活参数量',
'accesses.form.metadata.tags': '标签',
'accesses.form.metadata.maxTokens': '最大上下文长度',
'accesses.form.metadata.dimension': '维度',
'accesses.form.metadata.license': '许可证',
'accesses.form.metadata.releaseDate': '发布日期',
'accesses.form.metadata.languages': '语言',
'accesses.form.metadata.icons': '图标',
'accesses.form.metadata.uploadIcon': '上传图标'
};
+1 -1
View File
@@ -16,7 +16,7 @@ export default {
'menu.models.benchmark': '基准测试', 'menu.models.benchmark': '基准测试',
'menu.models.benchmarkDetail': '基准测试详情', 'menu.models.benchmarkDetail': '基准测试详情',
'menu.models.providers': '提供商', 'menu.models.providers': '提供商',
'menu.models.accesses': '接入', 'menu.models.routes': '路由',
'menu.modelCatalog': '模型库', 'menu.modelCatalog': '模型库',
'menu.models.catalog': '模型库', 'menu.models.catalog': '模型库',
'menu.resources': '资源', 'menu.resources': '资源',
+1 -1
View File
@@ -13,6 +13,6 @@ export default {
'providers.form.customConfig': '自定义配置', 'providers.form.customConfig': '自定义配置',
'providers.form.model.test': '测试', 'providers.form.model.test': '测试',
'providers.form.model.test.tips': '测试连接', 'providers.form.model.test.tips': '测试连接',
'providers.form.endpoint.placeholder': '提供商/模型', 'providers.form.target.placeholder': '提供商/模型',
'providers.form.fallback.token': '备用 API Key' 'providers.form.fallback.token': '备用 API Key'
}; };
+25
View File
@@ -0,0 +1,25 @@
export default {
'routes.title': '路由',
'routes.button.add': '添加路由',
'routes.table.routeTargets': '路由目标',
'routes.table.traffic': '流量',
'routes.table.setAsFallback': '降级',
'routes.form.target.title': '路由目标',
'routes.form.target.add': '添加路由目标',
'routes.form.target.fallback': '降级路由目标',
'routes.form.target.weight': '权重',
'routes.form.target.model': '模型',
'routes.form.metadata.title': '元数据',
'routes.form.metadata.add': '添加元数据',
'routes.table.label.fallback': '降级',
'routes.form.metadata.size': '参数量',
'routes.form.metadata.activeSize': '激活参数量',
'routes.form.metadata.tags': '标签',
'routes.form.metadata.maxTokens': '最大上下文长度',
'routes.form.metadata.dimension': '维度',
'routes.form.metadata.license': '许可证',
'routes.form.metadata.releaseDate': '发布日期',
'routes.form.metadata.languages': '语言',
'routes.form.metadata.icons': '图标',
'routes.form.metadata.uploadIcon': '上传图标'
};
+3 -3
View File
@@ -3,7 +3,7 @@ import { downloadFile, listFiles, listModels } from '@huggingface/hub';
import { PipelineType } from '@huggingface/tasks'; import { PipelineType } from '@huggingface/tasks';
import { request } from '@umijs/max'; import { request } from '@umijs/max';
import qs from 'query-string'; import qs from 'query-string';
import { ACCESS_API } from '../../model-access/apis'; import { MODEL_ROUTES } from '../../model-routes/apis';
import { import {
AccessControlFormData, AccessControlFormData,
BackendItem, BackendItem,
@@ -419,7 +419,7 @@ export async function queryBackendList(params?: { cluster_id: number }) {
} }
export async function queryModelAccessUserList(id: number) { export async function queryModelAccessUserList(id: number) {
return request<{ items: UserListItem[] }>(`${ACCESS_API}/${id}/access`, { return request<{ items: UserListItem[] }>(`${MODEL_ROUTES}/${id}/access`, {
method: 'GET' method: 'GET'
}); });
} }
@@ -428,7 +428,7 @@ export async function updateModelAccessUser(params: {
id: number; id: number;
data: AccessControlFormData; data: AccessControlFormData;
}) { }) {
return request(`${ACCESS_API}/${params.id}/access`, { return request(`${MODEL_ROUTES}/${params.id}/access`, {
method: 'POST', method: 'POST',
data: params.data data: params.data
}); });
-76
View File
@@ -1,76 +0,0 @@
import { request } from '@umijs/max';
import { AccessItem, AccessPointItem, FormData } from '../config/types';
export const ACCESS_API = '/model-accesses';
export const ACCESS_POINTS_API = '/model-access-endpoints';
export async function queryModelAccesses(
params: Global.SearchParams,
options?: any
) {
return request<Global.PageResponse<AccessItem>>(ACCESS_API, {
params,
method: 'GET',
cancelToken: options?.token
});
}
export async function createAccess(params: { data: FormData }) {
return request(`${ACCESS_API}`, {
method: 'POST',
data: params.data
});
}
export async function updateAccess(params: { id: number; data: FormData }) {
return request(`${ACCESS_API}/${params.id}`, {
method: 'PUT',
data: params.data
});
}
export async function deleteAccess(id: number) {
return request(`${ACCESS_API}/${id}`, {
method: 'DELETE'
});
}
export async function queryAccessPoints(params: { id: number }, options?: any) {
return request<Global.PageResponse<AccessPointItem>>(
`${ACCESS_POINTS_API}?access_id=${params.id}`,
{
method: 'GET',
params: {
page: -1
},
cancelToken: options?.token
}
);
}
export async function deleteAccessPoint(id: number) {
return request(`${ACCESS_POINTS_API}/${id}`, {
method: 'DELETE'
});
}
export async function updateAccessPoint(params: {
id: number;
data: Partial<AccessPointItem>;
}) {
return request(`${ACCESS_POINTS_API}/${params.id}`, {
method: 'PUT',
data: params.data
});
}
export async function setAccessPointAsFallback(params: {
id: number;
data: Partial<AccessPointItem>;
}) {
return request(`${ACCESS_POINTS_API}/${params.id}/set-fallback`, {
method: 'POST',
data: params.data
});
}
@@ -1,37 +0,0 @@
import { queryAccessPoints } from '../apis';
import { AccessPointItem } from '../config/types';
const useEditEndpoints = () => {
const generateEndpointData = (endpoints: AccessPointItem[]) => {
const fallbackEndpoint =
endpoints?.filter(
(ep) => ep.fallback_status_codes && ep.fallback_status_codes?.length > 0
)?.[0] || null;
const endPoints = endpoints?.filter(
(ep) =>
!ep.fallback_status_codes || ep.fallback_status_codes?.length === 0
);
return {
endpoints: endPoints,
fallbackEndpoint: fallbackEndpoint
};
};
const fetchEndpoints = async (accessId: number) => {
try {
const res = await queryAccessPoints({ id: accessId });
return res.items || [];
} catch (error) {
return [];
}
};
return {
generateEndpointData,
fetchEndpoints
};
};
export default useEditEndpoints;
+76
View File
@@ -0,0 +1,76 @@
import { request } from '@umijs/max';
import { FormData, RouteItem, RouteTarget } from '../config/types';
export const MODEL_ROUTES = '/model-routes';
export const MODEL_ROUTE_TARGETS = '/model-route-targets';
export async function queryModelRoutes(
params: Global.SearchParams,
options?: any
) {
return request<Global.PageResponse<RouteItem>>(MODEL_ROUTES, {
params,
method: 'GET',
cancelToken: options?.token
});
}
export async function createModelRoute(params: { data: FormData }) {
return request(`${MODEL_ROUTES}`, {
method: 'POST',
data: params.data
});
}
export async function updateModelRoute(params: { id: number; data: FormData }) {
return request(`${MODEL_ROUTES}/${params.id}`, {
method: 'PUT',
data: params.data
});
}
export async function deleteModelRoute(id: number) {
return request(`${MODEL_ROUTES}/${id}`, {
method: 'DELETE'
});
}
export async function queryRouteTargets(params: { id: number }, options?: any) {
return request<Global.PageResponse<RouteTarget>>(
`${MODEL_ROUTE_TARGETS}?route_id=${params.id}`,
{
method: 'GET',
params: {
page: -1
},
cancelToken: options?.token
}
);
}
export async function deleteModelRouteTarget(id: number) {
return request(`${MODEL_ROUTE_TARGETS}/${id}`, {
method: 'DELETE'
});
}
export async function updateModelRouteTarget(params: {
id: number;
data: Partial<RouteTarget>;
}) {
return request(`${MODEL_ROUTE_TARGETS}/${params.id}`, {
method: 'PUT',
data: params.data
});
}
export async function setRouteTargetAsFallback(params: {
id: number;
data: Partial<RouteTarget>;
}) {
return request(`${MODEL_ROUTE_TARGETS}/${params.id}/set-fallback`, {
method: 'POST',
data: params.data
});
}
@@ -1,9 +1,9 @@
import { PageActionType } from '@/config/types'; import { PageActionType } from '@/config/types';
import FormDrawer from '@/pages/_components/form-drawer'; import FormDrawer from '@/pages/_components/form-drawer';
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import { FormData, AccessItem as ListItem } from '../config/types'; import { FormData, RouteItem as ListItem } from '../config/types';
import ModelAccessForm from '../forms'; import ModelRouteForm from '../forms';
type AddModalProps = { type AddModalProps = {
title: string; title: string;
@@ -46,7 +46,7 @@ const AddProvider: React.FC<AddModalProps> = ({
onSubmit={handleSubmit} onSubmit={handleSubmit}
width={600} width={600}
> >
<ModelAccessForm <ModelRouteForm
ref={form} ref={form}
action={action} action={action}
currentData={currentData} currentData={currentData}
@@ -1,6 +1,6 @@
import FormDrawer from '@/pages/_components/form-drawer'; import FormDrawer from '@/pages/_components/form-drawer';
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import { FormData, AccessItem as ListItem } from '../config/types'; import { FormData, RouteItem as ListItem } from '../config/types';
import FallbackSettings from '../forms/fallback-settings'; import FallbackSettings from '../forms/fallback-settings';
type AddModalProps = { type AddModalProps = {
@@ -9,8 +9,8 @@ import { Col, Row } from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { EndpointStatus, EndpointStatusLabelMap } from '../config'; import { TargetStatus, TargetStatusValueMap } from '../config';
import { AccessPointItem } from '../config/types'; import { RouteTarget } from '../config/types';
const CellContent = styled.div` const CellContent = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
@@ -18,7 +18,7 @@ const CellContent = styled.div`
`; `;
interface ProviderModelProps { interface ProviderModelProps {
dataList: AccessPointItem[]; dataList: RouteTarget[];
onSelect: (val: any, record: any) => void; onSelect: (val: any, record: any) => void;
sourceModels: any[]; sourceModels: any[];
} }
@@ -32,7 +32,7 @@ interface AccessItemProps {
export const childActionList = [ export const childActionList = [
{ {
key: 'fallback', key: 'fallback',
label: 'accesses.table.setAsFallback', label: 'routes.table.setAsFallback',
icon: <IconFont type="icon-shield" /> icon: <IconFont type="icon-shield" />
}, },
{ {
@@ -45,7 +45,7 @@ export const childActionList = [
} }
]; ];
const AccessItem: React.FC<AccessItemProps> = ({ const RouteItem: React.FC<AccessItemProps> = ({
onSelect, onSelect,
data, data,
sourceModels sourceModels
@@ -82,7 +82,7 @@ const AccessItem: React.FC<AccessItemProps> = ({
<CellContent> <CellContent>
{data.weight > 0 && ( {data.weight > 0 && (
<AutoTooltip ghost> <AutoTooltip ghost>
{intl.formatMessage({ id: 'accesses.form.endpoint.weight' })}:{' '} {intl.formatMessage({ id: 'routes.form.target.weight' })}:{' '}
{data.weight} {data.weight}
</AutoTooltip> </AutoTooltip>
)} )}
@@ -95,7 +95,7 @@ const AccessItem: React.FC<AccessItemProps> = ({
)} )}
<span> <span>
{intl.formatMessage({ {intl.formatMessage({
id: 'accesses.table.label.fallback' id: 'routes.table.label.fallback'
})} })}
</span> </span>
</> </>
@@ -107,8 +107,8 @@ const AccessItem: React.FC<AccessItemProps> = ({
<AutoTooltip ghost> <AutoTooltip ghost>
<StatusTag <StatusTag
statusValue={{ statusValue={{
status: EndpointStatus[data.state], status: TargetStatus[data.state],
text: EndpointStatusLabelMap[data.state], text: TargetStatusValueMap[data.state],
message: '' message: ''
}} }}
/> />
@@ -140,24 +140,23 @@ const AccessItem: React.FC<AccessItemProps> = ({
); );
}; };
const AccessPoints: React.FC<ProviderModelProps> = ({ const RouteTargets: React.FC<ProviderModelProps> = ({
dataList, dataList,
onSelect, onSelect,
sourceModels sourceModels
}) => { }) => {
console.log('AccessPoints dataList:', dataList);
return ( return (
<div> <div>
{dataList.map((item, index) => ( {dataList.map((item, index) => (
<AccessItem <RouteItem
data={item} data={item}
key={index} key={index}
onSelect={onSelect} onSelect={onSelect}
sourceModels={sourceModels} sourceModels={sourceModels}
></AccessItem> ></RouteItem>
))} ))}
</div> </div>
); );
}; };
export default AccessPoints; export default RouteTargets;
@@ -2,19 +2,19 @@ import icons from '@/components/icon-font/icons';
import { StatusMaps } from '@/config'; import { StatusMaps } from '@/config';
import { StatusType } from '@/config/types'; import { StatusType } from '@/config/types';
export const EndpointsStatusValueMap: Record<string, string> = { export const TargetStatusValueMap: Record<string, string> = {
Active: 'active', Active: 'active',
Unavailable: 'unavailable' Unavailable: 'unavailable'
}; };
export const EndpointStatusLabelMap = { export const TargetStatusLabelMap = {
[EndpointsStatusValueMap.Active]: 'Active', [TargetStatusValueMap.Active]: 'Active',
[EndpointsStatusValueMap.Unavailable]: 'Unavailable' [TargetStatusValueMap.Unavailable]: 'Unavailable'
}; };
export const EndpointStatus: Record<string, StatusType> = { export const TargetStatus: Record<string, StatusType> = {
[EndpointsStatusValueMap.Active]: StatusMaps.success, [TargetStatusValueMap.Active]: StatusMaps.success,
[EndpointsStatusValueMap.Unavailable]: StatusMaps.error [TargetStatusValueMap.Unavailable]: StatusMaps.error
}; };
// actions for each row // actions for each row
@@ -4,13 +4,13 @@ export interface FormData {
categories: any[]; categories: any[];
meta: Record<string, any>; meta: Record<string, any>;
generic_proxy: boolean; generic_proxy: boolean;
fallback_endpoint: { fallback_target: {
provider_model_name?: string; provider_model_name?: string;
model_id?: number; model_id?: number;
provider_id?: number; provider_id?: number;
fallback_status_codes?: string[]; fallback_status_codes?: string[];
}; };
endpoints: { targets: {
provider_model_name?: string; provider_model_name?: string;
weight?: number | null; weight?: number | null;
model_id?: number; model_id?: number;
@@ -19,7 +19,7 @@ export interface FormData {
}[]; }[];
} }
export interface AccessItem { export interface RouteItem {
id: number; id: number;
created_at: string; created_at: string;
updated_at: string; updated_at: string;
@@ -29,12 +29,12 @@ export interface AccessItem {
categories: string[]; categories: string[];
meta: Record<string, any>; meta: Record<string, any>;
created_by_model: boolean; created_by_model: boolean;
endpoints: number; targets: number;
ready_endpoints: number; ready_targets: number;
access_policy: string; access_policy: string;
} }
export interface AccessPointItem { export interface RouteTarget {
id: number; id: number;
created_at: string; created_at: string;
updated_at: string; updated_at: string;
@@ -44,7 +44,7 @@ export interface AccessPointItem {
model_id: number; model_id: number;
provider_id: number; provider_id: number;
name: string; name: string;
access_id: number; route_id: number;
state: string; state: string;
fallback_status_codes: string[]; fallback_status_codes: string[];
} }
@@ -14,10 +14,10 @@ import {
useRef, useRef,
useState useState
} from 'react'; } from 'react';
import { FormData, AccessItem as ListItem } from '../config/types'; import { FormData, RouteItem as ListItem } from '../config/types';
import useEditEndpoints from '../hooks/use-edit-endpoints'; import useEditTargets from '../hooks/use-edit-targets';
import Basic from './basic'; import Basic from './basic';
import Endpoints from './endpoints'; import Targets from './targets';
interface ProviderFormProps { interface ProviderFormProps {
ref?: any; ref?: any;
@@ -29,7 +29,7 @@ interface ProviderFormProps {
const TABKeysMap = { const TABKeysMap = {
BASIC: 'basic', BASIC: 'basic',
METADATA: 'metadata', METADATA: 'metadata',
ENDPOINTS: 'endpoints', TARGETS: 'targets',
ADVANCED: 'advanced' ADVANCED: 'advanced'
}; };
@@ -40,8 +40,8 @@ const AccessForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
const [activeKey, setActiveKey] = useState<string[]>([TABKeysMap.BASIC]); const [activeKey, setActiveKey] = useState<string[]>([TABKeysMap.BASIC]);
const [form] = Form.useForm(); const [form] = Form.useForm();
const scrollTabsRef = useRef<any>(null); const scrollTabsRef = useRef<any>(null);
const endpointsRef = useRef<any>(null); const targetsRef = useRef<any>(null);
const { generateEndpointData, fetchEndpoints } = useEditEndpoints(); const { generateTargetData, fetchTargets } = useEditTargets();
const segmentOptions = [ const segmentOptions = [
{ {
value: TABKeysMap.BASIC, value: TABKeysMap.BASIC,
@@ -50,10 +50,10 @@ const AccessForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
field: 'name' field: 'name'
}, },
{ {
value: TABKeysMap.ENDPOINTS, value: TABKeysMap.TARGETS,
label: intl.formatMessage({ id: 'accesses.form.endpoint.title' }), label: intl.formatMessage({ id: 'routes.form.target.title' }),
icon: <IconFont type="icon-language" />, icon: <IconFont type="icon-language" />,
field: 'endpoints' field: 'targets'
} }
]; ];
@@ -61,26 +61,25 @@ const AccessForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
setActiveKey(key); setActiveKey(key);
}; };
const formatEndpoints = (values: FormData) => { const formatTargets = (values: FormData) => {
console.log('formatEndpoints values:', values); let targetList = [...(values.targets || [])];
let endPoints = [...(values.endpoints || [])]; let fallbackTarget = values.fallback_target;
let fallbackEndpoint = values.fallback_endpoint;
if (fallbackEndpoint) { if (fallbackTarget) {
const exsitinged = endPoints.find((ep) => { const exsitinged = targetList.find((ep) => {
if (fallbackEndpoint!.model_id) { if (fallbackTarget!.model_id) {
return ep.model_id === fallbackEndpoint!.model_id; return ep.model_id === fallbackTarget!.model_id;
} }
return ( return (
ep.provider_id === fallbackEndpoint!.provider_id && ep.provider_id === fallbackTarget!.provider_id &&
ep.provider_model_name === fallbackEndpoint!.provider_model_name ep.provider_model_name === fallbackTarget!.provider_model_name
); );
}); });
if (exsitinged) { if (exsitinged) {
endPoints = endPoints.map((ep) => { targetList = targetList.map((ep) => {
if ( if (
ep.model_id === fallbackEndpoint.model_id || ep.model_id === fallbackTarget.model_id ||
ep.provider_model_name === fallbackEndpoint.provider_model_name ep.provider_model_name === fallbackTarget.provider_model_name
) { ) {
return { return {
...ep, ...ep,
@@ -92,22 +91,22 @@ const AccessForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
} }
if (!exsitinged) { if (!exsitinged) {
endPoints.push({ targetList.push({
...fallbackEndpoint, ...fallbackTarget,
weight: 0, weight: 0,
fallback_status_codes: ['4xx', '5xx'] fallback_status_codes: ['4xx', '5xx']
}); });
} }
} }
return endPoints; return targetList;
}; };
const handleOnFinish = (values: FormData) => { const handleOnFinish = (values: FormData) => {
const endpoints = formatEndpoints(values); const targets = formatTargets(values);
const data = { const data = {
..._.omit(values, ['endpoints', 'fallback_endpoint']), ..._.omit(values, ['targets', 'fallback_target']),
endpoints: endpoints targets: targets
}; };
console.log('data=========', data); console.log('data=========', data);
onFinish(data); onFinish(data);
@@ -119,26 +118,19 @@ const AccessForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
useEffect(() => { useEffect(() => {
const initEditionForm = async () => { const initEditionForm = async () => {
const endpointList = await fetchEndpoints(currentData!.id); const targetList = await fetchTargets(currentData!.id);
const { endpoints, fallbackEndpoint } = const { targets, fallbackTarget } = generateTargetData(targetList);
generateEndpointData(endpointList);
console.log(
'endpoints:',
endpoints,
'fallbackEndpoint:',
fallbackEndpoint
);
// init form values // init form values
form.setFieldsValue({ form.setFieldsValue({
...currentData, ...currentData,
endpoints: endpoints, targets: targets,
fallback_endpoint: fallbackEndpoint fallback_target: fallbackTarget
}); });
// init endpoints form list // init targets form list
endpointsRef.current?.initDataList( targetsRef.current?.initDataList(
endpoints?.map((ep) => ({ targets?.map((ep) => ({
weight: ep.weight, weight: ep.weight,
value: ep.model_id value: ep.model_id
? ['deployments', ep.model_id] ? ['deployments', ep.model_id]
@@ -147,14 +139,11 @@ const AccessForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
); );
// init fallback value // init fallback value
if (fallbackEndpoint) { if (fallbackTarget) {
endpointsRef.current?.initFallbackValues({ targetsRef.current?.initFallbackValues({
value: fallbackEndpoint.model_id value: fallbackTarget.model_id
? ['deployments', fallbackEndpoint.model_id] ? ['deployments', fallbackTarget.model_id]
: [ : [fallbackTarget.provider_id, fallbackTarget.provider_model_name]
fallbackEndpoint.provider_id,
fallbackEndpoint.provider_model_name
]
}); });
} }
}; };
@@ -202,10 +191,10 @@ const AccessForm: React.FC<ProviderFormProps> = forwardRef((props, ref) => {
onChange={handleOnCollapseChange} onChange={handleOnCollapseChange}
items={[ items={[
{ {
key: TABKeysMap.ENDPOINTS, key: TABKeysMap.TARGETS,
label: intl.formatMessage({ id: 'accesses.form.endpoint.title' }), label: intl.formatMessage({ id: 'routes.form.target.title' }),
forceRender: true, forceRender: true,
children: <Endpoints ref={endpointsRef}></Endpoints> children: <Targets ref={targetsRef}></Targets>
} }
]} ]}
></CollapsePanel> ></CollapsePanel>
@@ -64,7 +64,7 @@ const MetaData = () => {
> >
<SealInputNumber <SealInputNumber
min={0} min={0}
label={`${intl.formatMessage({ id: 'accesses.form.metadata.size' })} (B)`} label={`${intl.formatMessage({ id: 'routes.form.metadata.size' })} (B)`}
></SealInputNumber> ></SealInputNumber>
</Form.Item> </Form.Item>
<Form.Item<FormData> <Form.Item<FormData>
@@ -74,7 +74,7 @@ const MetaData = () => {
<SealInputNumber <SealInputNumber
min={0} min={0}
label={`${intl.formatMessage({ label={`${intl.formatMessage({
id: 'accesses.form.metadata.activeSize' id: 'routes.form.metadata.activeSize'
})} (B)`} })} (B)`}
></SealInputNumber> ></SealInputNumber>
</Form.Item> </Form.Item>
@@ -83,7 +83,7 @@ const MetaData = () => {
<Form.Item<FormData> name={['meta', 'max_tokens']}> <Form.Item<FormData> name={['meta', 'max_tokens']}>
<SealInput.Input <SealInput.Input
label={intl.formatMessage({ label={intl.formatMessage({
id: 'accesses.form.metadata.maxTokens' id: 'routes.form.metadata.maxTokens'
})} })}
placeholder={intl.formatMessage( placeholder={intl.formatMessage(
{ id: 'common.help.eg' }, { id: 'common.help.eg' },
@@ -100,7 +100,7 @@ const MetaData = () => {
step={1} step={1}
precision={0} precision={0}
label={intl.formatMessage({ label={intl.formatMessage({
id: 'accesses.form.metadata.dimension' id: 'routes.form.metadata.dimension'
})} })}
></SealInputNumber> ></SealInputNumber>
</Form.Item> </Form.Item>
@@ -108,7 +108,7 @@ const MetaData = () => {
<Form.Item<FormData> name={['meta', 'release_date']}> <Form.Item<FormData> name={['meta', 'release_date']}>
<SealInput.Input <SealInput.Input
label={intl.formatMessage({ label={intl.formatMessage({
id: 'accesses.form.metadata.releaseDate' id: 'routes.form.metadata.releaseDate'
})} })}
placeholder={intl.formatMessage( placeholder={intl.formatMessage(
{ id: 'common.help.eg' }, { id: 'common.help.eg' },
@@ -126,7 +126,7 @@ const MetaData = () => {
</Form.Item> </Form.Item>
<Form.Item<FormData> name={['meta', 'licenses']} data-field="metadata"> <Form.Item<FormData> name={['meta', 'licenses']} data-field="metadata">
<ListInput <ListInput
label={intl.formatMessage({ id: 'accesses.form.metadata.license' })} label={intl.formatMessage({ id: 'routes.form.metadata.license' })}
btnText={intl.formatMessage({ id: 'common.button.addLabel' })} btnText={intl.formatMessage({ id: 'common.button.addLabel' })}
dataList={[]} dataList={[]}
onChange={(list: string[]) => handleMetadataChange(list, 'licenses')} onChange={(list: string[]) => handleMetadataChange(list, 'licenses')}
@@ -134,7 +134,7 @@ const MetaData = () => {
</Form.Item> </Form.Item>
<Form.Item<FormData> name={['meta', 'languages']} data-field="metadata"> <Form.Item<FormData> name={['meta', 'languages']} data-field="metadata">
<ListInput <ListInput
label={intl.formatMessage({ id: 'accesses.form.metadata.languages' })} label={intl.formatMessage({ id: 'routes.form.metadata.languages' })}
btnText={intl.formatMessage({ id: 'common.button.addLabel' })} btnText={intl.formatMessage({ id: 'common.button.addLabel' })}
dataList={[]} dataList={[]}
onChange={(list: string[]) => handleMetadataChange(list, 'languages')} onChange={(list: string[]) => handleMetadataChange(list, 'languages')}
@@ -143,7 +143,7 @@ const MetaData = () => {
<Form.Item<FormData> name={['meta', 'icon']} data-field="metadata"> <Form.Item<FormData> name={['meta', 'icon']} data-field="metadata">
<IconBox> <IconBox>
<span className="icon"> <span className="icon">
{intl.formatMessage({ id: 'accesses.form.metadata.icons' })} {intl.formatMessage({ id: 'routes.form.metadata.icons' })}
</span> </span>
<UploadWrapper> <UploadWrapper>
<UploadImg <UploadImg
@@ -161,7 +161,7 @@ const MetaData = () => {
) : ( ) : (
<Button size="middle" variant="dashed" color="default"> <Button size="middle" variant="dashed" color="default">
{intl.formatMessage({ {intl.formatMessage({
id: 'accesses.form.metadata.uploadIcon' id: 'routes.form.metadata.uploadIcon'
})} })}
</Button> </Button>
)} )}
@@ -7,7 +7,7 @@ import _ from 'lodash';
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { FormData } from '../config/types'; import { FormData } from '../config/types';
import useEndpointSourceModels from '../hooks/use-endpoint-source-models'; import useTargetSourceModels from '../hooks/use-target-source-models';
const Inner = styled.div` const Inner = styled.div`
display: flex; display: flex;
@@ -28,12 +28,11 @@ const Inner = styled.div`
} }
`; `;
const EndpointsForm = forwardRef((props, ref) => { const TargetsForm = forwardRef((props, ref) => {
const intl = useIntl(); const intl = useIntl();
const { sourceModels, loading, fetchSourceModels } = const { sourceModels, loading, fetchSourceModels } = useTargetSourceModels();
useEndpointSourceModels();
const form = Form.useFormInstance<FormData>(); const form = Form.useFormInstance<FormData>();
const endpoints = Form.useWatch('endpoints', form) || []; const targets = Form.useWatch('targets', form) || [];
const [fallbackValues, setFallbackValues] = useState<{ value: any[] }>({ const [fallbackValues, setFallbackValues] = useState<{ value: any[] }>({
value: [] value: []
}); });
@@ -58,20 +57,16 @@ const EndpointsForm = forwardRef((props, ref) => {
} }
})); }));
const handleEndpointsChange = ( const handleTargetsChange = (value: any[], index: number, options: any[]) => {
value: any[],
index: number,
options: any[]
) => {
const selectedOption = const selectedOption =
options?.find?.((opt) => opt.value === value[1]) || {}; options?.find?.((opt) => opt.value === value[1]) || {};
const endpointList = [...endpoints]; const targetList = [...targets];
endpointList[index] = { targetList[index] = {
weight: endpointList[index]?.weight || null, weight: targetList[index]?.weight || null,
...selectedOption?.data ...selectedOption?.data
}; };
form.setFieldValue('endpoints', [...endpointList]); form.setFieldValue('targets', [...targetList]);
const newDataList = [...dataList]; const newDataList = [...dataList];
newDataList[index] = { newDataList[index] = {
@@ -96,9 +91,9 @@ const EndpointsForm = forwardRef((props, ref) => {
const newDataList = dataList.filter((_, i) => i !== index); const newDataList = dataList.filter((_, i) => i !== index);
setDataList(newDataList); setDataList(newDataList);
const endpointList = [...endpoints]; const targetList = [...targets];
endpointList.splice(index, 1); targetList.splice(index, 1);
form.setFieldValue('endpoints', [...endpointList]); form.setFieldValue('targets', [...targetList]);
}; };
const handleFallbackChange = (value: any[], options?: any[]) => { const handleFallbackChange = (value: any[], options?: any[]) => {
@@ -106,7 +101,7 @@ const EndpointsForm = forwardRef((props, ref) => {
options?.find?.((opt) => opt.value === value[1]) || {}; options?.find?.((opt) => opt.value === value[1]) || {};
console.log('fallback selected option data:', value); console.log('fallback selected option data:', value);
form.setFieldValue('fallback_endpoint', { form.setFieldValue('fallback_target', {
...selectedOption?.data ...selectedOption?.data
}); });
setFallbackValues({ setFallbackValues({
@@ -115,13 +110,13 @@ const EndpointsForm = forwardRef((props, ref) => {
}; };
const handleOnWeightChange = (value: any, index: number) => { const handleOnWeightChange = (value: any, index: number) => {
const endpointList = [...endpoints]; const targetList = [...targets];
if (endpointList[index]) { if (targetList[index]) {
endpointList[index] = { targetList[index] = {
...endpointList[index], ...targetList[index],
weight: value weight: value
}; };
form.setFieldValue('endpoints', [...endpointList]); form.setFieldValue('targets', [...targetList]);
} }
const newDataList = [...dataList]; const newDataList = [...dataList];
@@ -139,8 +134,8 @@ const EndpointsForm = forwardRef((props, ref) => {
return ( return (
<> <>
<Form.Item <Form.Item
name="endpoints" name="targets"
data-field="endpoints" data-field="targets"
rules={[ rules={[
({ getFieldValue }) => ({ ({ getFieldValue }) => ({
validator(rule, value) { validator(rule, value) {
@@ -173,7 +168,7 @@ const EndpointsForm = forwardRef((props, ref) => {
} }
}} }}
dataList={dataList} dataList={dataList}
btnText={intl.formatMessage({ id: 'accesses.form.endpoint.add' })} btnText={intl.formatMessage({ id: 'routes.form.target.add' })}
onAdd={handleOnAdd} onAdd={handleOnAdd}
onDelete={handleOnDelete} onDelete={handleOnDelete}
> >
@@ -186,7 +181,7 @@ const EndpointsForm = forwardRef((props, ref) => {
multiple={false} multiple={false}
alwaysFocus={true} alwaysFocus={true}
onChange={(value, options) => onChange={(value, options) =>
handleEndpointsChange(value, index, options) handleTargetsChange(value, index, options)
} }
classNames={{ classNames={{
popup: { popup: {
@@ -195,7 +190,7 @@ const EndpointsForm = forwardRef((props, ref) => {
}} }}
maxTagCount={1} maxTagCount={1}
placeholder={intl.formatMessage({ placeholder={intl.formatMessage({
id: 'providers.form.endpoint.placeholder' id: 'providers.form.target.placeholder'
})} })}
value={item.value} value={item.value}
options={sourceModels} options={sourceModels}
@@ -209,14 +204,14 @@ const EndpointsForm = forwardRef((props, ref) => {
value={item.weight} value={item.weight}
onChange={(value) => handleOnWeightChange(value, index)} onChange={(value) => handleOnWeightChange(value, index)}
placeholder={intl.formatMessage({ placeholder={intl.formatMessage({
id: 'accesses.form.endpoint.weight' id: 'routes.form.target.weight'
})} })}
></SealInput.Number> ></SealInput.Number>
</> </>
)} )}
</MetadataList> </MetadataList>
</Form.Item> </Form.Item>
<Form.Item name="fallback_endpoint"> <Form.Item name="fallback_target">
<div> <div>
<SealCascader <SealCascader
showSearch showSearch
@@ -229,10 +224,10 @@ const EndpointsForm = forwardRef((props, ref) => {
} }
}} }}
label={intl.formatMessage({ label={intl.formatMessage({
id: 'accesses.form.endpoint.fallback' id: 'routes.form.target.fallback'
})} })}
placeholder={intl.formatMessage({ placeholder={intl.formatMessage({
id: 'providers.form.endpoint.placeholder' id: 'providers.form.target.placeholder'
})} })}
maxTagCount={1} maxTagCount={1}
value={fallbackValues.value} value={fallbackValues.value}
@@ -247,4 +242,4 @@ const EndpointsForm = forwardRef((props, ref) => {
); );
}); });
export default EndpointsForm; export default TargetsForm;
@@ -1,7 +1,7 @@
import { PageAction } from '@/config'; import { PageAction } from '@/config';
import { PageActionType } from '@/config/types'; import { PageActionType } from '@/config/types';
import { useState } from 'react'; import { useState } from 'react';
import { AccessItem as ListItem } from '../config/types'; import { RouteItem as ListItem } from '../config/types';
const useAccessControl = () => { const useAccessControl = () => {
const [openModalStatus, setOpenModalStatus] = useState<{ const [openModalStatus, setOpenModalStatus] = useState<{
@@ -1,9 +1,9 @@
import { PageAction } from '@/config'; import { PageAction } from '@/config';
import { PageActionType } from '@/config/types'; import { PageActionType } from '@/config/types';
import { useState } from 'react'; import { useState } from 'react';
import { AccessItem as ListItem } from '../config/types'; import { RouteItem as ListItem } from '../config/types';
const useCreateAccess = (options?: { refresh: () => void }) => { const useCreateRoute = (options?: { refresh: () => void }) => {
const [openModalStatus, setOpenModalStatus] = useState<{ const [openModalStatus, setOpenModalStatus] = useState<{
open: boolean; open: boolean;
action: PageActionType; action: PageActionType;
@@ -39,11 +39,11 @@ const useCreateAccess = (options?: { refresh: () => void }) => {
}; };
return { return {
openAccessModalStatus: openModalStatus, openRouteModalStatus: openModalStatus,
setOpenAccessModalStatus: setOpenModalStatus, setOpenRouteModalStatus: setOpenModalStatus,
openAccessModal: openModal, openRouteModal: openModal,
closeAccessModal: closeModal closeRouteModal: closeModal
}; };
}; };
export default useCreateAccess; export default useCreateRoute;
@@ -0,0 +1,37 @@
import { queryRouteTargets } from '../apis';
import { RouteTarget } from '../config/types';
const useEditTargets = () => {
const generateTargetData = (targetList: RouteTarget[]) => {
const fallbackTarget =
targetList?.filter(
(ep) => ep.fallback_status_codes && ep.fallback_status_codes?.length > 0
)?.[0] || null;
const targets = targetList?.filter(
(ep) =>
!ep.fallback_status_codes || ep.fallback_status_codes?.length === 0
);
return {
targets: targets,
fallbackTarget: fallbackTarget
};
};
const fetchTargets = async (accessId: number) => {
try {
const res = await queryRouteTargets({ id: accessId });
return res.items || [];
} catch (error) {
return [];
}
};
return {
generateTargetData,
fetchTargets
};
};
export default useEditTargets;
@@ -8,11 +8,11 @@ import { useIntl } from '@umijs/max';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { rowActionList } from '../config'; import { rowActionList } from '../config';
import { AccessItem } from '../config/types'; import { RouteItem } from '../config/types';
const useAccessColumns = ( const useAccessColumns = (
handleSelect: (val: string, record: AccessItem) => void, handleSelect: (val: string, record: RouteItem) => void,
onCellClick?: (record: AccessItem, dataIndex: string) => void onCellClick?: (record: RouteItem, dataIndex: string) => void
): SealColumnProps[] => { ): SealColumnProps[] => {
const intl = useIntl(); const intl = useIntl();
@@ -23,7 +23,7 @@ const useAccessColumns = (
dataIndex: 'name', dataIndex: 'name',
sorter: tableSorter(1), sorter: tableSorter(1),
span: 5, span: 5,
render: (text: string, record: AccessItem) => ( render: (text: string, record: RouteItem) => (
<span className="flex-center" style={{ maxWidth: '100%' }}> <span className="flex-center" style={{ maxWidth: '100%' }}>
<AutoTooltip ghost title={text}> <AutoTooltip ghost title={text}>
<span className="m-r-5">{text}</span> <span className="m-r-5">{text}</span>
@@ -33,12 +33,12 @@ const useAccessColumns = (
) )
}, },
{ {
title: intl.formatMessage({ id: 'accesses.table.accessPoints' }), title: intl.formatMessage({ id: 'routes.table.routeTargets' }),
dataIndex: 'endpoints', dataIndex: 'targets',
span: 10, span: 10,
render: (value: number, record: AccessItem) => ( render: (value: number, record: RouteItem) => (
<span> <span>
{record.ready_endpoints} / {value} {record.ready_targets} / {value}
</span> </span>
) )
}, },
@@ -57,7 +57,7 @@ const useAccessColumns = (
title: intl.formatMessage({ id: 'common.table.operation' }), title: intl.formatMessage({ id: 'common.table.operation' }),
dataIndex: 'operations', dataIndex: 'operations',
span: 4, span: 4,
render: (value: string, record: AccessItem) => ( render: (value: string, record: RouteItem) => (
<DropdownButtons <DropdownButtons
items={rowActionList} items={rowActionList}
onSelect={(val) => handleSelect(val, record)} onSelect={(val) => handleSelect(val, record)}
@@ -15,7 +15,7 @@ type CascaderOption<T extends object = EmptyObject> = {
children?: CascaderOption<T>[]; children?: CascaderOption<T>[];
} & Partial<T>; } & Partial<T>;
const useEndpointSourceModels = () => { const useTargetSourceModels = () => {
const intl = useIntl(); const intl = useIntl();
const [sourceModels, setSourceModels] = useState<CascaderOption[]>([]); const [sourceModels, setSourceModels] = useState<CascaderOption[]>([]);
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
@@ -88,4 +88,4 @@ const useEndpointSourceModels = () => {
}; };
}; };
export default useEndpointSourceModels; export default useTargetSourceModels;
@@ -20,23 +20,23 @@ import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box'; import PageBox from '../_components/page-box';
import AccessControlModal from '../llmodels/components/access-control-modal'; import AccessControlModal from '../llmodels/components/access-control-modal';
import { import {
ACCESS_API, MODEL_ROUTES,
ACCESS_POINTS_API, MODEL_ROUTE_TARGETS,
createAccess, createModelRoute,
deleteAccess, deleteModelRoute,
deleteAccessPoint, deleteModelRouteTarget,
queryAccessPoints, queryModelRoutes,
queryModelAccesses, queryRouteTargets,
setAccessPointAsFallback, setRouteTargetAsFallback,
updateAccess updateModelRoute
} from './apis'; } from './apis';
import AccessPoints from './components/access-points'; import AddRouteModal from './components/add-route-modal';
import AddAccessModal from './components/add-access-modal'; import RouteTargets from './components/route-targets';
import { FormData, AccessItem as ListItem } from './config/types'; import { FormData, RouteItem as ListItem } from './config/types';
import useAccessColumns from './hooks/use-access-columns';
import useAccessControl from './hooks/use-access-control'; import useAccessControl from './hooks/use-access-control';
import useCreateAccess from './hooks/use-create-access'; import useCreateRoute from './hooks/use-create-route';
import useEndpointSourceModels from './hooks/use-endpoint-source-models'; import useRoutesColumns from './hooks/use-routes-columns';
import useTargetSourceModels from './hooks/use-target-source-models';
const Accesses: React.FC = () => { const Accesses: React.FC = () => {
const { const {
@@ -52,31 +52,31 @@ const Accesses: React.FC = () => {
handleSearch, handleSearch,
handleNameChange handleNameChange
} = useTableFetch<ListItem>({ } = useTableFetch<ListItem>({
fetchAPI: queryModelAccesses, fetchAPI: queryModelRoutes,
deleteAPI: deleteAccess, deleteAPI: deleteModelRoute,
watch: true, watch: true,
API: ACCESS_API, API: MODEL_ROUTES,
contentForDelete: 'menu.models.access' contentForDelete: 'menu.models.routes'
}); });
const { watchDataList: allAccessPoints, deleteItemFromCache } = const { watchDataList: allRouteTargets, deleteItemFromCache } =
useWatchList(ACCESS_POINTS_API); useWatchList(MODEL_ROUTE_TARGETS);
const [expandAtom] = useAtom(expandKeysAtom); const [expandAtom] = useAtom(expandKeysAtom);
const { handleExpandChange, handleExpandAll, expandedRowKeys } = const { handleExpandChange, handleExpandAll, expandedRowKeys } =
useExpandedRowKeys(expandAtom); useExpandedRowKeys(expandAtom);
const intl = useIntl(); const intl = useIntl();
const { openAccessModalStatus, openAccessModal, closeAccessModal } = const { openRouteModalStatus, openRouteModal, closeRouteModal } =
useCreateAccess(); useCreateRoute();
const { const {
openAccessControlModal, openAccessControlModal,
closeAccessControlModal, closeAccessControlModal,
openAccessControlModalStatus openAccessControlModalStatus
} = useAccessControl(); } = useAccessControl();
const { sourceModels, fetchSourceModels } = useEndpointSourceModels(); const { sourceModels, fetchSourceModels } = useTargetSourceModels();
const handleClickDropdown = () => { const handleClickDropdown = () => {
openAccessModal( openRouteModal(
PageAction.CREATE, PageAction.CREATE,
intl.formatMessage({ id: 'accesses.button.add' }) intl.formatMessage({ id: 'routes.button.add' })
); );
}; };
@@ -85,30 +85,30 @@ const Accesses: React.FC = () => {
...data ...data
}; };
try { try {
if (openAccessModalStatus.action === PageAction.EDIT) { if (openRouteModalStatus.action === PageAction.EDIT) {
await updateAccess({ await updateModelRoute({
data: params, data: params,
id: openAccessModalStatus.currentData!.id id: openRouteModalStatus.currentData!.id
}); });
} }
if (openAccessModalStatus.action === PageAction.CREATE) { if (openRouteModalStatus.action === PageAction.CREATE) {
await createAccess({ await createModelRoute({
data: params data: params
}); });
} }
fetchData(); fetchData();
closeAccessModal(); closeRouteModal();
message.success(intl.formatMessage({ id: 'common.message.success' })); message.success(intl.formatMessage({ id: 'common.message.success' }));
} catch (error) {} } catch (error) {}
}; };
const handleModalCancel = () => { const handleModalCancel = () => {
console.log('handleModalCancel'); console.log('handleModalCancel');
closeAccessModal(); closeRouteModal();
}; };
const handleEditProvider = (row: ListItem) => { const handleEditProvider = (row: ListItem) => {
openAccessModal( openRouteModal(
PageAction.EDIT, PageAction.EDIT,
intl.formatMessage({ id: 'common.button.edit.item' }, { name: row.name }), intl.formatMessage({ id: 'common.button.edit.item' }, { name: row.name }),
row row
@@ -146,7 +146,7 @@ const Accesses: React.FC = () => {
const params = { const params = {
id: row.id id: row.id
}; };
const res = await queryAccessPoints(params, { const res = await queryRouteTargets(params, {
token: options?.token token: options?.token
}); });
@@ -158,14 +158,14 @@ const Accesses: React.FC = () => {
handleTableChange({}, {}, order, { action: 'sort' }); handleTableChange({}, {}, order, { action: 'sort' });
}; };
const handleDeleteEndpoint = (row: any) => { const handleDeleteTarget = (row: any) => {
modalRef.current?.show({ modalRef.current?.show({
content: 'accesses.table.accessPoints', content: 'routes.table.routeTargets',
okText: 'common.button.delete', okText: 'common.button.delete',
operation: 'common.delete.single.confirm', operation: 'common.delete.single.confirm',
name: row.name, name: row.name,
async onOk() { async onOk() {
await deleteAccessPoint(row.id); await deleteModelRouteTarget(row.id);
deleteItemFromCache?.(row.id); deleteItemFromCache?.(row.id);
} }
}); });
@@ -174,7 +174,7 @@ const Accesses: React.FC = () => {
const onChildSelect = useMemoizedFn(async (val: any, record: any) => { const onChildSelect = useMemoizedFn(async (val: any, record: any) => {
try { try {
if (val === 'fallback') { if (val === 'fallback') {
await setAccessPointAsFallback({ await setRouteTargetAsFallback({
id: record.id, id: record.id,
data: { data: {
fallback_status_codes: ['4xx', '5xx'] fallback_status_codes: ['4xx', '5xx']
@@ -182,7 +182,7 @@ const Accesses: React.FC = () => {
}); });
message.success(intl.formatMessage({ id: 'common.message.success' })); message.success(intl.formatMessage({ id: 'common.message.success' }));
} else if (val === 'delete') { } else if (val === 'delete') {
handleDeleteEndpoint(record); handleDeleteTarget(record);
} }
} catch (error) {} } catch (error) {}
}); });
@@ -192,7 +192,7 @@ const Accesses: React.FC = () => {
options: { parent?: any; [key: string]: any } options: { parent?: any; [key: string]: any }
) => { ) => {
return ( return (
<AccessPoints <RouteTargets
dataList={list} dataList={list}
onSelect={onChildSelect} onSelect={onChildSelect}
sourceModels={sourceModels} sourceModels={sourceModels}
@@ -201,14 +201,14 @@ const Accesses: React.FC = () => {
}; };
const setDisableExpand = (record: any) => { const setDisableExpand = (record: any) => {
return !record?.endpoints; return !record?.targets;
}; };
useEffect(() => { useEffect(() => {
fetchSourceModels(); fetchSourceModels();
}, []); }, []);
const columns = useAccessColumns(handleSelect); const columns = useRoutesColumns(handleSelect);
return ( return (
<> <>
@@ -218,7 +218,7 @@ const Accesses: React.FC = () => {
marginBottom={22} marginBottom={22}
marginTop={30} marginTop={30}
widths={{ input: 300 }} widths={{ input: 300 }}
buttonText={intl.formatMessage({ id: 'accesses.button.add' })} buttonText={intl.formatMessage({ id: 'routes.button.add' })}
rowSelection={rowSelection} rowSelection={rowSelection}
handleInputChange={handleNameChange} handleInputChange={handleNameChange}
handleSearch={handleSearch} handleSearch={handleSearch}
@@ -227,7 +227,7 @@ const Accesses: React.FC = () => {
></FilterBar> ></FilterBar>
<TableContext.Provider <TableContext.Provider
value={{ value={{
allChildren: allAccessPoints, allChildren: allRouteTargets,
setDisableExpand: setDisableExpand setDisableExpand: setDisableExpand
}} }}
> >
@@ -277,14 +277,14 @@ const Accesses: React.FC = () => {
></SealTable> ></SealTable>
</TableContext.Provider> </TableContext.Provider>
</PageBox> </PageBox>
<AddAccessModal <AddRouteModal
open={openAccessModalStatus.open} open={openRouteModalStatus.open}
action={openAccessModalStatus.action} action={openRouteModalStatus.action}
title={openAccessModalStatus.title} title={openRouteModalStatus.title}
currentData={openAccessModalStatus.currentData} currentData={openRouteModalStatus.currentData}
onCancel={handleModalCancel} onCancel={handleModalCancel}
onOk={handleModalOk} onOk={handleModalOk}
></AddAccessModal> ></AddRouteModal>
<AccessControlModal <AccessControlModal
onCancel={closeAccessControlModal} onCancel={closeAccessControlModal}
title={openAccessControlModalStatus.title} title={openAccessControlModalStatus.title}