+
Skip to content

Fix/file list #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion backend/cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ func main() {

// Initialize user service
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)
}

Expand Down
2 changes: 1 addition & 1 deletion backend/internal/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func SetupRoutes(r chi.Router, db *db.DB, fs *filesystem.FileSystem) {
// Workspace routes
r.Route("/workspaces", func(r chi.Router) {
r.Get("/", ListWorkspaces(db))
r.Post("/", CreateWorkspace(db))
r.Post("/", CreateWorkspace(db, fs))
r.Get("/last", GetLastWorkspace(db))
r.Put("/last", UpdateLastWorkspace(db))

Expand Down
7 changes: 6 additions & 1 deletion backend/internal/api/workspace_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
userID, err := getUserID(r)
if err != nil {
Expand All @@ -47,6 +47,11 @@ func CreateWorkspace(db *db.DB) http.HandlerFunc {
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)
}
}
Expand Down
59 changes: 42 additions & 17 deletions backend/internal/filesystem/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"novamd/internal/gitutils"
"os"
"path/filepath"
"sort"
"strings"
)

Expand Down Expand Up @@ -38,13 +39,6 @@ func (fs *FileSystem) InitializeUserWorkspace(userID, workspaceID int) error {
if err != nil {
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
}
Expand Down Expand Up @@ -82,26 +76,57 @@ func (fs *FileSystem) walkDirectory(dir, prefix string) ([]FileNode, error) {
return nil, err
}

nodes := make([]FileNode, 0)
// Split entries into directories and files
var dirs, files []os.DirEntry
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()
path := filepath.Join(prefix, 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{
ID: path,
Name: name,
Path: path,
}

if entry.IsDir() {
children, err := fs.walkDirectory(fullPath, path)
if err != nil {
return nil, err
}
node.Children = children
}

nodes = append(nodes, node)
}

Expand Down
12 changes: 3 additions & 9 deletions backend/internal/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package user
import (
"fmt"
"log"
"os"

"golang.org/x/crypto/bcrypt"

Expand All @@ -24,18 +23,13 @@ func NewUserService(database *db.DB, fs *filesystem.FileSystem) *UserService {
}
}

func (s *UserService) SetupAdminUser() (*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")
}

func (s *UserService) SetupAdminUser(adminEmail, adminPassword string) (*models.User, error) {
// Check if admin user exists
adminUser, err := s.DB.GetUserByEmail(adminEmail)
if adminUser != nil {
return adminUser, nil // Admin user already exists
} else if err != nil {
return nil, err
}

// Hash the password
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/hooks/useFileList.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useCallback, useEffect } from 'react';
import { useState, useCallback } from 'react';
import { fetchFileList } from '../services/api';
import { useWorkspace } from '../contexts/WorkspaceContext';

Expand All @@ -20,7 +20,7 @@ export const useFileList = () => {
console.error('Failed to load file list:', error);
setFiles([]);
}
}, [currentWorkspace]);
}, [currentWorkspace, workspaceLoading]);

return { files, loadFileList };
};
13 changes: 9 additions & 4 deletions frontend/src/hooks/useFileNavigation.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useCallback } from 'react';
import { useState, useCallback, useEffect } from 'react'; // Added useEffect
import { notifications } from '@mantine/notifications';
import { lookupFileByName } from '../services/api';
import { DEFAULT_FILE } from '../utils/constants';
Expand All @@ -10,8 +10,8 @@ export const useFileNavigation = () => {
const { currentWorkspace } = useWorkspace();

const handleFileSelect = useCallback((filePath) => {
setSelectedFile(filePath);
setIsNewFile(filePath === DEFAULT_FILE.path);
setSelectedFile(filePath || DEFAULT_FILE.path);
setIsNewFile(filePath ? false : true);
}, []);

const handleLinkClick = useCallback(
Expand All @@ -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 };
};
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载