feat: add Back to app button to redirect to last non-settings page (#821)
* add 'back to app' button to redirect to last non-settings page Users struggle to navigate back from the Settings page. I'd like to add a backwards arrow icon in the top left of the Settings page that navigates the user back to where they were before (perhaps like a browser back). What's the best way to go about this? * i18n * remove session storage use global state
This commit is contained in:
committed by
GitHub
parent
b797a9549c
commit
3aafd5d96b
@@ -6,6 +6,7 @@ import { Navbar } from '@/components/layout/navbar';
|
||||
import { Projects } from '@/pages/projects';
|
||||
import { ProjectTasks } from '@/pages/project-tasks';
|
||||
import { useTaskViewManager } from '@/hooks/useTaskViewManager';
|
||||
import { usePreviousPath } from '@/hooks/usePreviousPath';
|
||||
|
||||
import {
|
||||
AgentSettings,
|
||||
@@ -37,6 +38,9 @@ function AppContent() {
|
||||
const { config, updateAndSaveConfig, loading } = useUserSystem();
|
||||
const { isFullscreen } = useTaskViewManager();
|
||||
|
||||
// Track previous path for back navigation
|
||||
usePreviousPath();
|
||||
|
||||
const showNavbar = !isFullscreen;
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
28
frontend/src/hooks/usePreviousPath.ts
Normal file
28
frontend/src/hooks/usePreviousPath.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
const globalVisited: string[] = [];
|
||||
|
||||
export function usePreviousPath() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
// Track pathnames as user navigates
|
||||
useEffect(() => {
|
||||
if (globalVisited[globalVisited.length - 1] !== location.pathname) {
|
||||
globalVisited.push(location.pathname);
|
||||
// Keep only last 50 entries to prevent memory bloat
|
||||
if (globalVisited.length > 50) {
|
||||
globalVisited.splice(0, globalVisited.length - 50);
|
||||
}
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
return useCallback(() => {
|
||||
// Find last non-settings route in history
|
||||
const lastNonSettingsPath = [...globalVisited]
|
||||
.reverse()
|
||||
.find((p) => !p.startsWith('/settings'));
|
||||
navigate(lastNonSettingsPath || '/');
|
||||
}, [navigate]);
|
||||
}
|
||||
@@ -8,7 +8,8 @@
|
||||
"agents": "Agents",
|
||||
"agentsDesc": "Coding agent configurations",
|
||||
"mcp": "MCP Servers",
|
||||
"mcpDesc": "Model Context Protocol servers"
|
||||
"mcpDesc": "Model Context Protocol servers",
|
||||
"backToApp": "Back to app"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"agents": "Agentes",
|
||||
"agentsDesc": "Configuraciones de agentes",
|
||||
"mcp": "Servidores MCP",
|
||||
"mcpDesc": "Servidores de Protocolo de Contexto de Modelo (MCP)"
|
||||
"mcpDesc": "Servidores de Protocolo de Contexto de Modelo (MCP)",
|
||||
"backToApp": "Volver a la app"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
@@ -134,7 +135,10 @@
|
||||
"mcp": {
|
||||
"title": "Configuración de Servidor MCP",
|
||||
"description": "Configura los servidores del Protocolo de Contexto de Modelos (MCP) para ampliar las capacidades del agente de codificación con herramientas y recursos personalizados.",
|
||||
"loading": "Cargando configuración MCP...",
|
||||
"loading": {
|
||||
"jsonEditor": "Cargando...",
|
||||
"configuration": "Cargando configuración actual del servidor MCP..."
|
||||
},
|
||||
"applying": "Aplicando configuración...",
|
||||
"labels": {
|
||||
"agent": "Agente",
|
||||
@@ -145,10 +149,6 @@
|
||||
"serverHelper": "Haz clic en una tarjeta para insertar ese Servidor MCP en el JSON de arriba.",
|
||||
"saveLocation": "Los cambios se guardarán en:"
|
||||
},
|
||||
"loading": {
|
||||
"jsonEditor": "Cargando...",
|
||||
"configuration": "Cargando configuración actual del servidor MCP..."
|
||||
},
|
||||
"errors": {
|
||||
"loadFailed": "Error al cargar la configuración.",
|
||||
"invalidJson": "Formato JSON inválido",
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"agents": "エージェント",
|
||||
"agentsDesc": "コーディングエージェントの設定",
|
||||
"mcp": "MCPサーバー",
|
||||
"mcpDesc": "モデルコンテキストプロトコルサーバー"
|
||||
"mcpDesc": "モデルコンテキストプロトコルサーバー",
|
||||
"backToApp": "アプリに戻る"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { NavLink, Outlet } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Settings, Cpu, Server } from 'lucide-react';
|
||||
import { Settings, Cpu, Server, ArrowLeft } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { usePreviousPath } from '@/hooks/usePreviousPath';
|
||||
|
||||
const settingsNavigation = [
|
||||
{
|
||||
@@ -20,6 +22,7 @@ const settingsNavigation = [
|
||||
|
||||
export function SettingsLayout() {
|
||||
const { t } = useTranslation('settings');
|
||||
const goToPreviousPath = usePreviousPath();
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
@@ -27,6 +30,10 @@ export function SettingsLayout() {
|
||||
{/* Sidebar Navigation */}
|
||||
<aside className="w-full lg:w-64 lg:shrink-0 lg:sticky lg:top-8 lg:h-fit lg:max-h-[calc(100vh-4rem)] lg:overflow-y-auto">
|
||||
<div className="space-y-1">
|
||||
<Button variant="ghost" onClick={goToPreviousPath} className="mb-4">
|
||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
||||
{t('settings.layout.nav.backToApp')}
|
||||
</Button>
|
||||
<h2 className="px-3 py-2 text-lg font-semibold">
|
||||
{t('settings.layout.nav.title')}
|
||||
</h2>
|
||||
|
||||
Reference in New Issue
Block a user