improvement(kb): modals, page layouts (#2330)

This commit is contained in:
Emir Karabeg
2025-12-11 20:35:26 -08:00
committed by GitHub
parent 516dee14b7
commit 06d2db78ff
3 changed files with 136 additions and 107 deletions

View File

@@ -928,9 +928,22 @@ export function KnowledgeBase({
Tags
</Button>
)}
<Button onClick={() => setShowDeleteDialog(true)} className='h-[32px] rounded-[6px]'>
<Trash className='h-[14px] w-[14px]' />
</Button>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Button
onClick={() => setShowDeleteDialog(true)}
disabled={!userPermissions.canEdit}
className='h-[32px] rounded-[6px]'
>
<Trash className='h-[14px] w-[14px]' />
</Button>
</Tooltip.Trigger>
{!userPermissions.canEdit && (
<Tooltip.Content>
Write permission required to delete knowledge base
</Tooltip.Content>
)}
</Tooltip.Root>
</div>
</div>
@@ -940,7 +953,7 @@ export function KnowledgeBase({
</p>
)}
<div className='mt-[12px] flex items-center gap-[8px]'>
<div className='mt-[16px] flex items-center gap-[8px]'>
<span className='text-[14px] text-[var(--text-muted)]'>
{pagination.total} {pagination.total === 1 ? 'document' : 'documents'}
</span>

View File

@@ -1,7 +1,7 @@
'use client'
import { useEffect, useRef, useState } from 'react'
import { AlertCircle, Loader2, RotateCcw, X } from 'lucide-react'
import { Loader2, RotateCcw, X } from 'lucide-react'
import { useParams } from 'next/navigation'
import {
Button,
@@ -283,11 +283,11 @@ export function AddDocumentsModal({
return (
<div
key={index}
className='flex items-center gap-2 rounded-[4px] border p-[8px]'
>
{isFailed && !isRetrying && (
<AlertCircle className='h-4 w-4 flex-shrink-0 text-[var(--text-error)]' />
className={cn(
'flex items-center gap-2 rounded-[4px] border p-[8px]',
isFailed && !isRetrying && 'border-[var(--text-error)]'
)}
>
<span
className={cn(
'min-w-0 flex-1 truncate text-[12px]',
@@ -301,29 +301,31 @@ export function AddDocumentsModal({
{formatFileSize(file.size)}
</span>
<div className='flex flex-shrink-0 items-center gap-1'>
{isFailed && !isRetrying && (
<Button
type='button'
variant='ghost'
className='h-4 w-4 p-0 text-[var(--text-muted)] hover:text-[var(--text-primary)]'
onClick={() => handleRetryFile(index)}
disabled={isUploading}
>
<RotateCcw className='h-3.5 w-3.5' />
</Button>
)}
{isProcessing ? (
<Loader2 className='h-4 w-4 animate-spin text-[var(--text-muted)]' />
) : (
<Button
type='button'
variant='ghost'
className='h-4 w-4 p-0'
onClick={() => removeFile(index)}
disabled={isUploading}
>
<X className='h-3.5 w-3.5' />
</Button>
<>
{isFailed && (
<Button
type='button'
variant='ghost'
className='h-4 w-4 p-0'
onClick={() => handleRetryFile(index)}
disabled={isUploading}
>
<RotateCcw className='h-3 w-3' />
</Button>
)}
<Button
type='button'
variant='ghost'
className='h-4 w-4 p-0'
onClick={() => removeFile(index)}
disabled={isUploading}
>
<X className='h-3.5 w-3.5' />
</Button>
</>
)}
</div>
</div>
@@ -336,30 +338,34 @@ export function AddDocumentsModal({
</div>
</ModalBody>
<ModalFooter className='flex-col items-stretch gap-[12px]'>
{uploadError && (
<p className='text-[11px] text-[var(--text-error)] leading-tight'>
{uploadError.message}
</p>
)}
<div className='flex justify-end gap-[8px]'>
<Button variant='default' onClick={handleClose} type='button' disabled={isUploading}>
Cancel
</Button>
<Button
variant='primary'
type='button'
onClick={handleUpload}
disabled={files.length === 0 || isUploading}
>
{isUploading
? uploadProgress.stage === 'uploading'
? `Uploading ${uploadProgress.filesCompleted}/${uploadProgress.totalFiles}...`
: uploadProgress.stage === 'processing'
? 'Processing...'
: 'Uploading...'
: 'Upload'}
</Button>
<ModalFooter>
<div className='flex w-full items-center justify-between gap-[12px]'>
{uploadError ? (
<p className='min-w-0 flex-1 truncate text-[11px] text-[var(--text-error)] leading-tight'>
{uploadError.message}
</p>
) : (
<div />
)}
<div className='flex flex-shrink-0 gap-[8px]'>
<Button variant='default' onClick={handleClose} type='button' disabled={isUploading}>
Cancel
</Button>
<Button
variant='primary'
type='button'
onClick={handleUpload}
disabled={files.length === 0 || isUploading}
>
{isUploading
? uploadProgress.stage === 'uploading'
? `Uploading ${uploadProgress.filesCompleted}/${uploadProgress.totalFiles}...`
: uploadProgress.stage === 'processing'
? 'Processing...'
: 'Uploading...'
: 'Upload'}
</Button>
</div>
</div>
</ModalFooter>
</ModalContent>

View File

@@ -2,7 +2,7 @@
import { useEffect, useRef, useState } from 'react'
import { zodResolver } from '@hookform/resolvers/zod'
import { AlertCircle, Loader2, RotateCcw, X } from 'lucide-react'
import { Loader2, RotateCcw, X } from 'lucide-react'
import { useParams } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
@@ -449,11 +449,11 @@ export function CreateBaseModal({
return (
<div
key={index}
className='flex items-center gap-2 rounded-[4px] border p-[8px]'
>
{isFailed && !isRetrying && (
<AlertCircle className='h-4 w-4 flex-shrink-0 text-[var(--text-error)]' />
className={cn(
'flex items-center gap-2 rounded-[4px] border p-[8px]',
isFailed && !isRetrying && 'border-[var(--text-error)]'
)}
>
<span
className={cn(
'min-w-0 flex-1 truncate text-[12px]',
@@ -467,32 +467,34 @@ export function CreateBaseModal({
{formatFileSize(file.size)}
</span>
<div className='flex flex-shrink-0 items-center gap-1'>
{isFailed && !isRetrying && (
<Button
type='button'
variant='ghost'
className='h-4 w-4 p-0 text-[var(--text-muted)] hover:text-[var(--text-primary)]'
onClick={() => {
setRetryingIndexes((prev) => new Set(prev).add(index))
removeFile(index)
}}
disabled={isUploading}
>
<RotateCcw className='h-3.5 w-3.5' />
</Button>
)}
{isProcessing ? (
<Loader2 className='h-4 w-4 animate-spin text-[var(--text-muted)]' />
) : (
<Button
type='button'
variant='ghost'
className='h-4 w-4 p-0'
onClick={() => removeFile(index)}
disabled={isUploading}
>
<X className='h-3.5 w-3.5' />
</Button>
<>
{isFailed && (
<Button
type='button'
variant='ghost'
className='h-4 w-4 p-0'
onClick={() => {
setRetryingIndexes((prev) => new Set(prev).add(index))
removeFile(index)
}}
disabled={isUploading}
>
<RotateCcw className='h-3 w-3' />
</Button>
)}
<Button
type='button'
variant='ghost'
className='h-4 w-4 p-0'
onClick={() => removeFile(index)}
disabled={isUploading}
>
<X className='h-3.5 w-3.5' />
</Button>
</>
)}
</div>
</div>
@@ -509,32 +511,40 @@ export function CreateBaseModal({
</div>
</ModalBody>
<ModalFooter className='flex-col items-stretch gap-[12px]'>
{(submitStatus?.type === 'error' || uploadError) && (
<p className='text-[11px] text-[var(--text-error)] leading-tight'>
{uploadError?.message || submitStatus?.message}
</p>
)}
<div className='flex justify-end gap-[8px]'>
<Button
variant='default'
onClick={() => handleClose(false)}
type='button'
disabled={isSubmitting}
>
Cancel
</Button>
<Button variant='primary' type='submit' disabled={isSubmitting || !nameValue?.trim()}>
{isSubmitting
? isUploading
? uploadProgress.stage === 'uploading'
? `Uploading ${uploadProgress.filesCompleted}/${uploadProgress.totalFiles}...`
: uploadProgress.stage === 'processing'
? 'Processing...'
: 'Creating...'
: 'Creating...'
: 'Create'}
</Button>
<ModalFooter>
<div className='flex w-full items-center justify-between gap-[12px]'>
{submitStatus?.type === 'error' || uploadError ? (
<p className='min-w-0 flex-1 truncate text-[11px] text-[var(--text-error)] leading-tight'>
{uploadError?.message || submitStatus?.message}
</p>
) : (
<div />
)}
<div className='flex flex-shrink-0 gap-[8px]'>
<Button
variant='default'
onClick={() => handleClose(false)}
type='button'
disabled={isSubmitting}
>
Cancel
</Button>
<Button
variant='primary'
type='submit'
disabled={isSubmitting || !nameValue?.trim()}
>
{isSubmitting
? isUploading
? uploadProgress.stage === 'uploading'
? `Uploading ${uploadProgress.filesCompleted}/${uploadProgress.totalFiles}...`
: uploadProgress.stage === 'processing'
? 'Processing...'
: 'Creating...'
: 'Creating...'
: 'Create'}
</Button>
</div>
</div>
</ModalFooter>
</form>