fix: validation import model

This commit is contained in:
Faisal Amir 2025-08-19 21:29:18 +07:00
parent 926f3ab99a
commit 6ee044d106

View File

@ -79,6 +79,7 @@ function ProviderDetail() {
const [activeModels, setActiveModels] = useState<string[]>([]) const [activeModels, setActiveModels] = useState<string[]>([])
const [loadingModels, setLoadingModels] = useState<string[]>([]) const [loadingModels, setLoadingModels] = useState<string[]>([])
const [refreshingModels, setRefreshingModels] = useState(false) const [refreshingModels, setRefreshingModels] = useState(false)
const [importingModel, setImportingModel] = useState(false)
const { providerName } = useParams({ from: Route.id }) const { providerName } = useParams({ from: Route.id })
const { getProviderByName, setProviders, updateProvider } = useModelProvider() const { getProviderByName, setProviders, updateProvider } = useModelProvider()
const provider = getProviderByName(providerName) const provider = getProviderByName(providerName)
@ -482,7 +483,9 @@ function ProviderDetail() {
variant="link" variant="link"
size="sm" size="sm"
className="hover:no-underline" className="hover:no-underline"
disabled={importingModel}
onClick={async () => { onClick={async () => {
setImportingModel(true)
const selectedFile = await open({ const selectedFile = await open({
multiple: false, multiple: false,
directory: false, directory: false,
@ -496,10 +499,26 @@ function ProviderDetail() {
// If the dialog returns a file path, extract just the file name // If the dialog returns a file path, extract just the file name
const fileName = const fileName =
typeof selectedFile === 'string' typeof selectedFile === 'string'
? selectedFile.split(/[\\/]/).pop() ? selectedFile
.split(/[\\/]/)
.pop()
?.replace(/\s/g, '-')
: undefined : undefined
if (selectedFile && fileName) { if (selectedFile && fileName) {
// Check if model already exists
const modelExists = provider.models.some(
(model) => model.name === fileName
)
if (modelExists) {
toast.error('Model already exists', {
description: `${fileName} already imported`,
})
setImportingModel(false)
return
}
try { try {
await pullModel(fileName, selectedFile) await pullModel(fileName, selectedFile)
} catch (error) { } catch (error) {
@ -509,25 +528,35 @@ function ProviderDetail() {
) )
} finally { } finally {
// Refresh the provider to update the models list // Refresh the provider to update the models list
getProviders().then(setProviders) await getProviders().then(setProviders)
toast.success(t('providers:import'), { toast.success(t('providers:import'), {
id: `import-model-${provider.provider}`, id: `import-model-${provider.provider}`,
description: t( description: t(
'providers:importModelSuccess', 'providers:importModelSuccess',
{ provider: provider.provider } { provider: fileName }
), ),
}) })
setImportingModel(false)
} }
} else {
setImportingModel(false)
} }
}} }}
> >
<div className="cursor-pointer flex items-center justify-center rounded hover:bg-main-view-fg/15 bg-main-view-fg/10 transition-all duration-200 ease-in-out p-1.5 py-1 gap-1 -mr-2"> <div className="cursor-pointer flex items-center justify-center rounded hover:bg-main-view-fg/15 bg-main-view-fg/10 transition-all duration-200 ease-in-out p-1.5 py-1 gap-1 -mr-2">
{importingModel ? (
<IconLoader
size={18}
className="text-main-view-fg/50 animate-spin"
/>
) : (
<IconFolderPlus <IconFolderPlus
size={18} size={18}
className="text-main-view-fg/50" className="text-main-view-fg/50"
/> />
)}
<span className="text-main-view-fg/70"> <span className="text-main-view-fg/70">
{t('providers:import')} {importingModel ? 'Importing...' : t('providers:import')}
</span> </span>
</div> </div>
</Button> </Button>