yangdx commited on
Commit
d28c92f
·
1 Parent(s): 91b3580

fix(ui): improve pipeline status dialog layout and styling

Browse files

- Switch from AlertDialog to Dialog component for better modal behavior
- Adjust dialog positioning and alignment controls
- Remove custom close button to avoid duplication
- Add proper spacing between alignment buttons and close button
- Simplify history container height with min/max height
- Reduce overlay opacity for better visibility

lightrag_webui/src/components/documents/PipelineStatusDialog.tsx CHANGED
@@ -1,16 +1,15 @@
1
- import { useState, useEffect, useRef, useCallback } from 'react'
2
  import { useTranslation } from 'react-i18next'
3
  import { toast } from 'sonner'
4
- import { X, AlignLeft, AlignCenter, AlignRight } from 'lucide-react'
5
 
6
  import {
7
- AlertDialog,
8
- AlertDialogContent,
9
- AlertDialogHeader,
10
- AlertDialogTitle,
11
- AlertDialogDescription,
12
- AlertDialogOverlay,
13
- } from '@/components/ui/AlertDialog'
14
  import Button from '@/components/ui/Button'
15
  import { getPipelineStatus, PipelineStatusResponse } from '@/api/lightrag'
16
  import { errorMessage } from '@/lib/utils'
