Merge pull request #8 from LordMathis/fix/file-list

Fix/file list
This commit is contained in:
2024-10-29 22:18:28 +01:00
committed by GitHub
7 changed files with 70 additions and 35 deletions

View File

@@ -39,7 +39,13 @@ func main() {
// Initialize user service // Initialize user service
userService := user.NewUserService(database, fs) userService := user.NewUserService(database, fs)
if _, err := userService.SetupAdminUser(); err != nil {
adminEmail := os.Getenv("NOVAMD_ADMIN_EMAIL")
adminPassword := os.Getenv("NOVAMD_ADMIN_PASSWORD")
if adminEmail == "" || adminPassword == "" {
log.Fatal("NOVAMD_ADMIN_EMAIL and NOVAMD_ADMIN_PASSWORD environment variables must be set")
}
if _, err := userService.SetupAdminUser(adminEmail, adminPassword); err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@@ -16,7 +16,7 @@ func SetupRoutes(r chi.Router, db *db.DB, fs *filesystem.FileSystem) {
// Workspace routes // Workspace routes
r.Route("/workspaces", func(r chi.Router) { r.Route("/workspaces", func(r chi.Router) {
r.Get("/", ListWorkspaces(db)) r.Get("/", ListWorkspaces(db))
r.Post("/", CreateWorkspace(db)) r.Post("/", CreateWorkspace(db, fs))
r.Get("/last", GetLastWorkspace(db)) r.Get("/last", GetLastWorkspace(db))
r.Put("/last", UpdateLastWorkspace(db)) r.Put("/last", UpdateLastWorkspace(db))

View File

@@ -27,7 +27,7 @@ func ListWorkspaces(db *db.DB) http.HandlerFunc {
} }
} }
func CreateWorkspace(db *db.DB) http.HandlerFunc { func CreateWorkspace(db *db.DB, fs *filesystem.FileSystem) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
userID, err := getUserID(r) userID, err := getUserID(r)
if err != nil { if err != nil {
@@ -47,6 +47,11 @@ func CreateWorkspace(db *db.DB) http.HandlerFunc {
return return
} }
if err := fs.InitializeUserWorkspace(workspace.UserID, workspace.ID); err != nil {
http.Error(w, "Failed to initialize workspace directory", http.StatusInternalServerError)
return
}
respondJSON(w, workspace) respondJSON(w, workspace)
} }
} }

View File

@@ -6,6 +6,7 @@ import (
"novamd/internal/gitutils" "novamd/internal/gitutils"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
) )
@@ -38,13 +39,6 @@ func (fs *FileSystem) InitializeUserWorkspace(userID, workspaceID int) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to create workspace directory: %w", err) return fmt.Errorf("failed to create workspace directory: %w", err)
} }
// Optionally, create a welcome file in the new workspace
// welcomeFilePath := filepath.Join(workspacePath, "Welcome.md")
// welcomeContent := []byte("# Welcome to Your Main Workspace\n\nThis is your default workspace in NovaMD. You can start creating and editing files right away!")
// err = os.WriteFile(welcomeFilePath, welcomeContent, 0644)
// if err != nil {
// return fmt.Errorf("failed to create welcome file: %w", err)
// }
return nil return nil
} }
@@ -82,26 +76,57 @@ func (fs *FileSystem) walkDirectory(dir, prefix string) ([]FileNode, error) {
return nil, err return nil, err
} }
nodes := make([]FileNode, 0) // Split entries into directories and files
var dirs, files []os.DirEntry
for _, entry := range entries { for _, entry := range entries {
if entry.IsDir() {
dirs = append(dirs, entry)
} else {
files = append(files, entry)
}
}
// Sort directories and files separately
sort.Slice(dirs, func(i, j int) bool {
return strings.ToLower(dirs[i].Name()) < strings.ToLower(dirs[j].Name())
})
sort.Slice(files, func(i, j int) bool {
return strings.ToLower(files[i].Name()) < strings.ToLower(files[j].Name())
})
// Create combined slice with directories first, then files
nodes := make([]FileNode, 0, len(entries))
// Add directories first
for _, entry := range dirs {
name := entry.Name() name := entry.Name()
path := filepath.Join(prefix, name) path := filepath.Join(prefix, name)
fullPath := filepath.Join(dir, name) fullPath := filepath.Join(dir, name)
children, err := fs.walkDirectory(fullPath, path)
if err != nil {
return nil, err
}
node := FileNode{
ID: path,
Name: name,
Path: path,
Children: children,
}
nodes = append(nodes, node)
}
// Then add files
for _, entry := range files {
name := entry.Name()
path := filepath.Join(prefix, name)
node := FileNode{ node := FileNode{
ID: path, ID: path,
Name: name, Name: name,
Path: path, Path: path,
} }
if entry.IsDir() {
children, err := fs.walkDirectory(fullPath, path)
if err != nil {
return nil, err
}
node.Children = children
}
nodes = append(nodes, node) nodes = append(nodes, node)
} }

