From 69afef15ecf31a552204890ef96ca2a12191a075 Mon Sep 17 00:00:00 2001 From: LordMathis Date: Mon, 4 Nov 2024 21:51:38 +0100 Subject: [PATCH] Make logging in work on frontend --- backend/internal/api/routes.go | 4 +- backend/internal/db/users.go | 37 +++++++-- .../internal/handlers/workspace_handlers.go | 19 +++-- frontend/package-lock.json | 32 ++++++++ frontend/package.json | 1 + frontend/src/components/MarkdownPreview.jsx | 11 +-- frontend/src/components/WorkspaceSwitcher.jsx | 8 +- frontend/src/contexts/WorkspaceContext.jsx | 30 +++---- frontend/src/hooks/useFileContent.js | 2 +- frontend/src/hooks/useFileList.js | 2 +- frontend/src/hooks/useFileOperations.js | 6 +- frontend/src/hooks/useGitOperations.js | 4 +- frontend/src/hooks/useLastOpenedFile.js | 4 +- frontend/src/services/api.js | 80 ++++++++++--------- frontend/src/utils/remarkWikiLinks.js | 12 +-- frontend/vite.config.js | 11 ++- 16 files changed, 165 insertions(+), 98 deletions(-) diff --git a/backend/internal/api/routes.go b/backend/internal/api/routes.go index 37d0f51..ecc4c7a 100644 --- a/backend/internal/api/routes.go +++ b/backend/internal/api/routes.go @@ -45,8 +45,8 @@ func SetupRoutes(r chi.Router, db *db.DB, fs *filesystem.FileSystem, authMiddlew r.Route("/workspaces", func(r chi.Router) { r.Get("/", handler.ListWorkspaces()) r.Post("/", handler.CreateWorkspace()) - r.Get("/last", handler.GetLastWorkspace()) - r.Put("/last", handler.UpdateLastWorkspace()) + r.Get("/last", handler.GetLastWorkspaceName()) + r.Put("/last", handler.UpdateLastWorkspaceName()) // Single workspace routes r.Route("/{workspaceName}", func(r chi.Router) { diff --git a/backend/internal/db/users.go b/backend/internal/db/users.go index b2c3709..6f6edd5 100644 --- a/backend/internal/db/users.go +++ b/backend/internal/db/users.go @@ -120,9 +120,26 @@ func (db *DB) UpdateUser(user *models.User) error { return err } -func (db *DB) UpdateLastWorkspace(userID, workspaceID int) error { - _, err := db.Exec("UPDATE users SET last_workspace_id = ? WHERE id = ?", workspaceID, userID) - return err +func (db *DB) UpdateLastWorkspace(userID int, workspaceName string) error { + tx, err := db.Begin() + if err != nil { + return err + } + defer tx.Rollback() + + var workspaceID int + + err = tx.QueryRow("SELECT id FROM workspaces WHERE user_id = ? AND name = ?", userID, workspaceName).Scan(&workspaceID) + if err != nil { + return err + } + + _, err = tx.Exec("UPDATE users SET last_workspace_id = ? WHERE id = ?", workspaceID, userID) + if err != nil { + return err + } + + return tx.Commit() } func (db *DB) DeleteUser(id int) error { @@ -147,8 +164,14 @@ func (db *DB) DeleteUser(id int) error { return tx.Commit() } -func (db *DB) GetLastWorkspaceID(userID int) (int, error) { - var workspaceID int - err := db.QueryRow("SELECT last_workspace_id FROM users WHERE id = ?", userID).Scan(&workspaceID) - return workspaceID, err +func (db *DB) GetLastWorkspaceName(userID int) (string, error) { + var workspaceName string + err := db.QueryRow(` + SELECT + w.name + FROM workspaces w + JOIN users u ON u.last_workspace_id = w.id + WHERE u.id = ?`, userID). + Scan(&workspaceName) + return workspaceName, err } diff --git a/backend/internal/handlers/workspace_handlers.go b/backend/internal/handlers/workspace_handlers.go index c734575..bbb3c59 100644 --- a/backend/internal/handlers/workspace_handlers.go +++ b/backend/internal/handlers/workspace_handlers.go @@ -2,6 +2,7 @@ package handlers import ( "encoding/json" + "fmt" "net/http" "novamd/internal/httpcontext" @@ -151,10 +152,12 @@ func (h *Handler) DeleteWorkspace() http.HandlerFunc { } // Find another workspace to set as last + var nextWorkspaceName string var nextWorkspaceID int for _, ws := range workspaces { if ws.ID != ctx.Workspace.ID { nextWorkspaceID = ws.ID + nextWorkspaceName = ws.Name break } } @@ -188,28 +191,28 @@ func (h *Handler) DeleteWorkspace() http.HandlerFunc { } // Return the next workspace ID in the response so frontend knows where to redirect - respondJSON(w, map[string]int{"nextWorkspaceId": nextWorkspaceID}) + respondJSON(w, map[string]string{"nextWorkspaceName": nextWorkspaceName}) } } -func (h *Handler) GetLastWorkspace() http.HandlerFunc { +func (h *Handler) GetLastWorkspaceName() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ctx, ok := httpcontext.GetRequestContext(w, r) if !ok { return } - workspaceID, err := h.DB.GetLastWorkspaceID(ctx.UserID) + workspaceName, err := h.DB.GetLastWorkspaceName(ctx.UserID) if err != nil { http.Error(w, "Failed to get last workspace", http.StatusInternalServerError) return } - respondJSON(w, map[string]int{"lastWorkspaceId": workspaceID}) + respondJSON(w, map[string]string{"lastWorkspaceName": workspaceName}) } } -func (h *Handler) UpdateLastWorkspace() http.HandlerFunc { +func (h *Handler) UpdateLastWorkspaceName() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { ctx, ok := httpcontext.GetRequestContext(w, r) if !ok { @@ -217,15 +220,17 @@ func (h *Handler) UpdateLastWorkspace() http.HandlerFunc { } var requestBody struct { - WorkspaceID int `json:"workspaceId"` + WorkspaceName string `json:"workspaceName"` } if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil { + fmt.Println(err) http.Error(w, "Invalid request body", http.StatusBadRequest) return } - if err := h.DB.UpdateLastWorkspace(ctx.UserID, requestBody.WorkspaceID); err != nil { + if err := h.DB.UpdateLastWorkspace(ctx.UserID, requestBody.WorkspaceName); err != nil { + fmt.Println(err) http.Error(w, "Failed to update last workspace", http.StatusInternalServerError) return } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d42e69c..a16cf85 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -28,6 +28,7 @@ "rehype-mathjax": "^6.0.0", "rehype-prism": "^2.3.3", "rehype-react": "^8.0.0", + "remark": "^15.0.1", "remark-math": "^6.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", @@ -4975,6 +4976,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz", + "integrity": "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-math": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", @@ -5024,6 +5041,21 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 4c2b615..5f7b4d8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -42,6 +42,7 @@ "rehype-mathjax": "^6.0.0", "rehype-prism": "^2.3.3", "rehype-react": "^8.0.0", + "remark": "^15.0.1", "remark-math": "^6.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", diff --git a/frontend/src/components/MarkdownPreview.jsx b/frontend/src/components/MarkdownPreview.jsx index a86ae1e..90a8402 100644 --- a/frontend/src/components/MarkdownPreview.jsx +++ b/frontend/src/components/MarkdownPreview.jsx @@ -21,15 +21,10 @@ const MarkdownPreview = ({ content, handleFileSelect }) => { if (href.startsWith(`${baseUrl}/internal/`)) { // For existing files, extract the path and directly select it - const [filePath, heading] = decodeURIComponent( + const [filePath] = decodeURIComponent( href.replace(`${baseUrl}/internal/`, '') ).split('#'); handleFileSelect(filePath); - - // TODO: Handle heading navigation if needed - if (heading) { - console.debug('Heading navigation not implemented:', heading); - } } else if (href.startsWith(`${baseUrl}/notfound/`)) { // For non-existent files, show a notification const fileName = decodeURIComponent( @@ -47,7 +42,7 @@ const MarkdownPreview = ({ content, handleFileSelect }) => { () => unified() .use(remarkParse) - .use(remarkWikiLinks, currentWorkspace?.id) + .use(remarkWikiLinks, currentWorkspace?.name) .use(remarkMath) .use(remarkRehype) .use(rehypeMathjax) @@ -90,7 +85,7 @@ const MarkdownPreview = ({ content, handleFileSelect }) => { }, }, }), - [baseUrl, handleFileSelect, currentWorkspace?.id] + [baseUrl, handleFileSelect, currentWorkspace?.name] ); useEffect(() => { diff --git a/frontend/src/components/WorkspaceSwitcher.jsx b/frontend/src/components/WorkspaceSwitcher.jsx index e9b79a0..e29f24d 100644 --- a/frontend/src/components/WorkspaceSwitcher.jsx +++ b/frontend/src/components/WorkspaceSwitcher.jsx @@ -47,7 +47,7 @@ const WorkspaceSwitcher = () => { const handleWorkspaceCreated = async (newWorkspace) => { await loadWorkspaces(); - switchWorkspace(newWorkspace.id); + switchWorkspace(newWorkspace.name); }; return ( @@ -102,10 +102,10 @@ const WorkspaceSwitcher = () => { ) : ( workspaces.map((workspace) => { - const isSelected = workspace.id === currentWorkspace?.id; + const isSelected = workspace.name === currentWorkspace?.name; return ( { { - switchWorkspace(workspace.id); + switchWorkspace(workspace.name); setPopoverOpened(false); }} > diff --git a/frontend/src/contexts/WorkspaceContext.jsx b/frontend/src/contexts/WorkspaceContext.jsx index f7804e2..beddf4f 100644 --- a/frontend/src/contexts/WorkspaceContext.jsx +++ b/frontend/src/contexts/WorkspaceContext.jsx @@ -8,10 +8,10 @@ import React, { import { useMantineColorScheme } from '@mantine/core'; import { notifications } from '@mantine/notifications'; import { - fetchLastWorkspaceId, + fetchLastWorkspaceName, getWorkspace, updateWorkspace, - updateLastWorkspace, + updateLastWorkspaceName, deleteWorkspace, listWorkspaces, } from '../services/api'; @@ -41,9 +41,9 @@ export const WorkspaceProvider = ({ children }) => { } }, []); - const loadWorkspaceData = useCallback(async (workspaceId) => { + const loadWorkspaceData = useCallback(async (workspaceName) => { try { - const workspace = await getWorkspace(workspaceId); + const workspace = await getWorkspace(workspaceName); setCurrentWorkspace(workspace); setColorScheme(workspace.theme); } catch (error) { @@ -61,8 +61,8 @@ export const WorkspaceProvider = ({ children }) => { const allWorkspaces = await listWorkspaces(); if (allWorkspaces.length > 0) { const firstWorkspace = allWorkspaces[0]; - await updateLastWorkspace(firstWorkspace.id); - await loadWorkspaceData(firstWorkspace.id); + await updateLastWorkspaceName(firstWorkspace.name); + await loadWorkspaceData(firstWorkspace.name); } } catch (error) { console.error('Failed to load first available workspace:', error); @@ -77,9 +77,9 @@ export const WorkspaceProvider = ({ children }) => { useEffect(() => { const initializeWorkspace = async () => { try { - const { lastWorkspaceId } = await fetchLastWorkspaceId(); - if (lastWorkspaceId) { - await loadWorkspaceData(lastWorkspaceId); + const { lastWorkspaceName } = await fetchLastWorkspaceName(); + if (lastWorkspaceName) { + await loadWorkspaceData(lastWorkspaceName); } else { await loadFirstAvailableWorkspace(); } @@ -95,11 +95,11 @@ export const WorkspaceProvider = ({ children }) => { initializeWorkspace(); }, []); - const switchWorkspace = useCallback(async (workspaceId) => { + const switchWorkspace = useCallback(async (workspaceName) => { try { setLoading(true); - await updateLastWorkspace(workspaceId); - await loadWorkspaceData(workspaceId); + await updateLastWorkspaceName(workspaceName); + await loadWorkspaceData(workspaceName); await loadWorkspaces(); } catch (error) { console.error('Failed to switch workspace:', error); @@ -129,10 +129,10 @@ export const WorkspaceProvider = ({ children }) => { } // Delete workspace and get the next workspace ID - const response = await deleteWorkspace(currentWorkspace.id); + const response = await deleteWorkspace(currentWorkspace.name); // Load the new workspace data - await loadWorkspaceData(response.nextWorkspaceId); + await loadWorkspaceData(response.nextWorkspaceName); notifications.show({ title: 'Success', @@ -162,7 +162,7 @@ export const WorkspaceProvider = ({ children }) => { }; const response = await updateWorkspace( - currentWorkspace.id, + currentWorkspace.name, updatedWorkspace ); setCurrentWorkspace(response); diff --git a/frontend/src/hooks/useFileContent.js b/frontend/src/hooks/useFileContent.js index cb304d0..21b8776 100644 --- a/frontend/src/hooks/useFileContent.js +++ b/frontend/src/hooks/useFileContent.js @@ -19,7 +19,7 @@ export const useFileContent = (selectedFile) => { if (filePath === DEFAULT_FILE.path) { newContent = DEFAULT_FILE.content; } else if (!isImageFile(filePath)) { - newContent = await fetchFileContent(currentWorkspace.id, filePath); + newContent = await fetchFileContent(currentWorkspace.name, filePath); } else { newContent = ''; // Set empty content for image files } diff --git a/frontend/src/hooks/useFileList.js b/frontend/src/hooks/useFileList.js index ec8ea1f..4557f1f 100644 --- a/frontend/src/hooks/useFileList.js +++ b/frontend/src/hooks/useFileList.js @@ -10,7 +10,7 @@ export const useFileList = () => { if (!currentWorkspace || workspaceLoading) return; try { - const fileList = await fetchFileList(currentWorkspace.id); + const fileList = await fetchFileList(currentWorkspace.name); if (Array.isArray(fileList)) { setFiles(fileList); } else { diff --git a/frontend/src/hooks/useFileOperations.js b/frontend/src/hooks/useFileOperations.js index 0110755..6df5dae 100644 --- a/frontend/src/hooks/useFileOperations.js +++ b/frontend/src/hooks/useFileOperations.js @@ -29,7 +29,7 @@ export const useFileOperations = () => { if (!currentWorkspace) return false; try { - await saveFileContent(currentWorkspace.id, filePath, content); + await saveFileContent(currentWorkspace.name, filePath, content); notifications.show({ title: 'Success', message: 'File saved successfully', @@ -55,7 +55,7 @@ export const useFileOperations = () => { if (!currentWorkspace) return false; try { - await deleteFile(currentWorkspace.id, filePath); + await deleteFile(currentWorkspace.name, filePath); notifications.show({ title: 'Success', message: 'File deleted successfully', @@ -81,7 +81,7 @@ export const useFileOperations = () => { if (!currentWorkspace) return false; try { - await saveFileContent(currentWorkspace.id, fileName, initialContent); + await saveFileContent(currentWorkspace.name, fileName, initialContent); notifications.show({ title: 'Success', message: 'File created successfully', diff --git a/frontend/src/hooks/useGitOperations.js b/frontend/src/hooks/useGitOperations.js index 40e1669..9a3e5b3 100644 --- a/frontend/src/hooks/useGitOperations.js +++ b/frontend/src/hooks/useGitOperations.js @@ -10,7 +10,7 @@ export const useGitOperations = () => { if (!currentWorkspace || !settings.gitEnabled) return false; try { - await pullChanges(currentWorkspace.id); + await pullChanges(currentWorkspace.name); notifications.show({ title: 'Success', message: 'Successfully pulled latest changes', @@ -33,7 +33,7 @@ export const useGitOperations = () => { if (!currentWorkspace || !settings.gitEnabled) return false; try { - await commitAndPush(currentWorkspace.id, message); + await commitAndPush(currentWorkspace.name, message); notifications.show({ title: 'Success', message: 'Successfully committed and pushed changes', diff --git a/frontend/src/hooks/useLastOpenedFile.js b/frontend/src/hooks/useLastOpenedFile.js index 1844fd6..d1b8bef 100644 --- a/frontend/src/hooks/useLastOpenedFile.js +++ b/frontend/src/hooks/useLastOpenedFile.js @@ -9,7 +9,7 @@ export const useLastOpenedFile = () => { if (!currentWorkspace) return null; try { - const response = await getLastOpenedFile(currentWorkspace.id); + const response = await getLastOpenedFile(currentWorkspace.name); return response.lastOpenedFilePath || null; } catch (error) { console.error('Failed to load last opened file:', error); @@ -22,7 +22,7 @@ export const useLastOpenedFile = () => { if (!currentWorkspace) return; try { - await updateLastOpenedFile(currentWorkspace.id, filePath); + await updateLastOpenedFile(currentWorkspace.name, filePath); } catch (error) { console.error('Failed to save last opened file:', error); } diff --git a/frontend/src/services/api.js b/frontend/src/services/api.js index fdeeabb..ad7e84f 100644 --- a/frontend/src/services/api.js +++ b/frontend/src/services/api.js @@ -1,28 +1,28 @@ import { API_BASE_URL } from '../utils/constants'; import { apiCall } from './authApi'; -export const fetchLastWorkspaceId = async () => { +export const fetchLastWorkspaceName = async () => { const response = await apiCall(`${API_BASE_URL}/workspaces/last`); return response.json(); }; -export const fetchFileList = async (workspaceId) => { +export const fetchFileList = async (workspaceName) => { const response = await apiCall( - `${API_BASE_URL}/workspaces/${workspaceId}/files` + `${API_BASE_URL}/workspaces/${workspaceName}/files` ); return response.json(); }; -export const fetchFileContent = async (workspaceId, filePath) => { +export const fetchFileContent = async (workspaceName, filePath) => { const response = await apiCall( - `${API_BASE_URL}/workspaces/${workspaceId}/files/${filePath}` + `${API_BASE_URL}/workspaces/${workspaceName}/files/${filePath}` ); return response.text(); }; -export const saveFileContent = async (workspaceId, filePath, content) => { +export const saveFileContent = async (workspaceName, filePath, content) => { const response = await apiCall( - `${API_BASE_URL}/workspaces/${workspaceId}/files/${filePath}`, + `${API_BASE_URL}/workspaces/${workspaceName}/files/${filePath}`, { method: 'POST', headers: { @@ -34,9 +34,9 @@ export const saveFileContent = async (workspaceId, filePath, content) => { return response.text(); }; -export const deleteFile = async (workspaceId, filePath) => { +export const deleteFile = async (workspaceName, filePath) => { const response = await apiCall( - `${API_BASE_URL}/workspaces/${workspaceId}/files/${filePath}`, + `${API_BASE_URL}/workspaces/${workspaceName}/files/${filePath}`, { method: 'DELETE', } @@ -44,26 +44,29 @@ export const deleteFile = async (workspaceId, filePath) => { return response.text(); }; -export const getWorkspace = async (workspaceId) => { - const response = await apiCall(`${API_BASE_URL}/workspaces/${workspaceId}`); +export const getWorkspace = async (workspaceName) => { + const response = await apiCall(`${API_BASE_URL}/workspaces/${workspaceName}`); return response.json(); }; // Combined function to update workspace data including settings -export const updateWorkspace = async (workspaceId, workspaceData) => { - const response = await apiCall(`${API_BASE_URL}/workspaces/${workspaceId}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(workspaceData), - }); +export const updateWorkspace = async (workspaceName, workspaceData) => { + const response = await apiCall( + `${API_BASE_URL}/workspaces/${workspaceName}`, + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(workspaceData), + } + ); return response.json(); }; -export const pullChanges = async (workspaceId) => { +export const pullChanges = async (workspaceName) => { const response = await apiCall( - `${API_BASE_URL}/workspaces/${workspaceId}/git/pull`, + `${API_BASE_URL}/workspaces/${workspaceName}/git/pull`, { method: 'POST', } @@ -71,9 +74,9 @@ export const pullChanges = async (workspaceId) => { return response.json(); }; -export const commitAndPush = async (workspaceId, message) => { +export const commitAndPush = async (workspaceName, message) => { const response = await apiCall( - `${API_BASE_URL}/workspaces/${workspaceId}/git/commit`, + `${API_BASE_URL}/workspaces/${workspaceName}/git/commit`, { method: 'POST', headers: { @@ -85,13 +88,13 @@ export const commitAndPush = async (workspaceId, message) => { return response.json(); }; -export const getFileUrl = (workspaceId, filePath) => { - return `${API_BASE_URL}/workspaces/${workspaceId}/files/${filePath}`; +export const getFileUrl = (workspaceName, filePath) => { + return `${API_BASE_URL}/workspaces/${workspaceName}/files/${filePath}`; }; -export const lookupFileByName = async (workspaceId, filename) => { +export const lookupFileByName = async (workspaceName, filename) => { const response = await apiCall( - `${API_BASE_URL}/workspaces/${workspaceId}/files/lookup?filename=${encodeURIComponent( + `${API_BASE_URL}/workspaces/${workspaceName}/files/lookup?filename=${encodeURIComponent( filename )}` ); @@ -99,9 +102,9 @@ export const lookupFileByName = async (workspaceId, filename) => { return data.paths; }; -export const updateLastOpenedFile = async (workspaceId, filePath) => { +export const updateLastOpenedFile = async (workspaceName, filePath) => { const response = await apiCall( - `${API_BASE_URL}/workspaces/${workspaceId}/files/last`, + `${API_BASE_URL}/workspaces/${workspaceName}/files/last`, { method: 'PUT', headers: { @@ -113,9 +116,9 @@ export const updateLastOpenedFile = async (workspaceId, filePath) => { return response.json(); }; -export const getLastOpenedFile = async (workspaceId) => { +export const getLastOpenedFile = async (workspaceName) => { const response = await apiCall( - `${API_BASE_URL}/workspaces/${workspaceId}/files/last` + `${API_BASE_URL}/workspaces/${workspaceName}/files/last` ); return response.json(); }; @@ -136,20 +139,23 @@ export const createWorkspace = async (name) => { return response.json(); }; -export const deleteWorkspace = async (workspaceId) => { - const response = await apiCall(`${API_BASE_URL}/workspaces/${workspaceId}`, { - method: 'DELETE', - }); +export const deleteWorkspace = async (workspaceName) => { + const response = await apiCall( + `${API_BASE_URL}/workspaces/${workspaceName}`, + { + method: 'DELETE', + } + ); return response.json(); }; -export const updateLastWorkspace = async (workspaceId) => { +export const updateLastWorkspaceName = async (workspaceName) => { const response = await apiCall(`${API_BASE_URL}/workspaces/last`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ workspaceId }), + body: JSON.stringify({ workspaceName }), }); return response.json(); }; diff --git a/frontend/src/utils/remarkWikiLinks.js b/frontend/src/utils/remarkWikiLinks.js index d271d28..15d66aa 100644 --- a/frontend/src/utils/remarkWikiLinks.js +++ b/frontend/src/utils/remarkWikiLinks.js @@ -27,10 +27,10 @@ function createFileLink(filePath, displayText, heading, baseUrl) { }; } -function createImageNode(workspaceId, filePath, displayText) { +function createImageNode(workspaceName, filePath, displayText) { return { type: 'image', - url: getFileUrl(workspaceId, filePath), + url: getFileUrl(workspaceName, filePath), alt: displayText, title: displayText, }; @@ -43,9 +43,9 @@ function addMarkdownExtension(fileName) { return `${fileName}.md`; } -export function remarkWikiLinks(workspaceId) { +export function remarkWikiLinks(workspaceName) { return async function transformer(tree) { - if (!workspaceId) { + if (!workspaceName) { console.warn('No workspace ID provided to remarkWikiLinks plugin'); return; } @@ -113,13 +113,13 @@ export function remarkWikiLinks(workspaceId) { ? match.fileName : addMarkdownExtension(match.fileName); - const paths = await lookupFileByName(workspaceId, lookupFileName); + const paths = await lookupFileByName(workspaceName, lookupFileName); if (paths && paths.length > 0) { const filePath = paths[0]; if (match.isImage) { newNodes.push( - createImageNode(workspaceId, filePath, match.displayText) + createImageNode(workspaceName, filePath, match.displayText) ); } else { newNodes.push( diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 5ce297c..85e6a8d 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -52,11 +52,16 @@ export default defineConfig(({ mode }) => ({ // Markdown processing markdown: [ - 'react-markdown', 'react-syntax-highlighter', - 'rehype-katex', + 'rehype-mathjax', + 'rehype-prism', + 'rehype-react', + 'remark', 'remark-math', - 'katex', + 'remark-parse', + 'remark-rehype', + 'unified', + 'unist-util-visit', ], // Icons and utilities