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