- Database: activity_log table with indexes - Backend: Activity logger service + timeline API - Frontend: Timeline.vue with date grouping and filtering - Integration: Upload route logs activity - UI: Modern timeline with infinite scroll Backend changes: - migrations/010_activity_timeline.sql: Activity log schema - services/activity-logger.js: Log events to timeline - routes/timeline.js: GET /api/organizations/:orgId/timeline - routes/upload.js: Integrate activity logging - index.js: Register timeline route Frontend changes: - views/Timeline.vue: Timeline component with date grouping - router.js: Add /timeline route with auth - views/HomeView.vue: Add Timeline navigation button Features: - Reverse chronological event feed - Date grouping (Today, Yesterday, This Week, etc.) - Event type filtering (uploads, maintenance, etc.) - Infinite scroll pagination - User attribution - Links to source documents Resolves: Timeline feature spec
86 lines
1.9 KiB
JavaScript
86 lines
1.9 KiB
JavaScript
/**
|
|
* Vue Router configuration
|
|
*/
|
|
|
|
import { createRouter, createWebHistory } from 'vue-router'
|
|
import HomeView from './views/HomeView.vue'
|
|
|
|
const router = createRouter({
|
|
history: createWebHistory(import.meta.env.BASE_URL),
|
|
routes: [
|
|
{
|
|
path: '/',
|
|
name: 'home',
|
|
component: HomeView
|
|
},
|
|
{
|
|
path: '/search',
|
|
name: 'search',
|
|
component: () => import('./views/SearchView.vue')
|
|
},
|
|
{
|
|
path: '/document/:id',
|
|
name: 'document',
|
|
component: () => import('./views/DocumentView.vue')
|
|
},
|
|
{
|
|
path: '/jobs',
|
|
name: 'jobs',
|
|
component: () => import('./views/JobsView.vue')
|
|
},
|
|
{
|
|
path: '/stats',
|
|
name: 'stats',
|
|
component: () => import('./views/StatsView.vue')
|
|
},
|
|
{
|
|
path: '/timeline',
|
|
name: 'timeline',
|
|
component: () => import('./views/Timeline.vue'),
|
|
meta: { requiresAuth: true }
|
|
},
|
|
{
|
|
path: '/library',
|
|
name: 'library',
|
|
component: () => import('./views/LibraryView.vue')
|
|
},
|
|
{
|
|
path: '/login',
|
|
name: 'login',
|
|
component: () => import('./views/AuthView.vue'),
|
|
meta: { requiresGuest: true }
|
|
},
|
|
{
|
|
path: '/account',
|
|
name: 'account',
|
|
component: () => import('./views/AccountView.vue'),
|
|
meta: { requiresAuth: true }
|
|
}
|
|
]
|
|
})
|
|
|
|
// Navigation guards
|
|
router.beforeEach((to, from, next) => {
|
|
const accessToken = localStorage.getItem('accessToken')
|
|
const isAuthenticated = !!accessToken
|
|
|
|
// Check if route requires authentication
|
|
if (to.meta.requiresAuth && !isAuthenticated) {
|
|
// Redirect to login page with return URL
|
|
next({
|
|
name: 'login',
|
|
query: { redirect: to.fullPath }
|
|
})
|
|
}
|
|
// Check if route requires guest (not authenticated)
|
|
else if (to.meta.requiresGuest && isAuthenticated) {
|
|
// Redirect to home if already logged in
|
|
next({ name: 'home' })
|
|
}
|
|
// Allow navigation
|
|
else {
|
|
next()
|
|
}
|
|
})
|
|
|
|
export default router
|