View File

@@ -3,7 +3,6 @@ package user
import ( import (
"fmt" "fmt"
"log" "log"
"os"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@@ -24,18 +23,13 @@ func NewUserService(database *db.DB, fs *filesystem.FileSystem) *UserService {
} }
} }
func (s *UserService) SetupAdminUser() (*models.User, error) { func (s *UserService) SetupAdminUser(adminEmail, adminPassword string) (*models.User, error) {
// Get admin email and password from environment variables
adminEmail := os.Getenv("NOVAMD_ADMIN_EMAIL")
adminPassword := os.Getenv("NOVAMD_ADMIN_PASSWORD")
if adminEmail == "" || adminPassword == "" {
return nil, fmt.Errorf("NOVAMD_ADMIN_EMAIL and NOVAMD_ADMIN_PASSWORD environment variables must be set")
}
// Check if admin user exists // Check if admin user exists
adminUser, err := s.DB.GetUserByEmail(adminEmail) adminUser, err := s.DB.GetUserByEmail(adminEmail)
if adminUser != nil { if adminUser != nil {
return adminUser, nil // Admin user already exists return adminUser, nil // Admin user already exists
} else if err != nil {
return nil, err
} }
// Hash the password // Hash the password

View File

@@ -1,4 +1,4 @@
import { useState, useCallback, useEffect } from 'react'; import { useState, useCallback } from 'react';
import { fetchFileList } from '../services/api'; import { fetchFileList } from '../services/api';
import { useWorkspace } from '../contexts/WorkspaceContext'; import { useWorkspace } from '../contexts/WorkspaceContext';
@@ -20,7 +20,7 @@ export const useFileList = () => {
console.error('Failed to load file list:', error); console.error('Failed to load file list:', error);
setFiles([]); setFiles([]);
} }
}, [currentWorkspace]); }, [currentWorkspace, workspaceLoading]);
return { files, loadFileList }; return { files, loadFileList };
}; };

View File

@@ -1,4 +1,4 @@
import { useState, useCallback } from 'react'; import { useState, useCallback, useEffect } from 'react'; // Added useEffect
import { notifications } from '@mantine/notifications'; import { notifications } from '@mantine/notifications';
import { lookupFileByName } from '../services/api'; import { lookupFileByName } from '../services/api';
import { DEFAULT_FILE } from '../utils/constants'; import { DEFAULT_FILE } from '../utils/constants';
@@ -10,8 +10,8 @@ export const useFileNavigation = () => {
const { currentWorkspace } = useWorkspace(); const { currentWorkspace } = useWorkspace();
const handleFileSelect = useCallback((filePath) => { const handleFileSelect = useCallback((filePath) => {
setSelectedFile(filePath); setSelectedFile(filePath || DEFAULT_FILE.path);
setIsNewFile(filePath === DEFAULT_FILE.path); setIsNewFile(filePath ? false : true);
}, []); }, []);
const handleLinkClick = useCallback( const handleLinkClick = useCallback(
@@ -38,8 +38,13 @@ export const useFileNavigation = () => {
}); });
} }
}, },
[currentWorkspace] [currentWorkspace, handleFileSelect]
); );
// Reset to default file when workspace changes
useEffect(() => {
handleFileSelect(null);
}, [currentWorkspace, handleFileSelect]);
return { handleLinkClick, selectedFile, isNewFile, handleFileSelect }; return { handleLinkClick, selectedFile, isNewFile, handleFileSelect };
}; };