sam 1f0936763b Add traffic generator improvements: mode switching, ping, responder echo, RFC2544 fixes
Adds sender/responder mode switching via API, QuickPing component, echo-mode
responder with dedicated container, improved flow state sync, and RFC2544
test runner enhancements. Includes UI improvements across all traffic-gen
components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 14:22:41 -07:00

77 lines
2.8 KiB
Vue

<template>
<div class="quick-ping">
<div class="ping-row">
<input
v-model="target"
placeholder="IP address to ping..."
@keyup.enter="runPing"
:disabled="pinging"
/>
<button class="btn-ping" @click="runPing" :disabled="!target || pinging">
{{ pinging ? 'Pinging...' : 'Ping' }}
</button>
</div>
<div v-if="result" class="ping-result" :class="result.reachable ? 'reachable' : 'unreachable'">
<div class="ping-summary">
<span class="ping-target">{{ result.target }}</span>
<span v-if="result.reachable" class="ping-status ok">Reachable</span>
<span v-else class="ping-status fail">Unreachable</span>
</div>
<div v-if="result.reachable && result.stats" class="ping-stats">
<span>{{ result.received }}/{{ result.sent }} replies</span>
<span>Min: {{ result.stats.min_ms }}ms</span>
<span>Avg: {{ result.stats.avg_ms }}ms</span>
<span>Max: {{ result.stats.max_ms }}ms</span>
<span>Loss: {{ result.loss_pct }}%</span>
</div>
<div v-if="result.error" class="ping-error">{{ result.error }}</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { api } from '../api.js'
const target = ref('')
const pinging = ref(false)
const result = ref(null)
async function runPing() {
if (!target.value || pinging.value) return
pinging.value = true
result.value = null
try {
result.value = await api.ping(target.value, 5)
} catch (e) {
result.value = { target: target.value, reachable: false, error: e.message }
} finally {
pinging.value = false
}
}
</script>
<style scoped>
.quick-ping { margin-bottom: 16px; }
.ping-row { display: flex; gap: 6px; }
.ping-row input { flex: 1; }
.btn-ping {
padding: 6px 16px; font-weight: 600; font-size: 13px;
background: var(--accent); color: #fff; white-space: nowrap;
}
.btn-ping:disabled { opacity: 0.4; }
.ping-result {
margin-top: 8px; padding: 8px 12px;
border-radius: var(--radius); font-size: 13px;
}
.ping-result.reachable { background: rgba(72,187,120,0.1); border: 1px solid rgba(72,187,120,0.3); }
.ping-result.unreachable { background: rgba(252,129,129,0.1); border: 1px solid rgba(252,129,129,0.3); }
.ping-summary { display: flex; align-items: center; gap: 10px; }
.ping-target { font-weight: 600; font-family: monospace; }
.ping-status { font-size: 11px; padding: 2px 8px; border-radius: 10px; font-weight: 600; }
.ping-status.ok { background: rgba(72,187,120,0.2); color: var(--success); }
.ping-status.fail { background: rgba(252,129,129,0.2); color: var(--danger); }
.ping-stats { display: flex; gap: 12px; margin-top: 6px; font-size: 12px; color: var(--muted); font-family: monospace; }
.ping-error { margin-top: 4px; color: var(--danger); font-size: 12px; }
</style>