Stijnus
commited on
Commit
·
a286e3b
1
Parent(s):
2b585c2
ui fix
Browse files
app/components/settings/event-logs/EventLogsTab.tsx
CHANGED
@@ -4,6 +4,7 @@ import { Switch } from '~/components/ui/Switch';
|
|
4 |
import { logStore, type LogEntry } from '~/lib/stores/logs';
|
5 |
import { useStore } from '@nanostores/react';
|
6 |
import { classNames } from '~/utils/classNames';
|
|
|
7 |
|
8 |
interface SelectOption {
|
9 |
value: string;
|
@@ -301,104 +302,104 @@ export function EventLogsTab() {
|
|
301 |
{/* Filters */}
|
302 |
<div className="flex items-center gap-4 -mt-2">
|
303 |
{/* Level Filter */}
|
304 |
-
<
|
305 |
-
<
|
306 |
-
|
307 |
-
setShowLevelFilter(!showLevelFilter);
|
308 |
-
setShowCategoryFilter(false);
|
309 |
-
}}
|
310 |
-
className="flex items-center gap-2 px-3 py-1.5 rounded-lg hover:bg-purple-500/10 dark:hover:bg-purple-500/20 hover:text-purple-500 dark:hover:text-purple-500 transition-colors"
|
311 |
-
>
|
312 |
-
<div
|
313 |
-
className={classNames('text-sm', selectedLevelOption?.icon || 'i-ph:funnel')}
|
314 |
-
style={{ color: selectedLevelOption?.color }}
|
315 |
-
/>
|
316 |
-
<div className="text-sm text-bolt-elements-textSecondary">{selectedLevelOption?.label || 'All Levels'}</div>
|
317 |
-
<div
|
318 |
className={classNames(
|
319 |
-
'
|
320 |
-
|
|
|
|
|
|
|
|
|
|
|
321 |
)}
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
<
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
350 |
|
351 |
<div className="w-px h-4 bg-gray-200 dark:bg-gray-700" />
|
352 |
|
353 |
{/* Category Filter */}
|
354 |
-
<
|
355 |
-
<
|
356 |
-
|
357 |
-
setShowCategoryFilter(!showCategoryFilter);
|
358 |
-
setShowLevelFilter(false);
|
359 |
-
}}
|
360 |
-
className="flex items-center gap-2 px-3 py-1.5 rounded-lg hover:bg-purple-500/10 dark:hover:bg-purple-500/20 hover:text-purple-500 dark:hover:text-purple-500 transition-colors"
|
361 |
-
>
|
362 |
-
<div
|
363 |
-
className={classNames('text-sm', selectedCategoryOption?.icon || 'i-ph:squares-four')}
|
364 |
-
style={{ color: selectedCategoryOption?.color }}
|
365 |
-
/>
|
366 |
-
<div className="text-sm text-bolt-elements-textSecondary">
|
367 |
-
{selectedCategoryOption?.label || 'All Categories'}
|
368 |
-
</div>
|
369 |
-
<div
|
370 |
className={classNames(
|
371 |
-
'
|
372 |
-
|
|
|
|
|
|
|
|
|
|
|
373 |
)}
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
<
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
402 |
</div>
|
403 |
|
404 |
{/* Logs Container */}
|
|
|
4 |
import { logStore, type LogEntry } from '~/lib/stores/logs';
|
5 |
import { useStore } from '@nanostores/react';
|
6 |
import { classNames } from '~/utils/classNames';
|
7 |
+
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
|
8 |
|
9 |
interface SelectOption {
|
10 |
value: string;
|
|
|
302 |
{/* Filters */}
|
303 |
<div className="flex items-center gap-4 -mt-2">
|
304 |
{/* Level Filter */}
|
305 |
+
<DropdownMenu.Root open={showLevelFilter} onOpenChange={setShowLevelFilter}>
|
306 |
+
<DropdownMenu.Trigger asChild>
|
307 |
+
<button
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
308 |
className={classNames(
|
309 |
+
'flex items-center gap-2',
|
310 |
+
'rounded-lg px-3 py-1.5',
|
311 |
+
'text-sm text-gray-900 dark:text-white',
|
312 |
+
'bg-[#FAFAFA] dark:bg-[#0A0A0A]',
|
313 |
+
'border border-[#E5E5E5] dark:border-[#1A1A1A]',
|
314 |
+
'hover:bg-purple-500/10 dark:hover:bg-purple-500/20',
|
315 |
+
'transition-all duration-200',
|
316 |
)}
|
317 |
+
>
|
318 |
+
<div
|
319 |
+
className={classNames('text-lg', selectedLevelOption?.icon || 'i-ph:funnel')}
|
320 |
+
style={{ color: selectedLevelOption?.color }}
|
321 |
+
/>
|
322 |
+
<span>{selectedLevelOption?.label || 'All Levels'}</span>
|
323 |
+
<span className="i-ph:caret-down text-lg text-gray-500 dark:text-gray-400" />
|
324 |
+
</button>
|
325 |
+
</DropdownMenu.Trigger>
|
326 |
+
|
327 |
+
<DropdownMenu.Portal>
|
328 |
+
<DropdownMenu.Content
|
329 |
+
className="min-w-[200px] bg-white dark:bg-[#0A0A0A] rounded-lg shadow-lg py-1 z-[250] animate-in fade-in-0 zoom-in-95 border border-[#E5E5E5] dark:border-[#1A1A1A]"
|
330 |
+
sideOffset={5}
|
331 |
+
align="start"
|
332 |
+
side="bottom"
|
333 |
+
>
|
334 |
+
{logLevelOptions.map((option) => (
|
335 |
+
<DropdownMenu.Item
|
336 |
+
key={option.value}
|
337 |
+
className="group flex items-center px-4 py-2.5 text-sm text-gray-700 dark:text-gray-200 hover:bg-purple-500/10 dark:hover:bg-purple-500/20 cursor-pointer transition-colors"
|
338 |
+
onClick={() => setSelectedLevel(option.value)}
|
339 |
+
>
|
340 |
+
<div className="mr-3 flex h-5 w-5 items-center justify-center">
|
341 |
+
<div
|
342 |
+
className={classNames(option.icon, 'text-lg group-hover:text-purple-500 transition-colors')}
|
343 |
+
style={{ color: option.color }}
|
344 |
+
/>
|
345 |
+
</div>
|
346 |
+
<span className="group-hover:text-purple-500 transition-colors">{option.label}</span>
|
347 |
+
</DropdownMenu.Item>
|
348 |
+
))}
|
349 |
+
</DropdownMenu.Content>
|
350 |
+
</DropdownMenu.Portal>
|
351 |
+
</DropdownMenu.Root>
|
352 |
|
353 |
<div className="w-px h-4 bg-gray-200 dark:bg-gray-700" />
|
354 |
|
355 |
{/* Category Filter */}
|
356 |
+
<DropdownMenu.Root open={showCategoryFilter} onOpenChange={setShowCategoryFilter}>
|
357 |
+
<DropdownMenu.Trigger asChild>
|
358 |
+
<button
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
359 |
className={classNames(
|
360 |
+
'flex items-center gap-2',
|
361 |
+
'rounded-lg px-3 py-1.5',
|
362 |
+
'text-sm text-gray-900 dark:text-white',
|
363 |
+
'bg-[#FAFAFA] dark:bg-[#0A0A0A]',
|
364 |
+
'border border-[#E5E5E5] dark:border-[#1A1A1A]',
|
365 |
+
'hover:bg-purple-500/10 dark:hover:bg-purple-500/20',
|
366 |
+
'transition-all duration-200',
|
367 |
)}
|
368 |
+
>
|
369 |
+
<div
|
370 |
+
className={classNames('text-lg', selectedCategoryOption?.icon || 'i-ph:squares-four')}
|
371 |
+
style={{ color: selectedCategoryOption?.color }}
|
372 |
+
/>
|
373 |
+
<span>{selectedCategoryOption?.label || 'All Categories'}</span>
|
374 |
+
<span className="i-ph:caret-down text-lg text-gray-500 dark:text-gray-400" />
|
375 |
+
</button>
|
376 |
+
</DropdownMenu.Trigger>
|
377 |
+
|
378 |
+
<DropdownMenu.Portal>
|
379 |
+
<DropdownMenu.Content
|
380 |
+
className="min-w-[200px] bg-white dark:bg-[#0A0A0A] rounded-lg shadow-lg py-1 z-[250] animate-in fade-in-0 zoom-in-95 border border-[#E5E5E5] dark:border-[#1A1A1A]"
|
381 |
+
sideOffset={5}
|
382 |
+
align="start"
|
383 |
+
side="bottom"
|
384 |
+
>
|
385 |
+
{logCategoryOptions.map((option) => (
|
386 |
+
<DropdownMenu.Item
|
387 |
+
key={option.value}
|
388 |
+
className="group flex items-center px-4 py-2.5 text-sm text-gray-700 dark:text-gray-200 hover:bg-purple-500/10 dark:hover:bg-purple-500/20 cursor-pointer transition-colors"
|
389 |
+
onClick={() => setSelectedCategory(option.value)}
|
390 |
+
>
|
391 |
+
<div className="mr-3 flex h-5 w-5 items-center justify-center">
|
392 |
+
<div
|
393 |
+
className={classNames(option.icon, 'text-lg group-hover:text-purple-500 transition-colors')}
|
394 |
+
style={{ color: option.color }}
|
395 |
+
/>
|
396 |
+
</div>
|
397 |
+
<span className="group-hover:text-purple-500 transition-colors">{option.label}</span>
|
398 |
+
</DropdownMenu.Item>
|
399 |
+
))}
|
400 |
+
</DropdownMenu.Content>
|
401 |
+
</DropdownMenu.Portal>
|
402 |
+
</DropdownMenu.Root>
|
403 |
</div>
|
404 |
|
405 |
{/* Logs Container */}
|
app/components/settings/notifications/NotificationsTab.tsx
CHANGED
@@ -125,15 +125,15 @@ const NotificationsTab = () => {
|
|
125 |
return details.message ? <p className="text-sm text-gray-600 dark:text-gray-400">{details.message}</p> : null;
|
126 |
};
|
127 |
|
128 |
-
const filterOptions: { id: FilterType; label: string; icon: string }[] = [
|
129 |
-
{ id: 'all', label: 'All Notifications', icon: 'i-ph:bell' },
|
130 |
-
{ id: 'system', label: 'System', icon: 'i-ph:gear' },
|
131 |
-
{ id: 'update', label: 'Updates', icon: 'i-ph:arrow-circle-up' },
|
132 |
-
{ id: 'error', label: 'Errors', icon: 'i-ph:warning-circle' },
|
133 |
-
{ id: 'warning', label: 'Warnings', icon: 'i-ph:warning' },
|
134 |
-
{ id: 'info', label: 'Information', icon: 'i-ph:info' },
|
135 |
-
{ id: 'provider', label: 'Providers', icon: 'i-ph:robot' },
|
136 |
-
{ id: 'network', label: 'Network', icon: 'i-ph:wifi-high' },
|
137 |
];
|
138 |
|
139 |
return (
|
@@ -153,10 +153,8 @@ const NotificationsTab = () => {
|
|
153 |
)}
|
154 |
>
|
155 |
<span
|
156 |
-
className={classNames(
|
157 |
-
|
158 |
-
'text-lg text-gray-500 dark:text-gray-400',
|
159 |
-
)}
|
160 |
/>
|
161 |
{filterOptions.find((opt) => opt.id === filter)?.label || 'Filter Notifications'}
|
162 |
<span className="i-ph:caret-down text-lg text-gray-500 dark:text-gray-400" />
|
@@ -165,7 +163,7 @@ const NotificationsTab = () => {
|
|
165 |
|
166 |
<DropdownMenu.Portal>
|
167 |
<DropdownMenu.Content
|
168 |
-
className="min-w-[200px] bg-white dark:bg-
|
169 |
sideOffset={5}
|
170 |
align="start"
|
171 |
side="bottom"
|
@@ -178,10 +176,8 @@ const NotificationsTab = () => {
|
|
178 |
>
|
179 |
<div className="mr-3 flex h-5 w-5 items-center justify-center">
|
180 |
<div
|
181 |
-
className={classNames(
|
182 |
-
|
183 |
-
'text-gray-500 dark:text-gray-400 group-hover:text-purple-500 transition-colors',
|
184 |
-
)}
|
185 |
/>
|
186 |
</div>
|
187 |
<span className="group-hover:text-purple-500 transition-colors">{option.label}</span>
|
|
|
125 |
return details.message ? <p className="text-sm text-gray-600 dark:text-gray-400">{details.message}</p> : null;
|
126 |
};
|
127 |
|
128 |
+
const filterOptions: { id: FilterType; label: string; icon: string; color: string }[] = [
|
129 |
+
{ id: 'all', label: 'All Notifications', icon: 'i-ph:bell', color: '#9333ea' },
|
130 |
+
{ id: 'system', label: 'System', icon: 'i-ph:gear', color: '#6b7280' },
|
131 |
+
{ id: 'update', label: 'Updates', icon: 'i-ph:arrow-circle-up', color: '#9333ea' },
|
132 |
+
{ id: 'error', label: 'Errors', icon: 'i-ph:warning-circle', color: '#ef4444' },
|
133 |
+
{ id: 'warning', label: 'Warnings', icon: 'i-ph:warning', color: '#f59e0b' },
|
134 |
+
{ id: 'info', label: 'Information', icon: 'i-ph:info', color: '#3b82f6' },
|
135 |
+
{ id: 'provider', label: 'Providers', icon: 'i-ph:robot', color: '#10b981' },
|
136 |
+
{ id: 'network', label: 'Network', icon: 'i-ph:wifi-high', color: '#6366f1' },
|
137 |
];
|
138 |
|
139 |
return (
|
|
|
153 |
)}
|
154 |
>
|
155 |
<span
|
156 |
+
className={classNames('text-lg', filterOptions.find((opt) => opt.id === filter)?.icon || 'i-ph:funnel')}
|
157 |
+
style={{ color: filterOptions.find((opt) => opt.id === filter)?.color }}
|
|
|
|
|
158 |
/>
|
159 |
{filterOptions.find((opt) => opt.id === filter)?.label || 'Filter Notifications'}
|
160 |
<span className="i-ph:caret-down text-lg text-gray-500 dark:text-gray-400" />
|
|
|
163 |
|
164 |
<DropdownMenu.Portal>
|
165 |
<DropdownMenu.Content
|
166 |
+
className="min-w-[200px] bg-white dark:bg-[#0A0A0A] rounded-lg shadow-lg py-1 z-[250] animate-in fade-in-0 zoom-in-95 border border-[#E5E5E5] dark:border-[#1A1A1A]"
|
167 |
sideOffset={5}
|
168 |
align="start"
|
169 |
side="bottom"
|
|
|
176 |
>
|
177 |
<div className="mr-3 flex h-5 w-5 items-center justify-center">
|
178 |
<div
|
179 |
+
className={classNames(option.icon, 'text-lg group-hover:text-purple-500 transition-colors')}
|
180 |
+
style={{ color: option.color }}
|
|
|
|
|
181 |
/>
|
182 |
</div>
|
183 |
<span className="group-hover:text-purple-500 transition-colors">{option.label}</span>
|