big fixes
fixes feedback from thecodacus
This commit is contained in:
@@ -2,8 +2,6 @@ import React, { useEffect, useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { toast } from 'react-toastify';
|
||||
import { classNames } from '~/utils/classNames';
|
||||
import { settingsStyles } from '~/components/settings/settings.styles';
|
||||
import { DialogTitle, DialogDescription } from '~/components/ui/Dialog';
|
||||
|
||||
interface OllamaModel {
|
||||
name: string;
|
||||
@@ -197,108 +195,135 @@ export default function OllamaModelUpdater() {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center p-4">
|
||||
<div className={settingsStyles['loading-spinner']} />
|
||||
<div
|
||||
className={classNames(
|
||||
'rounded-full border-4 border-t-4 border-b-4 border-purple-500',
|
||||
'h-16 w-16 animate-spin',
|
||||
)}
|
||||
/>
|
||||
<span className="ml-2 text-bolt-elements-textSecondary">Loading models...</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<DialogTitle>Ollama Model Manager</DialogTitle>
|
||||
<DialogDescription>Update your local Ollama models to their latest versions</DialogDescription>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="i-ph:arrows-clockwise text-purple-500" />
|
||||
<span className="text-sm text-bolt-elements-textPrimary">{models.length} models available</span>
|
||||
<div
|
||||
className={classNames(
|
||||
'rounded-lg border bg-bolt-elements-background text-bolt-elements-textPrimary shadow-sm p-4',
|
||||
'hover:bg-bolt-elements-background-depth-2',
|
||||
'transition-all duration-200',
|
||||
)}
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-2xl font-bold">Ollama Model Manager</h2>
|
||||
<p>Update your local Ollama models to their latest versions</p>
|
||||
</div>
|
||||
<motion.button
|
||||
onClick={handleBulkUpdate}
|
||||
disabled={isBulkUpdating}
|
||||
className={classNames(
|
||||
settingsStyles.button.base,
|
||||
settingsStyles.button.primary,
|
||||
'hover:bg-purple-500/10 hover:text-purple-500',
|
||||
'dark:hover:bg-purple-500/20 dark:hover:text-purple-500',
|
||||
)}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{isBulkUpdating ? (
|
||||
<>
|
||||
<div className={settingsStyles['loading-spinner']} />
|
||||
Updating All...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="i-ph:arrows-clockwise" />
|
||||
Update All Models
|
||||
</>
|
||||
)}
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
{models.map((model) => (
|
||||
<div
|
||||
key={model.name}
|
||||
className={classNames(
|
||||
'flex items-center justify-between p-3 rounded-lg',
|
||||
'bg-[#F8F8F8] dark:bg-[#1A1A1A]',
|
||||
'border border-[#E5E5E5] dark:border-[#333333]',
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="i-ph:cube text-purple-500" />
|
||||
<span className="text-sm text-bolt-elements-textPrimary">{model.name}</span>
|
||||
{model.status === 'updating' && <div className={settingsStyles['loading-spinner']} />}
|
||||
{model.status === 'updated' && <div className="i-ph:check-circle text-green-500" />}
|
||||
{model.status === 'error' && <div className="i-ph:x-circle text-red-500" />}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs text-bolt-elements-textSecondary">
|
||||
<span>Version: {model.digest.substring(0, 7)}</span>
|
||||
{model.status === 'updated' && model.newDigest && (
|
||||
<>
|
||||
<div className="i-ph:arrow-right w-3 h-3" />
|
||||
<span className="text-green-500">{model.newDigest.substring(0, 7)}</span>
|
||||
</>
|
||||
)}
|
||||
{model.progress && (
|
||||
<span className="ml-2">
|
||||
{model.progress.status}{' '}
|
||||
{model.progress.total > 0 && (
|
||||
<>({Math.round((model.progress.current / model.progress.total) * 100)}%)</>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
{model.details && (
|
||||
<span className="ml-2">
|
||||
({model.details.parameter_size}, {model.details.quantization_level})
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<motion.button
|
||||
onClick={() => handleSingleUpdate(model.name)}
|
||||
disabled={model.status === 'updating'}
|
||||
className={classNames(
|
||||
settingsStyles.button.base,
|
||||
settingsStyles.button.secondary,
|
||||
'hover:bg-purple-500/10 hover:text-purple-500',
|
||||
'dark:bg-[#1A1A1A] dark:hover:bg-purple-500/20 dark:text-bolt-elements-textPrimary dark:hover:text-purple-500',
|
||||
)}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
<div className="i-ph:arrows-clockwise" />
|
||||
Update
|
||||
</motion.button>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="i-ph:arrows-clockwise text-purple-500" />
|
||||
<span className="text-sm text-bolt-elements-textPrimary">{models.length} models available</span>
|
||||
</div>
|
||||
))}
|
||||
<motion.button
|
||||
onClick={handleBulkUpdate}
|
||||
disabled={isBulkUpdating}
|
||||
className={classNames(
|
||||
'rounded-md px-4 py-2 text-sm',
|
||||
'bg-purple-500 text-white',
|
||||
'hover:bg-purple-600',
|
||||
'dark:bg-purple-500 dark:hover:bg-purple-600',
|
||||
'transition-all duration-200',
|
||||
)}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{isBulkUpdating ? (
|
||||
<>
|
||||
<div
|
||||
className={classNames(
|
||||
'rounded-full border-4 border-t-4 border-b-4 border-purple-500',
|
||||
'h-4 w-4 animate-spin mr-2',
|
||||
)}
|
||||
/>
|
||||
Updating All...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="i-ph:arrows-clockwise" />
|
||||
Update All Models
|
||||
</>
|
||||
)}
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
{models.map((model) => (
|
||||
<div
|
||||
key={model.name}
|
||||
className={classNames(
|
||||
'flex items-center justify-between p-3 rounded-lg',
|
||||
'bg-[#F8F8F8] dark:bg-[#1A1A1A]',
|
||||
'border border-[#E5E5E5] dark:border-[#333333]',
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="i-ph:cube text-purple-500" />
|
||||
<span className="text-sm text-bolt-elements-textPrimary">{model.name}</span>
|
||||
{model.status === 'updating' && (
|
||||
<div
|
||||
className={classNames(
|
||||
'rounded-full border-4 border-t-4 border-b-4 border-purple-500',
|
||||
'h-4 w-4 animate-spin',
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{model.status === 'updated' && <div className="i-ph:check-circle text-green-500" />}
|
||||
{model.status === 'error' && <div className="i-ph:x-circle text-red-500" />}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs text-bolt-elements-textSecondary">
|
||||
<span>Version: {model.digest.substring(0, 7)}</span>
|
||||
{model.status === 'updated' && model.newDigest && (
|
||||
<>
|
||||
<div className="i-ph:arrow-right w-3 h-3" />
|
||||
<span className="text-green-500">{model.newDigest.substring(0, 7)}</span>
|
||||
</>
|
||||
)}
|
||||
{model.progress && (
|
||||
<span className="ml-2">
|
||||
{model.progress.status}{' '}
|
||||
{model.progress.total > 0 && (
|
||||
<>({Math.round((model.progress.current / model.progress.total) * 100)}%)</>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
{model.details && (
|
||||
<span className="ml-2">
|
||||
({model.details.parameter_size}, {model.details.quantization_level})
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<motion.button
|
||||
onClick={() => handleSingleUpdate(model.name)}
|
||||
disabled={model.status === 'updating'}
|
||||
className={classNames(
|
||||
'rounded-md px-4 py-2 text-sm',
|
||||
'bg-purple-500 text-white',
|
||||
'hover:bg-purple-600',
|
||||
'dark:bg-purple-500 dark:hover:bg-purple-600',
|
||||
'transition-all duration-200',
|
||||
)}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
<div className="i-ph:arrows-clockwise" />
|
||||
Update
|
||||
</motion.button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user