verstak/frontend/src/lib/BrowserEvents.svelte

251 lines
5.6 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script>
import { t } from './i18n'
export let events = []
export let loading = false
export let onAccept = (ev) => {}
export let onDismiss = (ev) => {}
export let onAttach = (ev) => {}
export let onRefresh = () => {}
export let formatTime = (iso) => ''
function eventIcon(type) {
if (type === 'page_visit') return '🌐'
if (type === 'note_capture') return '📝'
if (type === 'screenshot') return '📸'
return '•'
}
function truncate(s, n) {
if (!s) return ''
return s.length > n ? s.substring(0, n) + '...' : s
}
</script>
<div class="browser-events">
<div class="browser-header">
<h3>{t('browserEvents', 'События браузера')}</h3>
<button class="refresh-btn" on:click={onRefresh} disabled={loading}>
{loading ? '⏳' : '🔄'}
</button>
</div>
{#if events.length === 0}
<div class="empty-state">
{#if loading}
<p class="loading">{t('loading', 'Загрузка...')}</p>
{:else}
<p class="empty-text">{t('noBrowserEvents', 'Нет событий браузера')}</p>
{/if}
</div>
{:else}
<div class="event-list">
{#each events as ev}
<div class="event-item" class:pending={ev.status === 'pending'}>
<div class="event-icon">{eventIcon(ev.type)}</div>
<div class="event-body">
<div class="event-domain">{ev.domain || '?'}</div>
<div class="event-title" title={ev.title}>{truncate(ev.title || ev.url, 80)}</div>
<div class="event-meta">
{#if ev.active_seconds > 0}
<span class="duration">{ev.active_seconds}с</span>
{/if}
{#if ev.ts_start}
<span class="time">{formatTime(ev.ts_start)}</span>
{/if}
{#if ev.status !== 'pending'}
<span class="status-badge status-{ev.status}">{ev.status}</span>
{/if}
</div>
{#if ev.selected_text}
<div class="event-text">"{truncate(ev.selected_text, 120)}"</div>
{/if}
</div>
{#if ev.status === 'pending'}
<div class="event-actions">
<button class="btn-accept" title="Принять как worklog"
on:click={() => onAccept(ev)}>✓</button>
<button class="btn-attach" title="Прикрепить к делу"
on:click={() => onAttach(ev)}>📎</button>
<button class="btn-dismiss" title="Удалить"
on:click={() => onDismiss(ev)}>✕</button>
</div>
{/if}
</div>
{/each}
</div>
{/if}
</div>
<style>
.browser-events {
padding: 8px 0;
}
.browser-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
padding: 0 4px;
}
.browser-header h3 {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--text-dim, #8892b0);
margin: 0;
}
.refresh-btn {
background: var(--surface2, #1e2d50);
border: none;
border-radius: 4px;
padding: 4px 8px;
cursor: pointer;
font-size: 12px;
transition: background 0.2s;
}
.refresh-btn:hover {
background: var(--surface, #16213e);
}
.empty-state {
padding: 24px;
text-align: center;
}
.empty-text, .loading {
color: var(--text-dim, #8892b0);
font-style: italic;
font-size: 12px;
}
.event-list {
display: flex;
flex-direction: column;
gap: 4px;
}
.event-item {
display: flex;
gap: 8px;
padding: 6px 8px;
background: var(--surface, #16213e);
border-radius: 6px;
transition: background 0.15s;
}
.event-item.pending {
border-left: 2px solid var(--accent, #0f9b8e);
}
.event-icon {
font-size: 16px;
line-height: 1.4;
min-width: 20px;
text-align: center;
}
.event-body {
flex: 1;
min-width: 0;
}
.event-domain {
font-size: 11px;
color: var(--accent, #0f9b8e);
font-weight: 500;
}
.event-title {
font-size: 12px;
color: var(--text, #e0e0e0);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.event-meta {
display: flex;
gap: 8px;
margin-top: 2px;
}
.duration, .time {
font-size: 10px;
color: var(--text-dim, #8892b0);
}
.status-badge {
font-size: 9px;
padding: 1px 4px;
border-radius: 3px;
text-transform: uppercase;
}
.status-accepted {
background: rgba(46, 204, 113, 0.2);
color: #2ecc71;
}
.status-dismissed {
background: rgba(231, 76, 60, 0.2);
color: #e74c3c;
}
.status-attached {
background: rgba(52, 152, 219, 0.2);
color: #3498db;
}
.event-text {
font-size: 11px;
color: var(--text-dim, #8892b0);
font-style: italic;
margin-top: 2px;
padding: 2px 6px;
background: rgba(255,255,255,0.03);
border-radius: 3px;
}
.event-actions {
display: flex;
gap: 2px;
align-items: flex-start;
}
.event-actions button {
background: none;
border: 1px solid var(--surface2, #1e2d50);
border-radius: 4px;
width: 24px;
height: 24px;
cursor: pointer;
font-size: 11px;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
transition: all 0.15s;
}
.btn-accept:hover {
background: rgba(46, 204, 113, 0.2);
border-color: #2ecc71;
}
.btn-attach:hover {
background: rgba(52, 152, 219, 0.2);
border-color: #3498db;
}
.btn-dismiss:hover {
background: rgba(231, 76, 60, 0.2);
border-color: #e74c3c;
}
</style>