Skip to content

Commit

Permalink
feat: Add AI dashboard page
Browse files Browse the repository at this point in the history
  • Loading branch information
CH3CHO committed Dec 25, 2024
1 parent 99a3c46 commit 12d2304
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ private UserConfigKey() {}
public static final String LOGIN_PAGE_PROMPT_KEY = "login.prompt";
public static final String DASHBOARD_URL = "dashboard.url";
public static final String DASHBOARD_URL_PREFIX = "dashboard.url.";
public static final String DASHBOARD_BUILTIN = "dashboard.builtin";
public static final String CHAT_ENABLED = "chat.enabled";
public static final String ADMIN_PASSWORD_CHANGE_DISABLED = "admin.password-change.disabled";

Expand All @@ -35,6 +36,7 @@ private UserConfigKey() {}
CONFIG_VALUE_TYPES.put(DASHBOARD_URL, String.class);
CONFIG_VALUE_TYPES.put(CHAT_ENABLED, Boolean.class);
CONFIG_VALUE_TYPES.put(ADMIN_PASSWORD_CHANGE_DISABLED, Boolean.class);
CONFIG_VALUE_TYPES.put(DASHBOARD_BUILTIN, Boolean.class);
CONFIG_VALUE_TYPES.put(SYSTEM_INITIALIZED, Boolean.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -30,17 +32,18 @@
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.higress.console.constant.UserConfigKey;
import com.alibaba.higress.console.controller.dto.DashboardInfo;
import com.alibaba.higress.console.controller.dto.DashboardType;
import com.alibaba.higress.console.controller.dto.Response;
import com.alibaba.higress.console.controller.dto.SystemInfo;
import com.alibaba.higress.console.controller.dto.SystemInitRequest;
import com.alibaba.higress.console.controller.dto.User;
import com.alibaba.higress.sdk.exception.ValidationException;
import com.alibaba.higress.console.controller.util.ControllerUtil;
import com.alibaba.higress.console.service.ConfigService;
import com.alibaba.higress.console.service.DashboardService;
import com.alibaba.higress.console.service.SessionService;
import com.alibaba.higress.console.service.SystemService;

import javax.annotation.PostConstruct;
import com.alibaba.higress.sdk.exception.ValidationException;

/**
* @author CH3CHO
Expand All @@ -50,10 +53,16 @@
@Validated
public class SystemController {

private DashboardService dashboardService;
private SessionService sessionService;
private ConfigService configService;
private SystemService systemService;

@Autowired
public void setDashboardService(DashboardService dashboardService) {
this.dashboardService = dashboardService;
}

@Autowired
public void setSessionService(SessionService sessionService) {
this.sessionService = sessionService;
Expand All @@ -72,6 +81,9 @@ public void setSystemService(SystemService systemService) {
@PostConstruct
public void syncSystemState() {
configService.setConfig(UserConfigKey.SYSTEM_INITIALIZED, sessionService.isAdminInitialized());
DashboardInfo dashboardInfo = dashboardService.getDashboardInfo(DashboardType.MAIN);
configService.setConfig(UserConfigKey.DASHBOARD_BUILTIN,
dashboardInfo != null && Boolean.TRUE.equals(dashboardInfo.getBuiltIn()));
}

@PostMapping("/init")
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/interfaces/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,9 @@ export interface DashboardInfo {
builtIn: boolean;
url: string;
}

export enum DashboardType {
MAIN = "MAIN",
AI = "AI",
LOG = "LOG",
}
8 changes: 7 additions & 1 deletion frontend/src/locales/en-US/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@
"serviceSources": "Service Sources",
"serviceList": "Service List",
"routeConfig": "Route Config",
"aiServiceManagement": "AI Service Config",
"aiRouteManagement": "AI Route Config",
"aiDashboard": "AI Dashboard",
"llmProviderManagement": "LLM Provider Management",
"domainManagement": "Domain Management",
"certManagement": "Certificate Management",
"consumerManagement": "Consumer Management",
"pluginManagement": "Plugin Management"
},
"index": {
Expand Down Expand Up @@ -185,6 +190,7 @@
"placeholder": {
"type": "Please select LLM vendor",
"name": "Please enter a name",
"agreement": "Please select a protocol",
"serviceName": "Please enter a service name",
"tokens": "Please enter authentication token",
"domain": "Please enter domain name",
Expand All @@ -203,7 +209,7 @@
"howtouse": "How to use",
"AirouterUse": "How to use AI routing"
},
"create": "Provide AI service providers",
"create": "Create AI service provider",
"edit": "Edit AI service provider",
"deleteConfirmation": "Are you sure you want to delete < 1 > {{currentLlmProviderName}} </1 >?",
"deleteRoute": "Are you sure you want to delete < 1 > {{currentRouteName}} </1 >?",
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/locales/zh-CN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"routeConfig": "路由配置",
"aiServiceManagement": "AI流量入口管理",
"aiRouteManagement": "AI路由管理",
"aiDashboard": "AI监控面板",
"llmProviderManagement": "AI服务提供者管理",
"domainManagement": "域名管理",
"certManagement": "证书管理",
Expand Down Expand Up @@ -168,8 +169,8 @@
"type": "大模型供应商",
"name": "名称",
"serviceName": "服务名称",
"agreement": "协议",
"domain": "域名",
"agreement": "协议",
"modelPredicate": "是否启用基于模型的路由匹配规则",
"extra": "启用后,若请求目标服务失败,网关会改为请求降级服务。",
"modelPredicatePrefix": "模型名称匹配规则",
Expand Down Expand Up @@ -208,7 +209,7 @@
"howtouse": "使用方法",
"AirouterUse": "AI路由使用方法"
},
"create": "提供AI服务提供者",
"create": "创建AI服务提供者",
"edit": "编辑AI服务提供者",
"deleteConfirmation": "确定删除 <1>{{currentLlmProviderName}}</1> 吗?",
"deleteRoute": "确定删除 <1>{{currentRouteName}}</1> 吗?",
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/pages/_defaultProps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ export default {
path: '/ai/route',
},
{
path: '/ai/config',
name: 'menu.aiDashboard',
path: '/ai/dashboard',
visiblePredicate: (configData: any) => configData && configData['dashboard.builtin'],
},
],
},
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/pages/ai/dashboard.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.mb0 {
margin-bottom: 0;
}
46 changes: 46 additions & 0 deletions frontend/src/pages/ai/dashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { DashboardType } from '@/interfaces/dashboard';
import { getDashboardInfo } from '@/services';
import { useRequest } from 'ahooks';
import { Col, Row, Spin } from 'antd';
import React from 'react';
import { useTranslation } from 'react-i18next';

const Dashboard: React.FC = () => {
const { t } = useTranslation();

const { data: dashboardInfo, error, loading } = useRequest(() => getDashboardInfo(DashboardType.AI));

if (loading) {
return (
<div style={{ width: '100%', height: '50vh', flex: 1 }}>
<Spin />
</div>
);
}

if (error || !dashboardInfo || !dashboardInfo.url) {
return (
<div style={{ width: '100%', height: '50vh', flex: 1, textAlign: 'center' }}>
<h1>{t('dashboard.loadFailed')}</h1>
</div>
);
}

const frameUrl = dashboardInfo.builtIn ? location.origin + dashboardInfo.url : dashboardInfo.url;
return (
<>
<Row gutter={24} style={{ marginBottom: '0.5rem' }}>
<Col
style={{ textAlign: 'center', display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}
offset={4}
span={16}
>
<a href={frameUrl} target="_blank">{t('dashboard.openInNewPage')}</a>
</Col>
</Row>
<iframe style={{ width: '100%', height: '100vh', border: 0, flex: 1 }} src={frameUrl} />
</>
)
};

export default Dashboard;
3 changes: 2 additions & 1 deletion frontend/src/pages/dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import dataSourceUidSampleImage from '@/assets/GrafanaDataSourceUID.png';
import { Mode } from '@/interfaces/config';
import { DashboardType } from '@/interfaces/dashboard';
import { getDashboardConfigData, getDashboardInfo, initDashboard, setDashboardUrl } from '@/services';
import store from '@/store';
import { useRequest } from 'ahooks';
Expand All @@ -17,7 +18,7 @@ const Dashboard: React.FC = () => {
const [dataSourceUidSampleVisible, setDataSourceUidSampleVisible] = useState(false);
const [mode, setMode] = useState<string>(Mode.K8S);

const { data: dashboardInfo, error, loading } = useRequest(getDashboardInfo);
const { data: dashboardInfo, error, loading } = useRequest(() => getDashboardInfo(DashboardType.MAIN));

const [configModel] = store.useModel('config');
useEffect(() => {
Expand Down
15 changes: 13 additions & 2 deletions frontend/src/pages/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import defaultProps from './_defaultProps';

export default function Layout() {
const [userState] = store.useModel('user');
const [configModel] = store.useModel('config');
const configData = configModel.properties || {};
const location = useLocation();
const { t } = useTranslation();

Expand Down Expand Up @@ -51,13 +53,22 @@ export default function Layout() {
}}
menu={{ defaultOpenAll: true }}
menuDataRender={(items) => {
function filterMenuItem(item) {
if (item.hideFromMenu) {
return false;
}
if (typeof item.visiblePredicate === 'function') {
return item.visiblePredicate(configData);
}
return true;
}
function translateMenuItem(item) {
return Object.assign({}, item, {
name: t(item.name || ''),
children: item.children && item.children.map(translateMenuItem) || null,
children: item.children && item.children.filter(filterMenuItem).map(translateMenuItem) || null,
})
}
return items.filter(i => !i.hideFromMenu).map(translateMenuItem);
return items.filter(filterMenuItem).map(translateMenuItem);
}}
menuItemRender={(item, defaultDom) => {
if (!item.path) {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/services/dashboard.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { DashboardInfo } from '@/interfaces/dashboard';
import { DashboardInfo, DashboardType } from '@/interfaces/dashboard';
import request from './request';

export const getDashboardInfo = (): Promise<DashboardInfo> => {
return request.get<any, DashboardInfo>("/dashboard/info");
export const getDashboardInfo = (type: DashboardType): Promise<DashboardInfo> => {
return request.get<any, DashboardInfo>("/dashboard/info", { params: { type } });
};

export const initDashboard = (): Promise<DashboardInfo> => {
Expand Down

0 comments on commit 12d2304

Please sign in to comment.