diff --git a/src/assets/styles/menu.less b/src/assets/styles/menu.less
index 8bacfe1c..d3081ce3 100644
--- a/src/assets/styles/menu.less
+++ b/src/assets/styles/menu.less
@@ -3,8 +3,7 @@
.ant-layout-sider-children {
border-inline: none;
border-radius: 0;
- // padding-inline: 16px;
- padding-block-end: 12px;
+ padding-block-end: 8px;
}
.umi-plugin-layout-right {
diff --git a/src/global.less b/src/global.less
index 50aeb7b5..c009e11f 100644
--- a/src/global.less
+++ b/src/global.less
@@ -218,6 +218,11 @@ body {
background-color: var(--color-fill-1);
height: 100%;
+ .ant-pro-sider-footer {
+ padding-block: 2px 0;
+ padding-left: 6px;
+ }
+
.ant-pro-sider-actions-list-item {
padding: 0;
@@ -228,7 +233,6 @@ body {
.ant-pro-sider-logo {
position: relative;
- padding-left: 18px;
padding-block: 12px;
border-block-end: none;
}
diff --git a/src/layouts/index.tsx b/src/layouts/index.tsx
index 75b124a9..eb94b87e 100644
--- a/src/layouts/index.tsx
+++ b/src/layouts/index.tsx
@@ -1,7 +1,7 @@
// @ts-nocheck
import { routeCacheAtom, setRouteCache } from '@/atoms/route-cache';
-import { userAtom } from '@/atoms/user';
+import { GPUStackVersionAtom, userAtom } from '@/atoms/user';
import DarkMask from '@/components/dark-mask';
import IconFont from '@/components/icon-font';
import routeCachekey from '@/config/route-cachekey';
@@ -112,6 +112,7 @@ export default (props: any) => {
const navigate = useNavigate();
const intl = useIntl();
const { clientRoutes } = useAppData();
+ const [version] = useAtom(GPUStackVersionAtom);
const initialInfo = (useModel && useModel('@@initialState')) || {
initialState: undefined,
@@ -311,6 +312,9 @@ export default (props: any) => {
onCollapse={onCollapse}
onMenuHeaderClick={onMenuHeaderClick}
menuHeaderRender={renderMenuHeader}
+ menuFooterRender={() => (
+ {version?.version}
+ )}
extra={[
= forwardRef(
const jsonData = yaml2Json(content);
const exsistingVersions = Object.keys(jsonData.version_configs || {});
+ // Check backend version rules
if (
actionStatus.isBuiltIn &&
- exsistingVersions.find((v) => !v.endsWith('-custom'))
+ exsistingVersions.find((v) => !v?.endsWith('-custom'))
) {
setError(intl.formatMessage({ id: 'backend.version.no.tips' }));
return false;
}
+
+ // Check custom backend name rule
if (
!actionStatus.isBuiltIn &&
actionStatus.action === PageAction.CREATE &&
- !jsonData.backend_name.endsWith('-custom')
+ !jsonData.backend_name?.endsWith('-custom')
) {
setError(intl.formatMessage({ id: 'backend.backend.rules.custom' }));
return false;
}
+ // Check default version exists
+ if (
+ jsonData.default_version &&
+ !exsistingVersions.includes(jsonData.default_version) &&
+ !actionStatus.isBuiltIn
+ ) {
+ // the default_version must be in [existingVersions]
+ setError(
+ intl.formatMessage(
+ { id: 'backend.version.default.not.exists' },
+ { versions: exsistingVersions.join(', ') }
+ )
+ );
+ return false;
+ }
+
return content;
} catch (error) {
+ setError((error as Error).message);
return false;
}
};
diff --git a/src/pages/backends/components/yaml-editor.tsx b/src/pages/backends/components/yaml-editor.tsx
index a08f15d3..3bdcb365 100644
--- a/src/pages/backends/components/yaml-editor.tsx
+++ b/src/pages/backends/components/yaml-editor.tsx
@@ -88,12 +88,12 @@ const ViewerEditor: React.FC = forwardRef((props, ref) => {
}
};
+ // Currently, do not use this function, but keep it for future validation needs
const getMarkers = () => {
const uri = editorRef.current?.getModel()?.uri;
const markers = monacoRef.current?.editor.getModelMarkers({
resource: uri
});
- console.log('Validation markers:', uri, markers);
return markers;
};
diff --git a/src/pages/llmodels/apis/index.ts b/src/pages/llmodels/apis/index.ts
index 24b7ad9a..f9665c9c 100644
--- a/src/pages/llmodels/apis/index.ts
+++ b/src/pages/llmodels/apis/index.ts
@@ -367,7 +367,7 @@ export async function queryCatalogList(
}
export async function queryCatalogItemSpec(
- params: { id: number; cluster_id: number },
+ params: { id: number; cluster_id: number | null },
options?: any
) {
return request>(
diff --git a/src/pages/llmodels/catalog.tsx b/src/pages/llmodels/catalog.tsx
index 180a74da..22e5d12e 100644
--- a/src/pages/llmodels/catalog.tsx
+++ b/src/pages/llmodels/catalog.tsx
@@ -198,7 +198,10 @@ const Catalog: React.FC = () => {
const getCatalogSource = async () => {
try {
const id = dataSource.dataList?.[0]?.id;
- const res: any = await queryCatalogItemSpec({ id, cluster_id: 0 });
+ const res: any = await queryCatalogItemSpec({
+ id,
+ cluster_id: null
+ });
sourceRef.current = res?.items?.[0]?.source;
} catch (error) {}
};
diff --git a/src/pages/llmodels/components/deploy-builtin-modal.tsx b/src/pages/llmodels/components/deploy-builtin-modal.tsx
index 4c7a207c..5c4b0227 100644
--- a/src/pages/llmodels/components/deploy-builtin-modal.tsx
+++ b/src/pages/llmodels/components/deploy-builtin-modal.tsx
@@ -250,6 +250,16 @@ const AddModal: React.FC = (props) => {
cluster_id: clusterId,
name
});
+
+ // If no avaliable gpus for the model, show warning message
+ if (!res.items.length) {
+ setWarningStatus({
+ show: true,
+ type: 'warning',
+ message: intl.formatMessage({ id: 'models.catalog.nogpus.tips' })
+ });
+ return;
+ }
handleCheckCompatibility(allValues);
} catch (error) {
// ignore
diff --git a/src/pages/llmodels/forms/index.tsx b/src/pages/llmodels/forms/index.tsx
index 16f4bf99..6c6e0d01 100644
--- a/src/pages/llmodels/forms/index.tsx
+++ b/src/pages/llmodels/forms/index.tsx
@@ -103,7 +103,6 @@ const DataForm: React.FC = forwardRef((props, ref) => {
const [form] = Form.useForm();
const intl = useIntl();
const [activeKey, setActiveKey] = React.useState([]);
- const scheduleType = Form.useWatch('scheduleType', form);
const [target, setTarget] = React.useState(TABKeysMap.BASIC);
console.log('scroller instance in form:', osInstance, scrollEventElement);
diff --git a/src/pages/llmodels/hooks/index.ts b/src/pages/llmodels/hooks/index.ts
index dca99982..4c2953f4 100644
--- a/src/pages/llmodels/hooks/index.ts
+++ b/src/pages/llmodels/hooks/index.ts
@@ -296,7 +296,12 @@ export const useCheckCompatibility = () => {
title: intl.formatMessage({ id: 'models.form.check.passed' }),
message: intl.formatMessage({ id: messageId }, { ram, vram })
};
- } else if (othersAvailable) {
+ } else if (
+ othersAvailable &&
+ !scheduling_messages?.length &&
+ !compatibility_messages?.length
+ ) {
+ // no specific messages, but other clusters are available
msgData = {
title: intl.formatMessage({
id: 'models.form.check.clusterUnavailable'
diff --git a/src/pages/login/apis/index.ts b/src/pages/login/apis/index.ts
index 13ab7789..b4821ad4 100644
--- a/src/pages/login/apis/index.ts
+++ b/src/pages/login/apis/index.ts
@@ -24,11 +24,14 @@ export const login = async (
};
export const logout = async (userInfo?: any) => {
- await request(`${AUTH_API}/logout`, {
+ const res = await request(`${AUTH_API}/logout`, {
method: 'POST'
});
clearStorageUserSettings();
clearAtomStorage(userAtom);
+ if (res.logout_url) {
+ window.location.href = res.logout_url;
+ }
return;
};