feat: enhance audit logging, add MCP settings, and production docker setup
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
- Implemented comprehensive audit logging for Tasks, Users, Settings, Goals, Labels, AI Chat, and Rewards. - Added Admin UI for MCP Server settings and Audit Logs. - Created docker-compose-production.yml with Traefik configuration. - Fixed backend bugs (missing storage methods, route closure). - Added Audit Logging Guidelines.
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Home, Calendar, List, LayoutGrid, Settings, CheckSquare, Target, Trophy, LogOut, Award } from 'lucide-react';
|
||||
import { Home, Calendar, List, LayoutGrid, Settings, CheckSquare, Target, Trophy, LogOut, Award, Bot, CalendarOff } from 'lucide-react';
|
||||
import { useQueryClient, useMutation, useQuery } from '@tanstack/react-query';
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Sidebar,
|
||||
@@ -13,12 +16,9 @@ import {
|
||||
useSidebar,
|
||||
SidebarTrigger,
|
||||
} from "@/components/ui/sidebar"
|
||||
import { useQueryClient, useMutation } from '@tanstack/react-query';
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { User } from "@shared/schema";
|
||||
import { Task, User } from '@shared/schema';
|
||||
import ThemeToggle from './ThemeToggle';
|
||||
import { useLocation } from "wouter";
|
||||
|
||||
import { GamificationBar } from './GamificationBar';
|
||||
|
||||
interface AppSidebarProps extends React.ComponentProps<typeof Sidebar> {
|
||||
@@ -32,6 +32,13 @@ export function AppSidebar({ user, ...props }: AppSidebarProps) {
|
||||
const queryClient = useQueryClient();
|
||||
const [location, setLocation] = useLocation();
|
||||
|
||||
// Fetch unscheduled count
|
||||
// const { data: unscheduledCount = 0 } = useQuery({
|
||||
// queryKey: ['/api/tasks'],
|
||||
// select: (tasks: Task[]) => tasks.filter(t => !t.dueDate && t.status !== 'done').length,
|
||||
// enabled: !!user
|
||||
// });
|
||||
|
||||
const logoutMutation = useMutation({
|
||||
mutationFn: async () => {
|
||||
await fetch("/api/logout", { method: "POST" });
|
||||
@@ -47,9 +54,11 @@ export function AppSidebar({ user, ...props }: AppSidebarProps) {
|
||||
{ title: t('navigation.tasks'), id: 'tasks', path: '/tasks', icon: Home, color: 'text-blue-500' },
|
||||
{ title: t('navigation.calendar'), id: 'calendar', path: '/calendar', icon: Calendar, color: 'text-violet-500' },
|
||||
{ title: t('navigation.weekList'), id: 'weeklist', path: '/weeklist', icon: List, color: 'text-pink-500' },
|
||||
{ title: t('unscheduled.title', 'Unscheduled'), id: 'unscheduled', path: '/unscheduled', icon: CalendarOff, color: 'text-slate-500' },
|
||||
{ title: t('navigation.kanban'), id: 'kanban', path: '/kanban', icon: LayoutGrid, color: 'text-orange-500' },
|
||||
{ title: t('navigation.achievements'), id: 'achievements', path: '/achievements', icon: Trophy, color: 'text-yellow-500' },
|
||||
{ title: t('navigation.leaderboard'), id: 'leaderboard', path: '/leaderboard', icon: Award, color: 'text-yellow-500' },
|
||||
...(user?.aiEnabled ? [{ title: t('navigation.aiChat', 'AI Chat'), id: 'ai-chat', path: '/ai', icon: Bot, color: 'text-indigo-500' }] : []),
|
||||
{ title: t('navigation.settings'), id: 'settings', path: '/settings', icon: Settings, color: 'text-gray-500' },
|
||||
]
|
||||
|
||||
@@ -82,7 +91,8 @@ export function AppSidebar({ user, ...props }: AppSidebarProps) {
|
||||
tooltip={item.title}
|
||||
className={`h-12 transition-all duration-200 ${location === item.path || (item.path !== '/' && location.startsWith(item.path))
|
||||
? 'bg-gradient-to-r from-violet-600 to-indigo-600 text-white shadow-md hover:from-violet-500 hover:to-indigo-500 hover:text-white'
|
||||
: 'hover:bg-sidebar-accent hover:pl-4'}`}
|
||||
: 'hover:bg-sidebar-accent hover:pl-4'
|
||||
}`}
|
||||
>
|
||||
<item.icon className={`transition-all duration-200 ${state === 'collapsed' ? 'size-7' : 'size-5'} ${location === item.path || (item.path !== '/' && location.startsWith(item.path)) ? 'text-white' : item.color}`} />
|
||||
{state !== 'collapsed' && (
|
||||
|
||||
Reference in New Issue
Block a user