fix: comment from QA regarding import model (#2213)

Signed-off-by: James <james@jan.ai>
Co-authored-by: James <james@jan.ai>
This commit is contained in:
NamH 2024-03-03 20:38:01 +07:00 committed by GitHub
parent 52f84dce9f
commit b70e7fb917
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 46 additions and 51 deletions

View File

@ -93,12 +93,12 @@ export function handleAppIPCs() {
const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, { const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, {
title: 'Select model files', title: 'Select model files',
buttonLabel: 'Select', buttonLabel: 'Select',
properties: ['openFile', 'multiSelections'], properties: ['openFile', 'openDirectory', 'multiSelections'],
}) })
if (canceled) { if (canceled) {
return return
} else {
return filePaths
} }
return filePaths
}) })
} }

View File

@ -1,29 +0,0 @@
type Props = {
title: string
description?: string
disabled?: boolean
onChange?: (text?: string) => void
}
export default function ItemCardSidebar({
description,
title,
disabled,
onChange,
}: Props) {
return (
<div className="flex flex-col gap-2">
<div className="flex items-center gap-2">
<span>{title}</span>
</div>
<input
value={description}
disabled={disabled}
type="text"
className="block w-full rounded-md border-0 px-1 py-1.5 text-white shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
placeholder=""
onChange={(e) => onChange?.(e.target.value)}
/>
</div>
)
}

View File

@ -39,7 +39,7 @@ export default function useDropModelBinaries() {
})) }))
if (unsupportedFiles.length > 0) { if (unsupportedFiles.length > 0) {
snackbar({ snackbar({
description: `File has to be a .gguf file`, description: `Only files with .gguf extension can be imported.`,
type: 'error', type: 'error',
}) })
} }

View File

@ -116,6 +116,11 @@ const EditModelInfoModal: React.FC = () => {
return null return null
} }
const onTagsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const tags = e.target.value.split(',')
setTags(tags)
}
return ( return (
<Modal <Modal
open={importModelStage === 'EDIT_MODEL_INFO'} open={importModelStage === 'EDIT_MODEL_INFO'}
@ -128,21 +133,23 @@ const EditModelInfoModal: React.FC = () => {
<div className="flex flex-row space-x-4 rounded-xl border p-4"> <div className="flex flex-row space-x-4 rounded-xl border p-4">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-blue-400"> <div className="flex h-10 w-10 items-center justify-center rounded-full bg-blue-400">
<Paperclip /> <Paperclip color="#fff" />
</div> </div>
<div className="flex flex-col"> <div className="flex flex-1 flex-col">
<p>{editingModel.name}</p> <p>{editingModel.name}</p>
<div className="flex flex-row"> <div className="flex flex-row">
<span className="mr-2 text-sm text-[#71717A]"> <span className="mr-2 text-sm text-[#71717A]">
{toGibibytes(editingModel.size)} {toGibibytes(editingModel.size)}
</span> </span>
<span className="text-sm font-semibold text-[#71717A]"> <div className="flex flex-row space-x-1">
Format:{' '} <span className="text-sm font-semibold text-[#71717A]">
</span> Format:
<span className="text-sm font-normal text-[#71717A]"> </span>
{editingModel.format.toUpperCase()} <span className="text-sm font-normal text-[#71717A]">
</span> {editingModel.format.toUpperCase()}
</span>
</div>
</div> </div>
<div className="mt-1 flex flex-row items-center space-x-2"> <div className="mt-1 flex flex-row items-center space-x-2">
<span className="line-clamp-1 text-xs font-normal text-[#71717A]"> <span className="line-clamp-1 text-xs font-normal text-[#71717A]">
@ -189,7 +196,7 @@ const EditModelInfoModal: React.FC = () => {
</div> </div>
<div className="flex flex-col"> <div className="flex flex-col">
<label className="mb-1">Tags</label> <label className="mb-1">Tags</label>
<Input /> <Input value={tags.join(',')} onChange={onTagsChange} />
</div> </div>
</form> </form>

View File

@ -1,7 +1,7 @@
import { useCallback } from 'react' import { useCallback } from 'react'
import { useDropzone } from 'react-dropzone' import { useDropzone } from 'react-dropzone'
import { ImportingModel, baseName, fs } from '@janhq/core' import { ImportingModel, baseName, fs, joinPath } from '@janhq/core'
import { Modal, ModalContent, ModalHeader, ModalTitle } from '@janhq/uikit' import { Modal, ModalContent, ModalHeader, ModalTitle } from '@janhq/uikit'
import { useAtomValue, useSetAtom } from 'jotai' import { useAtomValue, useSetAtom } from 'jotai'
@ -34,14 +34,31 @@ const SelectingModelModal: React.FC = () => {
const sanitizedFilePaths: FilePathWithSize[] = [] const sanitizedFilePaths: FilePathWithSize[] = []
for (const filePath of filePaths) { for (const filePath of filePaths) {
const fileStats = await fs.fileStat(filePath, true) const fileStats = await fs.fileStat(filePath, true)
if (!fileStats || fileStats.isDirectory) continue if (!fileStats) continue
const fileName = await baseName(filePath) if (!fileStats.isDirectory) {
sanitizedFilePaths.push({ const fileName = await baseName(filePath)
path: filePath, sanitizedFilePaths.push({
name: fileName, path: filePath,
size: fileStats.size, name: fileName,
}) size: fileStats.size,
})
} else {
// allowing only one level of directory
const files = await fs.readdirSync(filePath)
for (const file of files) {
const fullPath = await joinPath([filePath, file])
const fileStats = await fs.fileStat(fullPath, true)
if (!fileStats || fileStats.isDirectory) continue
sanitizedFilePaths.push({
path: fullPath,
name: file,
size: fileStats.size,
})
}
}
} }
const unsupportedFiles = sanitizedFilePaths.filter( const unsupportedFiles = sanitizedFilePaths.filter(
@ -68,7 +85,7 @@ const SelectingModelModal: React.FC = () => {
) )
if (unsupportedFiles.length > 0) { if (unsupportedFiles.length > 0) {
snackbar({ snackbar({
description: `File has to be a .gguf file`, description: `Only files with .gguf extension can be imported.`,
type: 'error', type: 'error',
}) })
} }