Spaces:
Sleeping
Sleeping
| <template> | |
| <div class="modal-overlay" @click.self="$emit('close')"> | |
| <div class="details-modal-content"> | |
| <div class="modal-header"> | |
| <div class="agent-info"> | |
| <div class="agent-avatar" :style="{ backgroundColor: agent.color || '#6B7280' }"> | |
| {{ agent.name?.charAt(0) || 'A' }} | |
| </div> | |
| <div> | |
| <h2 class="agent-name">{{ agent.name }}</h2> | |
| <p class="agent-type">{{ agent.type }} Agent</p> | |
| </div> | |
| </div> | |
| <button class="close-button" @click="$emit('close')"> | |
| ✕ | |
| </button> | |
| </div> | |
| <div class="modal-body"> | |
| <!-- Status Section --> | |
| <div class="section"> | |
| <h3 class="section-title">Status</h3> | |
| <div class="status-info"> | |
| <div class="status-item"> | |
| <span class="status-label">Current Status:</span> | |
| <span | |
| class="status-badge" | |
| :class="{ | |
| 'bg-green-100 text-green-800': agent.status === 'active', | |
| 'bg-red-100 text-red-800': agent.status === 'inactive', | |
| 'bg-yellow-100 text-yellow-800': agent.status === 'starting' | |
| }" | |
| > | |
| {{ agent.status || 'Unknown' }} | |
| </span> | |
| </div> | |
| <div class="status-item"> | |
| <span class="status-label">Created:</span> | |
| <span>{{ formatDate(agent.created_at) }}</span> | |
| </div> | |
| <div class="status-item"> | |
| <span class="status-label">Last Active:</span> | |
| <span>{{ formatDate(agent.last_active || agent.created_at) }}</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Metrics Section --> | |
| <div class="section"> | |
| <h3 class="section-title">Performance Metrics</h3> | |
| <div class="metrics-grid"> | |
| <div class="metric-card"> | |
| <div class="metric-value">{{ agent.metrics?.messages_processed || 0 }}</div> | |
| <div class="metric-label">Messages Processed</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-value">{{ agent.metrics?.average_response_time?.toFixed(2) || '0.00' }}s</div> | |
| <div class="metric-label">Avg Response Time</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-value">{{ agent.metrics?.success_rate || '100' }}%</div> | |
| <div class="metric-label">Success Rate</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-value">{{ agent.metrics?.uptime || '0' }}h</div> | |
| <div class="metric-label">Uptime</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Configuration Section --> | |
| <div class="section"> | |
| <h3 class="section-title">Configuration</h3> | |
| <div class="config-info"> | |
| <div class="config-item"> | |
| <span class="config-label">Name:</span> | |
| <input | |
| v-model="editForm.name" | |
| class="config-input" | |
| :disabled="!editing" | |
| /> | |
| </div> | |
| <div class="config-item"> | |
| <span class="config-label">Type:</span> | |
| <select | |
| v-model="editForm.type" | |
| class="config-input" | |
| :disabled="!editing" | |
| > | |
| <option value="coordinator">Coordinator</option> | |
| <option value="developer">Developer</option> | |
| <option value="analyst">Analyst</option> | |
| <option value="specialist">Specialist</option> | |
| </select> | |
| </div> | |
| <div class="config-item"> | |
| <span class="config-label">Description:</span> | |
| <textarea | |
| v-model="editForm.description" | |
| class="config-input resize-y" | |
| rows="3" | |
| :disabled="!editing" | |
| ></textarea> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="modal-footer"> | |
| <button class="secondary-button" @click="$emit('close')"> | |
| Close | |
| </button> | |
| <button | |
| v-if="!editing" | |
| class="primary-button" | |
| @click="startEdit" | |
| > | |
| Edit Agent | |
| </button> | |
| <div v-else class="edit-actions"> | |
| <button class="cancel-button" @click="cancelEdit"> | |
| Cancel | |
| </button> | |
| <button class="save-button" @click="saveChanges"> | |
| Save Changes | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </template> | |
| <script> | |
| import { ref, reactive } from 'vue' | |
| export default { | |
| name: 'AgentDetailsModal', | |
| props: { | |
| agent: { | |
| type: Object, | |
| required: true | |
| } | |
| }, | |
| emits: ['close', 'update'], | |
| setup(props, { emit }) { | |
| const editing = ref(false) | |
| const editForm = reactive({ | |
| name: props.agent.name, | |
| type: props.agent.type, | |
| description: props.agent.description || '' | |
| }) | |
| const startEdit = () => { | |
| editing.value = true | |
| } | |
| const cancelEdit = () => { | |
| editing.value = false | |
| // Reset form | |
| editForm.name = props.agent.name | |
| editForm.type = props.agent.type | |
| editForm.description = props.agent.description || '' | |
| } | |
| const saveChanges = () => { | |
| const updatedAgent = { | |
| ...props.agent, | |
| name: editForm.name, | |
| type: editForm.type, | |
| description: editForm.description | |
| } | |
| emit('update', updatedAgent) | |
| editing.value = false | |
| } | |
| const formatDate = (dateString) => { | |
| if (!dateString) return 'Unknown' | |
| return new Date(dateString).toLocaleString('de-DE') | |
| } | |
| return { | |
| editing, | |
| editForm, | |
| startEdit, | |
| cancelEdit, | |
| saveChanges, | |
| formatDate | |
| } | |
| } | |
| } | |
| </script> | |
| <style scoped> | |
| .modal-overlay { | |
| @apply fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50; | |
| } | |
| .details-modal-content { | |
| @apply bg-white rounded-lg shadow-xl w-full max-w-4xl mx-4 max-h-screen flex flex-col; | |
| } | |
| .modal-header { | |
| @apply flex items-center justify-between p-6 border-b border-gray-200; | |
| } | |
| .agent-info { | |
| @apply flex items-center space-x-4; | |
| } | |
| .agent-avatar { | |
| @apply w-12 h-12 rounded-lg flex items-center justify-center text-white font-medium text-lg; | |
| } | |
| .agent-name { | |
| @apply text-xl font-semibold text-gray-900; | |
| } | |
| .agent-type { | |
| @apply text-sm text-gray-600 capitalize; | |
| } | |
| .close-button { | |
| @apply text-gray-400 hover:text-gray-600 text-xl font-bold w-8 h-8 flex items-center justify-center; | |
| } | |
| .modal-body { | |
| @apply flex-1 overflow-y-auto p-6 space-y-8; | |
| } | |
| .section { | |
| @apply space-y-4; | |
| } | |
| .section-title { | |
| @apply text-lg font-semibold text-gray-900 border-b border-gray-200 pb-2; | |
| } | |
| .status-info { | |
| @apply space-y-3; | |
| } | |
| .status-item { | |
| @apply flex items-center justify-between; | |
| } | |
| .status-label { | |
| @apply text-sm font-medium text-gray-700; | |
| } | |
| .status-badge { | |
| @apply px-2 py-1 text-xs font-medium rounded-full; | |
| } | |
| .metrics-grid { | |
| @apply grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4; | |
| } | |
| .metric-card { | |
| @apply bg-gray-50 rounded-lg p-4 text-center; | |
| } | |
| .metric-value { | |
| @apply text-2xl font-bold text-gray-900; | |
| } | |
| .metric-label { | |
| @apply text-sm text-gray-600 mt-1; | |
| } | |
| .config-info { | |
| @apply space-y-4; | |
| } | |
| .config-item { | |
| @apply space-y-2; | |
| } | |
| .config-label { | |
| @apply block text-sm font-medium text-gray-700; | |
| } | |
| .config-input { | |
| @apply w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed; | |
| } | |
| .modal-footer { | |
| @apply flex items-center justify-end space-x-3 p-6 border-t border-gray-200; | |
| } | |
| .edit-actions { | |
| @apply flex space-x-2; | |
| } | |
| .secondary-button { | |
| @apply px-4 py-2 border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50 font-medium; | |
| } | |
| .primary-button { | |
| @apply px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 font-medium; | |
| } | |
| .cancel-button { | |
| @apply px-4 py-2 border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50 font-medium; | |
| } | |
| .save-button { | |
| @apply px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 font-medium; | |
| } | |
| </style> |