mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-05 15:44:21 +00:00
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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 {
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"novamd/internal/gitutils"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package user
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"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) {
|
||||
// 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
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -20,7 +20,7 @@ export const useFileList = () => {
|
||||
console.error('Failed to load file list:', error);
|
||||
setFiles([]);
|
||||
}
|
||||
}, [currentWorkspace]);
|
||||
}, [currentWorkspace, workspaceLoading]);
|
||||
|
||||
return { files, loadFileList };
|
||||
};
|
||||
|
||||
@@ -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';
|
||||
@@ -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(
|
||||
@@ -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 };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user