@@ -31,44 +30,15 @@ export default function PipelineStatusDialog({
31
  const [status, setStatus] = useState<PipelineStatusResponse | null>(null)
32
  const [position, setPosition] = useState<DialogPosition>('center')
33
  const [isUserScrolled, setIsUserScrolled] = useState(false)
34
- const [historyHeight, setHistoryHeight] = useState('20em')
35
  const historyRef = useRef<HTMLDivElement>(null)
36
- const resizeObserverRef = useRef<ResizeObserver | null>(null)
37
-
38
- // Calculate history height based on window height
39
- const updateHistoryHeight = useCallback(() => {
40
- const minHeight = 7.5 // 5 lines * 1.5em line height
41
- const windowHeight = window.innerHeight
42
- const pixelsPerEm = parseFloat(getComputedStyle(document.documentElement).fontSize)
43
- const maxHeightInEm = Math.max(Math.floor((windowHeight * 0.4) / pixelsPerEm), minHeight)
44
- setHistoryHeight(`${maxHeightInEm}em`)
45
- }, [])
46
 
47
  // Reset position when dialog opens
48
  useEffect(() => {
49
  if (open) {
50
  setPosition('center')
51
  setIsUserScrolled(false)
52
- updateHistoryHeight()
53
- }
54
- }, [open, updateHistoryHeight])
55
-
56
- // Setup resize observer
57
- useEffect(() => {
58
- if (!open) return
59
-
60
- resizeObserverRef.current = new ResizeObserver((entries) => {
61
- if (entries[0]) {
62
- updateHistoryHeight()
63
- }
64
- })
65
-
66
- resizeObserverRef.current.observe(document.body)
67
-
68
- return () => {
69
- resizeObserverRef.current?.disconnect()
70
  }
71
- }, [open, updateHistoryHeight])
72
 
73
  // Handle scroll position
74
  useEffect(() => {
@@ -112,74 +82,63 @@ export default function PipelineStatusDialog({
112
  }, [open, t])
113
 
114
  return (
115
- <AlertDialog open={open} onOpenChange={onOpenChange}>
116
- <AlertDialogOverlay className="bg-black/30" />
117
- <AlertDialogContent
118
  className={cn(
119
- 'sm:max-w-[600px] transition-all duration-200',
120
- position === 'left' && '!left-4 !translate-x-0',
121
  position === 'center' && '!left-1/2 !-translate-x-1/2',
122
- position === 'right' && '!right-4 !left-auto !translate-x-0'
123
  )}
124
  >
125
- <AlertDialogDescription className="sr-only">
126
  {status?.job_name
127
  ? `${t('documentPanel.pipelineStatus.jobName')}: ${status.job_name}, ${t('documentPanel.pipelineStatus.progress')}: ${status.cur_batch}/${status.batchs}`
128
  : t('documentPanel.pipelineStatus.noActiveJob')
129
  }
130
- </AlertDialogDescription>
131
- <AlertDialogHeader className="flex flex-row items-center justify-between">
132
- <AlertDialogTitle>
133
  {t('documentPanel.pipelineStatus.title')}
134
- </AlertDialogTitle>
135
 
136
- {/* Position control buttons and close button */}
137
- <div className="flex items-center gap-2">
138
- <div className="flex items-center gap-1">
139
- <Button
140
- variant="ghost"
141
- size="icon"
142
- className={cn(
143
- 'h-6 w-6',
144
- position === 'left' && 'bg-zinc-200 text-zinc-800 hover:bg-zinc-300 dark:bg-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-600'
145
- )}
146
- onClick={() => setPosition('left')}
147
- >
148
- <AlignLeft className="h-4 w-4" />
149
- </Button>
150
- <Button
151
- variant="ghost"
152
- size="icon"
153
- className={cn(
154
- 'h-6 w-6',
155
- position === 'center' && 'bg-zinc-200 text-zinc-800 hover:bg-zinc-300 dark:bg-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-600'
156
- )}
157
- onClick={() => setPosition('center')}
158
- >
159
- <AlignCenter className="h-4 w-4" />
160
- </Button>
161
- <Button
162
- variant="ghost"
163
- size="icon"
164
- className={cn(
165
- 'h-6 w-6',
166
- position === 'right' && 'bg-zinc-200 text-zinc-800 hover:bg-zinc-300 dark:bg-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-600'
167
- )}
168
- onClick={() => setPosition('right')}
169
- >
170
- <AlignRight className="h-4 w-4" />
171
- </Button>
172
- </div>
173
  <Button
174
  variant="ghost"
175
  size="icon"
176
- className="h-6 w-6"
177
- onClick={() => onOpenChange(false)}
 
 
 
178
  >
179
- <X className="h-4 w-4" />
180
  </Button>
181
  </div>
182
- </AlertDialogHeader>
183
 
184
  {/* Status Content */}
185
  <div className="space-y-4 pt-4">
@@ -218,8 +177,7 @@ export default function PipelineStatusDialog({
218
  <div
219
  ref={historyRef}
220
  onScroll={handleScroll}
221
- className="font-mono text-sm rounded-md bg-zinc-800 text-zinc-100 p-3 overflow-y-auto"
222
- style={{ height: historyHeight }}
223
  >
224
  {status?.history_messages?.map((msg, idx) => (
225
  <div key={idx}>{msg}</div>
@@ -227,7 +185,7 @@ export default function PipelineStatusDialog({
227
  </div>
228
  </div>
229
  </div>
230
- </AlertDialogContent>
231
- </AlertDialog>
232
  )
233
  }
 
1
+ import { useState, useEffect, useRef } from 'react'
2
  import { useTranslation } from 'react-i18next'
3
  import { toast } from 'sonner'
4
+ import { AlignLeft, AlignCenter, AlignRight } from 'lucide-react'
5
 
6
  import {
7
+ Dialog,
8
+ DialogContent,
9
+ DialogHeader,
10
+ DialogTitle,
11
+ DialogDescription
12
+ } from '@/components/ui/Dialog'
 
13
  import Button from '@/components/ui/Button'
14
  import { getPipelineStatus, PipelineStatusResponse } from '@/api/lightrag'
15
  import { errorMessage } from '@/lib/utils'
 
30
  const [status, setStatus] = useState<PipelineStatusResponse | null>(null)
31
  const [position, setPosition] = useState<DialogPosition>('center')
32
  const [isUserScrolled, setIsUserScrolled] = useState(false)
 
33
  const historyRef = useRef<HTMLDivElement>(null)
 
 
 
 
 
 
 
 
 
 
34
 
35
  // Reset position when dialog opens
36
  useEffect(() => {
37
  if (open) {
38
  setPosition('center')
39
  setIsUserScrolled(false)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
+ }, [open])
42
 
43
  // Handle scroll position
44
  useEffect(() => {
 
82
  }, [open, t])
83
 
84
  return (
85
+ <Dialog open={open} onOpenChange={onOpenChange}>
86
+ <DialogContent
 
87
  className={cn(
88
+ 'sm:max-w-[600px] transition-all duration-200 fixed',
89
+ position === 'left' && '!left-[25%] !translate-x-[-50%] !mx-4',
90
  position === 'center' && '!left-1/2 !-translate-x-1/2',
91
+ position === 'right' && '!left-[75%] !translate-x-[-50%] !mx-4'
92
  )}
93
  >
94
+ <DialogDescription className="sr-only">
95
  {status?.job_name
96
  ? `${t('documentPanel.pipelineStatus.jobName')}: ${status.job_name}, ${t('documentPanel.pipelineStatus.progress')}: ${status.cur_batch}/${status.batchs}`
97
  : t('documentPanel.pipelineStatus.noActiveJob')
98
  }
99
+ </DialogDescription>
100
+ <DialogHeader className="flex flex-row items-center">
101
+ <DialogTitle className="flex-1">
102
  {t('documentPanel.pipelineStatus.title')}
103
+ </DialogTitle>
104
 
105
+ {/* Position control buttons */}
106
+ <div className="flex items-center gap-2 mr-8">
107
+ <Button
108
+ variant="ghost"
109
+ size="icon"
110
+ className={cn(
111
+ 'h-6 w-6',
112
+ position === 'left' && 'bg-zinc-200 text-zinc-800 hover:bg-zinc-300 dark:bg-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-600'
113
+ )}
114
+ onClick={() => setPosition('left')}
115
+ >
116
+ <AlignLeft className="h-4 w-4" />
117
+ </Button>
118
+ <Button
119
+ variant="ghost"
120
+ size="icon"
121
+ className={cn(
122
+ 'h-6 w-6',
123
+ position === 'center' && 'bg-zinc-200 text-zinc-800 hover:bg-zinc-300 dark:bg-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-600'
124
+ )}
125
+ onClick={() => setPosition('center')}
126
+ >
127
+ <AlignCenter className="h-4 w-4" />
128
+ </Button>
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  <Button
130
  variant="ghost"
131
  size="icon"
132
+ className={cn(
133
+ 'h-6 w-6',
134
+ position === 'right' && 'bg-zinc-200 text-zinc-800 hover:bg-zinc-300 dark:bg-zinc-700 dark:text-zinc-200 dark:hover:bg-zinc-600'
135
+ )}
136
+ onClick={() => setPosition('right')}
137
  >
138
+ <AlignRight className="h-4 w-4" />
139
  </Button>
140
  </div>
141
+ </DialogHeader>
142
 
143
  {/* Status Content */}
144
  <div className="space-y-4 pt-4">
 
177
  <div
178
  ref={historyRef}
179
  onScroll={handleScroll}
180
+ className="font-mono text-sm rounded-md bg-zinc-800 text-zinc-100 p-3 overflow-y-auto min-h-[7.5em] max-h-[40vh]"
 
181
  >
182
  {status?.history_messages?.map((msg, idx) => (
183
  <div key={idx}>{msg}</div>
 
185
  </div>
186
  </div>
187
  </div>
188
+ </DialogContent>
189
+ </Dialog>
190
  )
191
  }
lightrag_webui/src/components/ui/Dialog.tsx CHANGED
@@ -19,7 +19,7 @@ const DialogOverlay = React.forwardRef<
19
  <DialogPrimitive.Overlay
20
  ref={ref}
21
  className={cn(
22
- 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',
23
  className
24
  )}
25
  {...props}
 
19
  <DialogPrimitive.Overlay
20
  ref={ref}
21
  className={cn(
22
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/30',
23
  className
24
  )}
25
  {...props}