Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ tests/test_logs/
CLAUDE.md
.DS_Store

# Frontend build output
mcphawk/web/static/*

# Node modules
node_modules/
frontend/node_modules/
Expand Down
Binary file modified examples/branding/mcphawk_screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 64 additions & 0 deletions frontend/src/App-original.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<template>
<div class="min-h-screen bg-gray-50 dark:bg-gray-900">
<!-- Header -->
<header class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
<div class="px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<div class="flex items-center">
<img src="/mcphawk_logo.png" alt="MCPHawk Logo" class="h-[62px]">
<ConnectionStatus class="ml-4" />
</div>
<div class="flex items-center space-x-4">
<StatsPanel />
<ThemeToggle />
</div>
</div>
</div>
</header>

<!-- Main Content -->
<main class="flex-1">
<div class="px-4 sm:px-6 lg:px-8 py-6">
<!-- Filters -->
<div class="mb-6">
<LogFilters />
</div>

<!-- Log Table -->
<div class="bg-white dark:bg-gray-800 shadow-xl rounded-xl overflow-hidden">
<LogTable />
</div>
</div>
</main>

<!-- Message Detail Modal -->
<MessageDetailModal />
</div>
</template>

<script setup>
import { onMounted, onUnmounted } from 'vue'
import { useLogStore } from '@/stores/logs'
import { useWebSocketStore } from '@/stores/websocket'
import ConnectionStatus from '@/components/common/ConnectionStatus.vue'
import ThemeToggle from '@/components/common/ThemeToggle.vue'
import StatsPanel from '@/components/Stats/StatsPanel.vue'
import LogFilters from '@/components/LogTable/LogFiltersModern.vue'
import LogTable from '@/components/LogTable/LogTable.vue'
import MessageDetailModal from '@/components/MessageDetail/MessageDetailModal.vue'

const logStore = useLogStore()
const wsStore = useWebSocketStore()

onMounted(() => {
// Load initial logs
logStore.fetchLogs()

// Connect WebSocket
wsStore.connect()
})

onUnmounted(() => {
wsStore.disconnect()
})
</script>
98 changes: 98 additions & 0 deletions frontend/src/App-sidebar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<template>
<div class="min-h-screen bg-gray-50 dark:bg-gray-900 flex flex-col">
<!-- Header -->
<header class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700 z-10">
<div class="px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<div class="flex items-center">
<button
@click="sidebarOpen = !sidebarOpen"
class="lg:hidden p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700"
>
<Bars3Icon v-if="!sidebarOpen" class="h-6 w-6" />
<XMarkIcon v-else class="h-6 w-6" />
</button>
<img src="/mcphawk_logo.png" alt="MCPHawk Logo" class="h-[62px] ml-2 lg:ml-0">
<ConnectionStatus class="ml-4" />
</div>
<div class="flex items-center space-x-4">
<StatsPanel />
<ThemeToggle />
</div>
</div>
</div>
</header>

<!-- Main Content Area -->
<div class="flex-1 flex overflow-hidden">
<!-- Sidebar -->
<aside
class="w-80 flex-shrink-0 overflow-hidden transition-all duration-300 lg:relative lg:translate-x-0"
:class="[
sidebarOpen ? 'translate-x-0' : '-translate-x-full',
'fixed inset-y-0 left-0 z-40 lg:static lg:inset-auto'
]"
>
<div class="h-full" style="margin-top: 65px;" class="lg:mt-0">
<LogFiltersSidebar />
</div>
</aside>

<!-- Mobile sidebar backdrop -->
<div
v-if="sidebarOpen"
@click="sidebarOpen = false"
class="lg:hidden fixed inset-0 bg-black/50 z-30"
style="margin-top: 65px;"
></div>

<!-- Main Content -->
<main class="flex-1 overflow-auto">
<div class="px-4 sm:px-6 lg:px-8 py-6">
<!-- Search Bar and Actions -->
<div class="mb-6">
<LogSearchBar />
</div>

<!-- Log Table -->
<div class="bg-white dark:bg-gray-800 shadow-xl rounded-xl overflow-hidden">
<LogTable />
</div>
</div>
</main>
</div>

<!-- Message Detail Modal -->
<MessageDetailModal />
</div>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from 'vue'
import { useLogStore } from '@/stores/logs'
import { useWebSocketStore } from '@/stores/websocket'
import ConnectionStatus from '@/components/common/ConnectionStatus.vue'
import ThemeToggle from '@/components/common/ThemeToggle.vue'
import StatsPanel from '@/components/Stats/StatsPanel.vue'
import LogFiltersSidebar from '@/components/LogTable/LogFiltersSidebar.vue'
import LogSearchBar from '@/components/LogTable/LogSearchBar.vue'
import LogTable from '@/components/LogTable/LogTable.vue'
import MessageDetailModal from '@/components/MessageDetail/MessageDetailModal.vue'
import { Bars3Icon, XMarkIcon } from '@heroicons/vue/24/outline'

const logStore = useLogStore()
const wsStore = useWebSocketStore()
const sidebarOpen = ref(false)

onMounted(() => {
// Load initial logs
logStore.fetchLogs()

// Connect WebSocket
wsStore.connect()
})

onUnmounted(() => {
wsStore.disconnect()
})
</script>
91 changes: 74 additions & 17 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
<template>
<div class="min-h-screen bg-gray-50 dark:bg-gray-900">
<div class="min-h-screen bg-gray-50 dark:bg-gray-900 flex flex-col">
<!-- Header -->
<header class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
<header class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700 z-10">
<div class="px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<div class="flex items-center">
<div class="flex items-center space-x-4">
<img src="/mcphawk_logo.png" alt="MCPHawk Logo" class="h-[62px]">
<ConnectionStatus class="ml-4" />
<div class="h-8 w-px bg-gray-300 dark:bg-gray-600"></div>
<button
@click="toggleSidebar"
class="flex items-center gap-2 px-3 py-1.5 rounded-lg text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700 transition-all duration-200"
:title="sidebarOpen ? 'Hide filters' : 'Show filters'"
>
<ViewColumnsIcon class="h-5 w-5" />
<span class="text-sm font-medium hidden sm:inline">
{{ sidebarOpen ? 'Hide' : 'Show' }} Filters
</span>
</button>
<ConnectionStatus />
</div>
<div class="flex items-center space-x-4">
<StatsPanel />
Expand All @@ -16,49 +27,95 @@
</div>
</header>

<!-- Main Content -->
<main class="flex-1">
<div class="px-4 sm:px-6 lg:px-8 py-4">
<!-- Filters -->
<div class="mb-4">
<LogFilters />
<!-- Main Content Area -->
<div class="flex-1 flex overflow-hidden">
<!-- Sidebar -->
<aside
:class="[
'w-64 flex-shrink-0 overflow-hidden transition-all duration-300',
windowWidth < 1024
? 'fixed inset-y-0 left-0 z-40'
: 'relative',
sidebarOpen
? 'translate-x-0'
: '-translate-x-full lg:hidden'
]"
>
<div class="h-full lg:h-full" :class="{'mt-16': true, 'lg:mt-0': true}">
<LogFiltersSidebar />
</div>
</aside>

<!-- Mobile sidebar backdrop -->
<div
v-if="sidebarOpen && windowWidth < 1024"
@click="sidebarOpen = false"
class="fixed inset-0 bg-black/50 z-30 mt-16"
></div>

<!-- Log Table -->
<div class="bg-white dark:bg-gray-800 shadow rounded-lg">
<LogTable />
<!-- Main Content -->
<main class="flex-1 overflow-auto">
<div class="px-4 sm:px-6 lg:px-8 py-6">
<!-- Search Bar and Actions -->
<div class="mb-6">
<LogSearchBar />
</div>

<!-- Log Table -->
<div class="bg-white dark:bg-gray-800 shadow-xl rounded-xl overflow-hidden">
<LogTable />
</div>
</div>
</div>
</main>
</main>
</div>

<!-- Message Detail Modal -->
<MessageDetailModal />
</div>
</template>

<script setup>
import { onMounted, onUnmounted } from 'vue'
import { onMounted, onUnmounted, ref } from 'vue'
import { useLogStore } from '@/stores/logs'
import { useWebSocketStore } from '@/stores/websocket'
import ConnectionStatus from '@/components/common/ConnectionStatus.vue'
import ThemeToggle from '@/components/common/ThemeToggle.vue'
import StatsPanel from '@/components/Stats/StatsPanel.vue'
import LogFilters from '@/components/LogTable/LogFilters.vue'
import LogFiltersSidebar from '@/components/LogTable/LogFiltersSidebar.vue'
import LogSearchBar from '@/components/LogTable/LogSearchBar.vue'
import LogTable from '@/components/LogTable/LogTable.vue'
import MessageDetailModal from '@/components/MessageDetail/MessageDetailModal.vue'
import { ViewColumnsIcon } from '@heroicons/vue/24/outline'

const logStore = useLogStore()
const wsStore = useWebSocketStore()
const sidebarOpen = ref(true) // Default to open on desktop
const windowWidth = ref(window.innerWidth)

// Handle window resize
const handleResize = () => {
windowWidth.value = window.innerWidth
}

// Toggle sidebar
const toggleSidebar = () => {
sidebarOpen.value = !sidebarOpen.value
}

onMounted(() => {
// Load initial logs
logStore.fetchLogs()

// Connect WebSocket
wsStore.connect()

// Add resize listener
window.addEventListener('resize', handleResize)
handleResize() // Initial check
})

onUnmounted(() => {
wsStore.disconnect()
window.removeEventListener('resize', handleResize)
})
</script>
Loading