feat: integrate @tailwindcss/typography and enhance folder picker functionality
- Added @tailwindcss/typography dependency to package.json and tailwind.config.js. - Updated FolderPicker.vue to include additional properties (isGitRepo, hasDocuments) for directories. - Enhanced Sidebar.vue with folder creation and document handling features, including drag-and-drop functionality. - Implemented createFolder and moveDocument mutations in gql.ts for managing folder and document operations. - Added logic to handle folder creation and document creation prompts in Sidebar.vue. - Updated the layout and interactions in Sidebar.vue to improve user experience.
This commit is contained in:
@@ -40,6 +40,26 @@ func (s *Store) Write(slug, content string) error {
|
||||
return os.WriteFile(path, []byte(content), 0644)
|
||||
}
|
||||
|
||||
// CreateFolder creates a new folder/directory.
|
||||
func (s *Store) CreateFolder(folderSlug string) error {
|
||||
path := s.folderPath(folderSlug)
|
||||
return os.MkdirAll(path, 0755)
|
||||
}
|
||||
|
||||
// MoveDocument moves a document from one location to another.
|
||||
func (s *Store) MoveDocument(fromSlug, toSlug string) error {
|
||||
fromPath := s.filePath(fromSlug)
|
||||
toPath := s.filePath(toSlug)
|
||||
|
||||
// Ensure target directory exists
|
||||
if err := os.MkdirAll(filepath.Dir(toPath), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Move the file
|
||||
return os.Rename(fromPath, toPath)
|
||||
}
|
||||
|
||||
// Delete removes a document from disk.
|
||||
func (s *Store) Delete(slug string) error {
|
||||
return os.Remove(s.filePath(slug))
|
||||
@@ -63,8 +83,91 @@ func (s *Store) List(prefix string) ([]string, error) {
|
||||
return slugs, err
|
||||
}
|
||||
|
||||
// ListImages returns all images in the directory of a given slug.
|
||||
func (s *Store) ListImages(slug string) ([]map[string]interface{}, error) {
|
||||
dir := filepath.Dir(s.filePath(slug))
|
||||
var images []map[string]interface{}
|
||||
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return images, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
name := entry.Name()
|
||||
ext := strings.ToLower(filepath.Ext(name))
|
||||
if ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif" || ext == ".svg" || ext == ".webp" {
|
||||
info, err := entry.Info()
|
||||
if err == nil {
|
||||
images = append(images, map[string]interface{}{
|
||||
"name": name,
|
||||
"size": info.Size(),
|
||||
// The URL is relative to the media endpoint mapped in the server.
|
||||
"url": "/media/" + strings.TrimPrefix(filepath.ToSlash(filepath.Join(filepath.Dir(slug), name)), "/"),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return images, nil
|
||||
}
|
||||
|
||||
// SaveImage saves an uploaded image file into the directory of a slug.
|
||||
func (s *Store) SaveImage(slug, filename string, data []byte) error {
|
||||
dir := filepath.Dir(s.filePath(slug))
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(filepath.Join(dir, filename), data, 0644)
|
||||
}
|
||||
|
||||
// DeleteImage removes an image file from the directory of a slug.
|
||||
func (s *Store) DeleteImage(slug, filename string) error {
|
||||
dir := filepath.Dir(s.filePath(slug))
|
||||
return os.Remove(filepath.Join(dir, filename))
|
||||
}
|
||||
|
||||
// GetImagePath returns the absolute path on disk for a media file.
|
||||
// It prevents directory traversal out of the root storage path.
|
||||
func (s *Store) GetImagePath(relPath string) (string, error) {
|
||||
if strings.Contains(relPath, "..") {
|
||||
return "", errors.New("invalid path")
|
||||
}
|
||||
return filepath.Join(s.root, filepath.FromSlash(relPath)), nil
|
||||
}
|
||||
|
||||
// ListFolders returns all folder paths relative to root, excluding .git.
|
||||
func (s *Store) ListFolders() ([]string, error) {
|
||||
var folders []string
|
||||
err := filepath.WalkDir(s.root, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() {
|
||||
if d.Name() == ".git" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if path != s.root {
|
||||
rel, _ := filepath.Rel(s.root, path)
|
||||
folders = append(folders, filepath.ToSlash(rel))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return folders, err
|
||||
}
|
||||
|
||||
func (s *Store) filePath(slug string) string {
|
||||
return filepath.Join(s.root, filepath.FromSlash(slug)+".adoc")
|
||||
}
|
||||
|
||||
func (s *Store) folderPath(folderSlug string) string {
|
||||
return filepath.Join(s.root, filepath.FromSlash(folderSlug))
|
||||
}
|
||||
|
||||
var ErrNotFound = errors.New("document not found")
|
||||
|
||||
Reference in New Issue
Block a user