From d6dce4021da5fc38524225e529855475dd3d9683 Mon Sep 17 00:00:00 2001 From: jialin Date: Thu, 14 Aug 2025 10:16:31 +0800 Subject: [PATCH] fix: filter non-normal gguf files --- src/components/lang-select/index.tsx | 20 +++++++- .../theme-toggle/theme-drop-actions.tsx | 4 ++ src/global.less | 1 - src/locales/en-US/common.ts | 4 +- src/locales/ja-JP/common.ts | 5 +- src/locales/ru-RU/common.ts | 5 +- src/locales/zh-CN/common.ts | 3 +- .../llmodels/components/hf-model-file.tsx | 9 +++- src/pages/login/components/login-form.tsx | 39 +++++---------- src/pages/login/components/password-form.tsx | 7 +-- src/pages/login/hooks/use-sso-auth.ts | 12 ++++- src/pages/login/index.tsx | 49 ++++++++++++++++--- 12 files changed, 107 insertions(+), 51 deletions(-) diff --git a/src/components/lang-select/index.tsx b/src/components/lang-select/index.tsx index bd4e99a1..03f3dea2 100644 --- a/src/components/lang-select/index.tsx +++ b/src/components/lang-select/index.tsx @@ -2,9 +2,27 @@ import langConfigMap from '@/locales/lang-config-map'; import { GlobalOutlined } from '@ant-design/icons'; import { getAllLocales, setLocale } from '@umijs/max'; import { Dropdown } from 'antd'; +import { createStyles } from 'antd-style'; import { get } from 'lodash'; +const useStyles = createStyles(({ token, css }) => ({ + button: css` + color: ${token.colorText}; + padding: 0 12px; + cursor: pointer; + .anticon { + color: ${token.colorText}; + } + &:hover { + .anticon { + color: ${token.colorTextTertiary}; + } + } + ` +})); + const LangSelect = () => { + const { styles } = useStyles(); const allLocals = getAllLocales(); const items = allLocals.map((key) => { return { @@ -25,7 +43,7 @@ const LangSelect = () => { return ( - + diff --git a/src/components/theme-toggle/theme-drop-actions.tsx b/src/components/theme-toggle/theme-drop-actions.tsx index 243600a2..fff87157 100644 --- a/src/components/theme-toggle/theme-drop-actions.tsx +++ b/src/components/theme-toggle/theme-drop-actions.tsx @@ -15,9 +15,13 @@ const useStyles = createStyles(({ token, css }) => ({ padding: 0 8px; &:hover { color: ${token.colorTextTertiary}; + .anticon { + color: ${token.colorTextTertiary}; + } } .anticon { font-size: 16px; + color: ${token.colorText}; } .icon-auto { font-size: 20px; diff --git a/src/global.less b/src/global.less index 84688976..418410f4 100644 --- a/src/global.less +++ b/src/global.less @@ -570,7 +570,6 @@ body { .ant-message-notice-content { border-radius: var(--border-radius-base) !important; - line-height: 2; max-width: 300px; text-align: left; word-break: break-word; diff --git a/src/locales/en-US/common.ts b/src/locales/en-US/common.ts index a06a5963..e1f315b2 100644 --- a/src/locales/en-US/common.ts +++ b/src/locales/en-US/common.ts @@ -255,5 +255,7 @@ export default { 'common.login.auth': 'Authenticating...', 'common.login.auth.failed': 'Authentication failed', 'common.login.password': 'Log in with Password', - 'common.external.login': 'Log in with {type}' + 'common.external.login': 'Log in with {type}', + 'common.sso.noConfig': + 'Single sign-on is not enabled on this system. Please contact your administrator.' }; diff --git a/src/locales/ja-JP/common.ts b/src/locales/ja-JP/common.ts index 0cc25a8a..8de117b7 100644 --- a/src/locales/ja-JP/common.ts +++ b/src/locales/ja-JP/common.ts @@ -255,7 +255,9 @@ export default { 'common.login.auth': 'Authenticating...', 'common.login.auth.failed': 'Authentication failed', 'common.login.password': 'Log in with Password', - 'common.external.login': 'Log in with {type}' + 'common.external.login': 'Log in with {type}', + 'common.sso.noConfig': + 'Single sign-on is not enabled on this system. Please contact your administrator.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -278,4 +280,5 @@ export default { // 17. 'common.login.auth.failed': 'Authentication failed', // 18. 'common.external.login': 'Log in with {type}' // 19. 'common.login.password': 'Log in with Password', +// 20. 'common.sso.noConfig': 'Single sign-on is not enabled on this system. Please contact your administrator.' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/common.ts b/src/locales/ru-RU/common.ts index 2f6755be..ed436b8d 100644 --- a/src/locales/ru-RU/common.ts +++ b/src/locales/ru-RU/common.ts @@ -254,10 +254,13 @@ export default { 'common.login.auth': 'Аутентификация...', 'common.login.auth.failed': 'Ошибка аутентификации', 'common.login.password': 'Log in with Password', - 'common.external.login': 'Log in with {type}' + 'common.external.login': 'Log in with {type}', + 'common.sso.noConfig': + 'Single sign-on is not enabled on this system. Please contact your administrator.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== // 1. 'common.external.login': 'Log in with {type}' // 2. 'common.login.password': 'Log in with Password' +// 3. 'common.sso.noConfig': 'Single sign-on is not enabled on this system. Please contact your administrator.' // ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/common.ts b/src/locales/zh-CN/common.ts index 3c730b7b..810e8cb2 100644 --- a/src/locales/zh-CN/common.ts +++ b/src/locales/zh-CN/common.ts @@ -248,5 +248,6 @@ export default { 'common.login.auth': '认证中...', 'common.login.auth.failed': '认证失败', 'common.login.password': '使用密码登录', - 'common.external.login': '使用 {type} 登录' + 'common.external.login': '使用 {type} 登录', + 'common.sso.noConfig': '该系统未启用单点登录,请联系管理员。' }; diff --git a/src/pages/llmodels/components/hf-model-file.tsx b/src/pages/llmodels/components/hf-model-file.tsx index 850b71c5..19d2f2ee 100644 --- a/src/pages/llmodels/components/hf-model-file.tsx +++ b/src/pages/llmodels/components/hf-model-file.tsx @@ -161,6 +161,11 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { return filterRegGGUF.test(file.path) || _.includes(file.path, '.gguf'); }; + const isNormalGGUFModelFile = (filename: string) => { + const file = filename?.toLowerCase() ?? ''; + return file.indexOf('mmproj') === -1 && file.indexOf('imatrix') === -1; + }; + // hugging face files const getHuggingfaceFiles = async () => { try { @@ -175,7 +180,7 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { }); const list = _.filter(fileList, (file: any) => { - return hfFileFilter(file) && file.path.indexOf('mmproj') === -1; + return hfFileFilter(file) && isNormalGGUFModelFile(file.path); }); return list; @@ -188,7 +193,7 @@ const HFModelFile: React.FC = forwardRef((props, ref) => { return ( filterRegGGUF.test(file.Path) && file.Type === 'blob' && - file.Path.indexOf('mmproj') === -1 + isNormalGGUFModelFile(file.Path) ); }; diff --git a/src/pages/login/components/login-form.tsx b/src/pages/login/components/login-form.tsx index 1332ac49..fdbc47b6 100644 --- a/src/pages/login/components/login-form.tsx +++ b/src/pages/login/components/login-form.tsx @@ -1,7 +1,5 @@ import LogoIcon from '@/assets/images/gpustack-logo.png'; import { userAtom } from '@/atoms/user'; -import LangSelect from '@/components/lang-select'; -import ThemeDropActions from '@/components/theme-toggle/theme-drop-actions'; import { useIntl, useModel } from '@umijs/max'; import { Button, Divider, Form, Spin, message } from 'antd'; import { createStyles } from 'antd-style'; @@ -52,22 +50,6 @@ const DividerWrapper = styled(Divider)` `; const useStyles = createStyles(({ token, css }) => ({ - header: css` - display: flex; - align-items: center; - gap: 8px; - position: fixed; - right: 0; - top: 0; - height: 60px; - padding: 20px; - .anticon-global { - color: ${token.colorText}; - } - .anticon:hover { - color: ${token.colorTextTertiary}; - } - `, errorMessage: css` display: flex; flex-direction: column; @@ -99,6 +81,7 @@ const LoginForm = () => { const intl = useIntl(); const [form] = Form.useForm(); const [isPassword, setIsPassword] = useState(false); + const [loading, setLoading] = useState(false); const renderWelCome = () => { return ( @@ -161,6 +144,7 @@ const LoginForm = () => { gotoDefaultPage(userInfo); } }, + onError: (error) => { // gpustack handle in the interceptor } @@ -173,6 +157,9 @@ const LoginForm = () => { setUserInfo(userInfo); gotoDefaultPage({}); }, + onLoading: (loading) => { + setLoading(loading); + }, onError: handleOnError }); @@ -186,6 +173,8 @@ const LoginForm = () => { } else if (SSOAuth.options.saml) { SSOAuth.loginWithSAML(); } + setLoading(true); + setAuthError(null); }; const hasThirdPartyLogin = useMemo(() => { @@ -228,22 +217,16 @@ const LoginForm = () => { }; const isThirdPartyAuthHandling = useMemo(() => { - return SSOAuth.isSSOLogin && !authError; - }, [SSOAuth.isSSOLogin, authError]); + return loading && !authError; + }, [loading, authError]); return (
{contextHolder} -
- - -
{isThirdPartyAuthHandling ? ( - - - {intl.formatMessage({ id: 'common.login.auth' })} - + +
) : ( <> diff --git a/src/pages/login/components/password-form.tsx b/src/pages/login/components/password-form.tsx index a0b33c6c..81532dce 100644 --- a/src/pages/login/components/password-form.tsx +++ b/src/pages/login/components/password-form.tsx @@ -2,8 +2,8 @@ import { initialPasswordAtom, userAtom } from '@/atoms/user'; import SealInput from '@/components/seal-form/seal-input'; import { PasswordReg } from '@/config'; import { CRYPT_TEXT } from '@/utils/localstore/index'; -import { GlobalOutlined, LockOutlined } from '@ant-design/icons'; -import { SelectLang, useIntl } from '@umijs/max'; +import { LockOutlined } from '@ant-design/icons'; +import { useIntl } from '@umijs/max'; import { Button, Form, message } from 'antd'; import CryptoJS from 'crypto-js'; import { useAtom } from 'jotai'; @@ -47,9 +47,6 @@ const PasswordForm: React.FC = () => { return (
-
- } reload={false} /> -
Promise; onSuccess?: (userInfo: any) => void; onError?: (err: Error) => void; + onLoading?: (loading: boolean) => void; }) { const [loginOption, setLoginOption] = useState({ saml: false, oidc: false }); + const intl = useIntl(); + const { location } = history; const params = new URLSearchParams(location.search); const sso = params.get('sso'); @@ -53,17 +57,21 @@ export function useSSOAuth({ saml: !!authConfig.is_saml }); if (sso) { + onLoading?.(true); if (authConfig.is_oidc) { oidcLogin(); } else if (authConfig.is_saml) { samlLogin(); } else { - onError?.(new Error('No SSO configuration found')); + onError?.( + new Error(intl.formatMessage({ id: 'common.sso.noConfig' })) + ); } } } catch (error: any) { setLoginOption({ oidc: false, saml: false }); onError?.(error); + onLoading?.(false); } }; diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index b90ea0e5..169c9272 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -2,9 +2,12 @@ import Bg2 from '@/assets/images/bg-2.png'; import { userAtom } from '@/atoms/user'; import DarkMask from '@/components/dark-mask'; import Footer from '@/components/footer'; +import LangSelect from '@/components/lang-select'; +import ThemeDropActions from '@/components/theme-toggle/theme-drop-actions'; import useUserSettings from '@/hooks/use-user-settings'; import { useModel } from '@umijs/max'; import { ConfigProvider, theme } from 'antd'; +import { createStyles } from 'antd-style'; import { useAtom } from 'jotai'; import { useEffect } from 'react'; import styled from 'styled-components'; @@ -12,6 +15,29 @@ import LoginForm from './components/login-form'; import PasswordForm from './components/password-form'; import { checkDefaultPage } from './utils'; +const useStyles = createStyles(({ token, css }) => ({ + header: css` + display: flex; + align-items: center; + gap: 8px; + position: fixed; + right: 0; + top: 0; + height: 60px; + padding: 20px; + .anticon-global { + color: ${token.colorText}; + } + .anticon:hover { + color: ${token.colorTextTertiary}; + } + `, + formContainer: css` + height: calc(100vh - 64px); + width: 100%; + ` +})); + const Wrapper = styled.div<{ $isDarkTheme: boolean }>` position: fixed; top: 0; @@ -30,7 +56,6 @@ const Wrapper = styled.div<{ $isDarkTheme: boolean }>` `; const Box = styled.div` - padding-top: 10%; display: flex; flex-direction: column; justify-content: space-between; @@ -40,6 +65,7 @@ const Box = styled.div` const FormWrapper = styled.div` position: relative; margin: 0 auto; + z-index: 999; border-radius: var(--border-radius-modal); width: max-content; height: max-content; @@ -48,6 +74,8 @@ const FormWrapper = styled.div` padding: 40px; background-color: var(--color-modal-content-bg); box-shadow: var(--color-modal-box-shadow); + margin-top: 50vh; + transform: translateY(-50%); .field-wrapper { background-color: transparent !important; } @@ -58,6 +86,7 @@ const FormWrapper = styled.div` `; const Login = () => { + const { styles } = useStyles(); const { themeData, userSettings, isDarkTheme } = useUserSettings(); const [userInfo, setUserInfo] = useAtom(userAtom); const { initialState, setInitialState } = useModel('@@initialState') || {}; @@ -95,10 +124,14 @@ const Login = () => { ...themeData }} > -
- - - +
+ + +
+ + + +
{userInfo?.require_password_change ? ( @@ -106,9 +139,9 @@ const Login = () => { )} -
- -
+
+