A deployable markdown editor that connects with your self hosted files and lets you edit in a beautiful interface

feat: updates migration and dashboard file

+12 -18
+1 -1
backend/internal/database/migrations/20260214_create_user_repos_table.sql
··· 1 1 -- Create table 'user_repos' to manage repositories for each user 2 - CREATE TABLE user_repos ( 2 + CREATE TABLE IF NOT EXISTS user_repos ( 3 3 id INTEGER PRIMARY KEY AUTOINCREMENT, 4 4 user_id INTEGER NOT NULL, 5 5 repo_name TEXT NOT NULL,
+11 -17
frontend/src/components/dashboard/DashboardApp.tsx
··· 42 42 repo: string; 43 43 folder: string; 44 44 } | null>(null); 45 + const [shouldRedirect, setShouldRedirect] = useState(false); 45 46 const [selectedFile, setSelectedFile] = useState<string | null>(null); 46 47 const { data: user, isLoading: userLoading } = useCurrentUser(); 47 48 const { data: userRepos, isLoading: reposLoading } = useUserRepos(); 48 49 49 50 // Check for repo from URL params, user.last_repo, or user_repos table 50 51 useEffect(() => { 51 - console.log('[DEBUG] Dashboard useEffect running'); 52 - console.log('[DEBUG] userLoading:', userLoading, 'reposLoading:', reposLoading); 53 - console.log('[DEBUG] user:', user?.last_repo, 'userRepos:', userRepos?.length); 54 - 55 52 if (userLoading || reposLoading || !user) { 56 - console.log('[DEBUG] Still loading, returning early'); 57 53 return; 58 54 } 59 55 60 56 // Check URL params first 61 57 const urlParams = new URLSearchParams(window.location.search); 62 58 const repoParam = urlParams.get('repo'); 63 - console.log('[DEBUG] URL repo param:', repoParam); 64 59 65 60 if (repoParam) { 66 61 const [owner, repo] = repoParam.split('/'); 67 62 if (owner && repo) { 68 - console.log('[DEBUG] Setting repo from URL param:', owner, repo); 69 63 setRepoConfig({ owner, repo, folder: '' }); 70 64 return; 71 65 } 72 66 } 73 67 74 68 // Check user's last_repo from users table 75 - console.log('[DEBUG] Checking user.last_repo:', user.last_repo); 76 69 if (user.last_repo) { 77 70 const [owner, repo] = user.last_repo.split('/'); 78 71 if (owner && repo) { 79 - console.log('[DEBUG] Setting repo from user.last_repo:', owner, repo); 80 72 setRepoConfig({ owner, repo, folder: '' }); 81 73 return; 82 74 } 83 75 } 84 76 85 77 // Check user_repos table (sorted by most recent) 86 - console.log('[DEBUG] Checking user_repos table, count:', userRepos?.length); 87 78 if (userRepos && userRepos.length > 0) { 88 - // Get the most recently used repo (first in the list from API) 89 79 const mostRecentRepo = userRepos[0]; 90 - console.log('[DEBUG] Most recent repo from user_repos:', mostRecentRepo.repo_name); 91 - 92 80 const [owner, repo] = mostRecentRepo.repo_name.split('/'); 93 81 if (owner && repo) { 94 - console.log('[DEBUG] Setting repo from user_repos table:', owner, repo); 95 82 setRepoConfig({ owner, repo, folder: '' }); 96 83 return; 97 84 } 98 85 } 99 86 100 - // No repo configured, redirect to select-repo page 101 - console.log('[DEBUG] No repo found, redirecting to /select-repo'); 102 - window.location.href = '/select-repo'; 87 + // No repo configured, mark for redirect to select-repo page 88 + setShouldRedirect(true); 103 89 }, [user, userLoading, userRepos, reposLoading]); 104 90 91 + // Perform redirect after state is set to avoid race conditions 92 + useEffect(() => { 93 + if (shouldRedirect) { 94 + window.location.href = '/select-repo'; 95 + } 96 + }, [shouldRedirect]); 97 + 98 + // Only fetch files once we have a valid repo config 105 99 const { data: filesData, isLoading: filesLoading } = useFiles( 106 100 repoConfig?.owner || '', 107 101 repoConfig?.repo || '',