From 6eb3eecb248f09cffa3072f2c3b3065c3d3a8449 Mon Sep 17 00:00:00 2001 From: LordMathis Date: Sat, 19 Oct 2024 13:48:37 +0200 Subject: [PATCH] Add Workspace context --- frontend/src/App.js | 12 +- frontend/src/components/Editor.js | 4 +- frontend/src/components/FileActions.js | 4 +- frontend/src/components/Layout.js | 20 +- frontend/src/components/MainContent.js | 4 +- frontend/src/components/Settings.js | 4 +- frontend/src/components/Sidebar.js | 4 +- .../components/settings/AppearanceSettings.js | 4 +- frontend/src/contexts/SettingsContext.js | 79 ------ frontend/src/contexts/WorkspaceContext.js | 92 +++++++ frontend/src/hooks/useFileContent.js | 49 ++-- frontend/src/hooks/useFileList.js | 8 +- frontend/src/hooks/useFileNavigation.js | 8 +- frontend/src/hooks/useFileOperations.js | 25 +- frontend/src/hooks/useGitOperations.js | 19 +- frontend/src/services/api.js | 230 +++++++++++++----- 16 files changed, 356 insertions(+), 210 deletions(-) delete mode 100644 frontend/src/contexts/SettingsContext.js create mode 100644 frontend/src/contexts/WorkspaceContext.js diff --git a/frontend/src/App.js b/frontend/src/App.js index 5b3a52b..2ba651a 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -3,19 +3,13 @@ import { MantineProvider, ColorSchemeScript } from '@mantine/core'; import { Notifications } from '@mantine/notifications'; import { ModalsProvider } from '@mantine/modals'; import Layout from './components/Layout'; -import { SettingsProvider, useSettings } from './contexts/SettingsContext'; +import { WorkspaceProvider } from './contexts/WorkspaceContext'; import { ModalProvider } from './contexts/ModalContext'; import '@mantine/core/styles.css'; import '@mantine/notifications/styles.css'; import './App.scss'; function AppContent() { - const { loading } = useSettings(); - - if (loading) { - return
Loading...
; - } - return ; } @@ -26,11 +20,11 @@ function App() { - + - + diff --git a/frontend/src/components/Editor.js b/frontend/src/components/Editor.js index 1491f8e..91dd89f 100644 --- a/frontend/src/components/Editor.js +++ b/frontend/src/components/Editor.js @@ -5,10 +5,10 @@ import { EditorView, keymap } from '@codemirror/view'; import { markdown } from '@codemirror/lang-markdown'; import { defaultKeymap } from '@codemirror/commands'; import { oneDark } from '@codemirror/theme-one-dark'; -import { useSettings } from '../contexts/SettingsContext'; +import { useWorkspace } from '../contexts/WorkspaceContext'; const Editor = ({ content, handleContentChange, handleSave, selectedFile }) => { - const { settings } = useSettings(); + const { settings } = useWorkspace(); const editorRef = useRef(); const viewRef = useRef(); diff --git a/frontend/src/components/FileActions.js b/frontend/src/components/FileActions.js index 5984a89..b387022 100644 --- a/frontend/src/components/FileActions.js +++ b/frontend/src/components/FileActions.js @@ -6,11 +6,11 @@ import { IconGitPullRequest, IconGitCommit, } from '@tabler/icons-react'; -import { useSettings } from '../contexts/SettingsContext'; import { useModalContext } from '../contexts/ModalContext'; +import { useWorkspace } from '../contexts/WorkspaceContext'; const FileActions = ({ handlePullChanges, selectedFile }) => { - const { settings } = useSettings(); + const { settings } = useWorkspace(); const { setNewFileModalVisible, setDeleteFileModalVisible, diff --git a/frontend/src/components/Layout.js b/frontend/src/components/Layout.js index 97df9e8..ef012f2 100644 --- a/frontend/src/components/Layout.js +++ b/frontend/src/components/Layout.js @@ -1,16 +1,30 @@ import React from 'react'; -import { AppShell, Container } from '@mantine/core'; +import { AppShell, Container, Loader, Center } from '@mantine/core'; import Header from './Header'; import Sidebar from './Sidebar'; import MainContent from './MainContent'; import { useFileNavigation } from '../hooks/useFileNavigation'; import { useFileList } from '../hooks/useFileList'; +import { useWorkspace } from '../contexts/WorkspaceContext'; const Layout = () => { + const { currentWorkspace, loading: workspaceLoading } = useWorkspace(); const { selectedFile, handleFileSelect, handleLinkClick } = useFileNavigation(); const { files, loadFileList } = useFileList(); + if (workspaceLoading) { + return ( +
+ +
+ ); + } + + if (!currentWorkspace) { + return
No workspace found. Please create a workspace.
; + } + return ( @@ -22,8 +36,8 @@ const Layout = () => { p={0} style={{ display: 'flex', - height: 'calc(100vh - 60px - 2rem)', // Subtracting header height and vertical padding - overflow: 'hidden', // Prevent scrolling in the container + height: 'calc(100vh - 60px - 2rem)', + overflow: 'hidden', }} > { const [activeTab, setActiveTab] = useState('source'); - const { settings } = useSettings(); + const { settings } = useWorkspace(); const { content, hasUnsavedChanges, diff --git a/frontend/src/components/Settings.js b/frontend/src/components/Settings.js index b0e10ce..7526254 100644 --- a/frontend/src/components/Settings.js +++ b/frontend/src/components/Settings.js @@ -1,7 +1,7 @@ import React, { useReducer, useEffect, useCallback, useRef } from 'react'; import { Modal, Badge, Button, Group, Title } from '@mantine/core'; import { notifications } from '@mantine/notifications'; -import { useSettings } from '../contexts/SettingsContext'; +import { useWorkspace } from '../contexts/WorkspaceContext'; import AppearanceSettings from './settings/AppearanceSettings'; import EditorSettings from './settings/EditorSettings'; import GitSettings from './settings/GitSettings'; @@ -50,7 +50,7 @@ function settingsReducer(state, action) { } const Settings = () => { - const { settings, updateSettings, colorScheme } = useSettings(); + const { settings, updateSettings, colorScheme } = useWorkspace(); const { settingsModalVisible, setSettingsModalVisible } = useModalContext(); const [state, dispatch] = useReducer(settingsReducer, initialState); const isInitialMount = useRef(true); diff --git a/frontend/src/components/Sidebar.js b/frontend/src/components/Sidebar.js index 79271f7..04619c7 100644 --- a/frontend/src/components/Sidebar.js +++ b/frontend/src/components/Sidebar.js @@ -3,10 +3,10 @@ import { Box } from '@mantine/core'; import FileActions from './FileActions'; import FileTree from './FileTree'; import { useGitOperations } from '../hooks/useGitOperations'; -import { useSettings } from '../contexts/SettingsContext'; +import { useWorkspace } from '../contexts/WorkspaceContext'; const Sidebar = ({ selectedFile, handleFileSelect, files, loadFileList }) => { - const { settings } = useSettings(); + const { settings } = useWorkspace(); const { handlePull } = useGitOperations(settings.gitEnabled); useEffect(() => { diff --git a/frontend/src/components/settings/AppearanceSettings.js b/frontend/src/components/settings/AppearanceSettings.js index f29f253..2073c4f 100644 --- a/frontend/src/components/settings/AppearanceSettings.js +++ b/frontend/src/components/settings/AppearanceSettings.js @@ -1,9 +1,9 @@ import React from 'react'; import { Text, Switch, Group, Box, Title } from '@mantine/core'; -import { useSettings } from '../../contexts/SettingsContext'; +import { useWorkspace } from '../../contexts/WorkspaceContext'; const AppearanceSettings = ({ onThemeChange }) => { - const { colorScheme, toggleColorScheme } = useSettings(); + const { colorScheme, toggleColorScheme } = useWorkspace(); const handleThemeChange = () => { toggleColorScheme(); diff --git a/frontend/src/contexts/SettingsContext.js b/frontend/src/contexts/SettingsContext.js deleted file mode 100644 index 0a8df8d..0000000 --- a/frontend/src/contexts/SettingsContext.js +++ /dev/null @@ -1,79 +0,0 @@ -import React, { - createContext, - useContext, - useEffect, - useMemo, - useCallback, - useState, -} from 'react'; -import { useMantineColorScheme } from '@mantine/core'; -import { fetchUserSettings, saveUserSettings } from '../services/api'; -import { DEFAULT_SETTINGS } from '../utils/constants'; - -const SettingsContext = createContext(); - -export const useSettings = () => useContext(SettingsContext); - -export const SettingsProvider = ({ children }) => { - const { colorScheme, setColorScheme } = useMantineColorScheme(); - const [settings, setSettings] = useState(DEFAULT_SETTINGS); - const [loading, setLoading] = useState(true); - - useEffect(() => { - const loadSettings = async () => { - try { - const userSettings = await fetchUserSettings(1); - setSettings(userSettings.settings); - setColorScheme(userSettings.settings.theme); - } catch (error) { - console.error('Failed to load user settings:', error); - } finally { - setLoading(false); - } - }; - - loadSettings(); - }, []); - - const updateSettings = useCallback( - async (newSettings) => { - try { - await saveUserSettings({ - userId: 1, - settings: newSettings, - }); - setSettings(newSettings); - if (newSettings.theme) { - setColorScheme(newSettings.theme); - } - } catch (error) { - console.error('Failed to save settings:', error); - throw error; - } - }, - [setColorScheme] - ); - - const toggleColorScheme = useCallback(() => { - const newTheme = colorScheme === 'dark' ? 'light' : 'dark'; - setColorScheme(newTheme); - updateSettings({ ...settings, theme: newTheme }); - }, [colorScheme, settings, setColorScheme, updateSettings]); - - const contextValue = useMemo( - () => ({ - settings, - updateSettings, - toggleColorScheme, - loading, - colorScheme, - }), - [settings, updateSettings, toggleColorScheme, loading, colorScheme] - ); - - return ( - - {children} - - ); -}; diff --git a/frontend/src/contexts/WorkspaceContext.js b/frontend/src/contexts/WorkspaceContext.js new file mode 100644 index 0000000..41b4e46 --- /dev/null +++ b/frontend/src/contexts/WorkspaceContext.js @@ -0,0 +1,92 @@ +import React, { + createContext, + useContext, + useState, + useEffect, + useCallback, +} from 'react'; +import { useMantineColorScheme } from '@mantine/core'; +import { + fetchLastWorkspace, + fetchWorkspaceSettings, + saveWorkspaceSettings, +} from '../services/api'; +import { DEFAULT_SETTINGS } from '../utils/constants'; + +const WorkspaceContext = createContext(); + +export const WorkspaceProvider = ({ children }) => { + const [currentWorkspace, setCurrentWorkspace] = useState(null); + const [settings, setSettings] = useState(DEFAULT_SETTINGS); + const [loading, setLoading] = useState(true); + const { colorScheme, setColorScheme } = useMantineColorScheme(); + + useEffect(() => { + const loadWorkspaceAndSettings = async () => { + try { + const workspace = await fetchLastWorkspace(); + setCurrentWorkspace(workspace); + + if (workspace) { + const workspaceSettings = await fetchWorkspaceSettings(workspace.id); + setSettings(workspaceSettings.settings); + setColorScheme(workspaceSettings.settings.theme); + } + } catch (error) { + console.error('Failed to load workspace or settings:', error); + } finally { + setLoading(false); + } + }; + + loadWorkspaceAndSettings(); + }, [setColorScheme]); + + const updateSettings = useCallback( + async (newSettings) => { + if (!currentWorkspace) return; + + try { + await saveWorkspaceSettings(currentWorkspace.id, newSettings); + setSettings(newSettings); + if (newSettings.theme) { + setColorScheme(newSettings.theme); + } + } catch (error) { + console.error('Failed to save settings:', error); + throw error; + } + }, + [currentWorkspace, setColorScheme] + ); + + const toggleColorScheme = useCallback(() => { + const newTheme = colorScheme === 'dark' ? 'light' : 'dark'; + setColorScheme(newTheme); + updateSettings({ ...settings, theme: newTheme }); + }, [colorScheme, settings, setColorScheme, updateSettings]); + + const value = { + currentWorkspace, + setCurrentWorkspace, + settings, + updateSettings, + toggleColorScheme, + loading, + colorScheme, + }; + + return ( + + {children} + + ); +}; + +export const useWorkspace = () => { + const context = useContext(WorkspaceContext); + if (context === undefined) { + throw new Error('useWorkspace must be used within a WorkspaceProvider'); + } + return context; +}; diff --git a/frontend/src/hooks/useFileContent.js b/frontend/src/hooks/useFileContent.js index ba12b22..cb304d0 100644 --- a/frontend/src/hooks/useFileContent.js +++ b/frontend/src/hooks/useFileContent.js @@ -2,38 +2,45 @@ import { useState, useCallback, useEffect } from 'react'; import { fetchFileContent } from '../services/api'; import { isImageFile } from '../utils/fileHelpers'; import { DEFAULT_FILE } from '../utils/constants'; +import { useWorkspace } from '../contexts/WorkspaceContext'; export const useFileContent = (selectedFile) => { + const { currentWorkspace } = useWorkspace(); const [content, setContent] = useState(DEFAULT_FILE.content); const [originalContent, setOriginalContent] = useState(DEFAULT_FILE.content); const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); - const loadFileContent = useCallback(async (filePath) => { - try { - let newContent; - if (filePath === DEFAULT_FILE.path) { - newContent = DEFAULT_FILE.content; - } else if (!isImageFile(filePath)) { - newContent = await fetchFileContent(filePath); - } else { - newContent = ''; // Set empty content for image files + const loadFileContent = useCallback( + async (filePath) => { + if (!currentWorkspace) return; + + try { + let newContent; + if (filePath === DEFAULT_FILE.path) { + newContent = DEFAULT_FILE.content; + } else if (!isImageFile(filePath)) { + newContent = await fetchFileContent(currentWorkspace.id, filePath); + } else { + newContent = ''; // Set empty content for image files + } + setContent(newContent); + setOriginalContent(newContent); + setHasUnsavedChanges(false); + } catch (err) { + console.error('Error loading file content:', err); + setContent(''); // Set empty content on error + setOriginalContent(''); + setHasUnsavedChanges(false); } - setContent(newContent); - setOriginalContent(newContent); - setHasUnsavedChanges(false); - } catch (err) { - console.error('Error loading file content:', err); - setContent(''); // Set empty content on error - setOriginalContent(''); - setHasUnsavedChanges(false); - } - }, []); + }, + [currentWorkspace] + ); useEffect(() => { - if (selectedFile) { + if (selectedFile && currentWorkspace) { loadFileContent(selectedFile); } - }, [selectedFile, loadFileContent]); + }, [selectedFile, currentWorkspace, loadFileContent]); const handleContentChange = useCallback( (newContent) => { diff --git a/frontend/src/hooks/useFileList.js b/frontend/src/hooks/useFileList.js index 2e8abed..36171a8 100644 --- a/frontend/src/hooks/useFileList.js +++ b/frontend/src/hooks/useFileList.js @@ -1,12 +1,16 @@ import { useState, useCallback } from 'react'; import { fetchFileList } from '../services/api'; +import { useWorkspace } from '../contexts/WorkspaceContext'; export const useFileList = () => { const [files, setFiles] = useState([]); + const { currentWorkspace } = useWorkspace(); const loadFileList = useCallback(async () => { + if (!currentWorkspace) return; + try { - const fileList = await fetchFileList(); + const fileList = await fetchFileList(currentWorkspace.id); if (Array.isArray(fileList)) { setFiles(fileList); } else { @@ -15,7 +19,7 @@ export const useFileList = () => { } catch (error) { console.error('Failed to load file list:', error); } - }, []); + }, [currentWorkspace]); return { files, loadFileList }; }; diff --git a/frontend/src/hooks/useFileNavigation.js b/frontend/src/hooks/useFileNavigation.js index 497f1e4..7c3623d 100644 --- a/frontend/src/hooks/useFileNavigation.js +++ b/frontend/src/hooks/useFileNavigation.js @@ -2,10 +2,12 @@ import { useState, useCallback } from 'react'; import { notifications } from '@mantine/notifications'; import { lookupFileByName } from '../services/api'; import { DEFAULT_FILE } from '../utils/constants'; +import { useWorkspace } from '../contexts/WorkspaceContext'; export const useFileNavigation = () => { const [selectedFile, setSelectedFile] = useState(DEFAULT_FILE.path); const [isNewFile, setIsNewFile] = useState(true); + const { currentWorkspace } = useWorkspace(); const handleFileSelect = useCallback((filePath) => { setSelectedFile(filePath); @@ -14,8 +16,10 @@ export const useFileNavigation = () => { const handleLinkClick = useCallback( async (filename) => { + if (!currentWorkspace) return; + try { - const filePaths = await lookupFileByName(filename); + const filePaths = await lookupFileByName(currentWorkspace.id, filename); if (filePaths.length >= 1) { handleFileSelect(filePaths[0]); } else { @@ -34,7 +38,7 @@ export const useFileNavigation = () => { }); } }, - [handleFileSelect] + [currentWorkspace, handleFileSelect] ); return { handleLinkClick, selectedFile, isNewFile, handleFileSelect }; diff --git a/frontend/src/hooks/useFileOperations.js b/frontend/src/hooks/useFileOperations.js index a76b5b4..4b7f70a 100644 --- a/frontend/src/hooks/useFileOperations.js +++ b/frontend/src/hooks/useFileOperations.js @@ -1,12 +1,12 @@ import { useCallback } from 'react'; import { notifications } from '@mantine/notifications'; import { saveFileContent, deleteFile } from '../services/api'; -import { useSettings } from '../contexts/SettingsContext'; +import { useWorkspace } from '../contexts/WorkspaceContext'; import { useGitOperations } from './useGitOperations'; export const useFileOperations = () => { - const { settings } = useSettings(); - const { handleCommitAndPush } = useGitOperations(settings.gitEnabled); + const { currentWorkspace, settings } = useWorkspace(); + const { handleCommitAndPush } = useGitOperations(); const autoCommit = useCallback( async (filePath, action) => { @@ -15,7 +15,6 @@ export const useFileOperations = () => { .replace('${filename}', filePath) .replace('${action}', action); - // Capitalize the first letter of the commit message commitMessage = commitMessage.charAt(0).toUpperCase() + commitMessage.slice(1); @@ -27,8 +26,10 @@ export const useFileOperations = () => { const handleSave = useCallback( async (filePath, content) => { + if (!currentWorkspace) return false; + try { - await saveFileContent(filePath, content); + await saveFileContent(currentWorkspace.id, filePath, content); notifications.show({ title: 'Success', message: 'File saved successfully', @@ -46,13 +47,15 @@ export const useFileOperations = () => { return false; } }, - [autoCommit] + [currentWorkspace, autoCommit] ); const handleDelete = useCallback( async (filePath) => { + if (!currentWorkspace) return false; + try { - await deleteFile(filePath); + await deleteFile(currentWorkspace.id, filePath); notifications.show({ title: 'Success', message: 'File deleted successfully', @@ -70,13 +73,15 @@ export const useFileOperations = () => { return false; } }, - [autoCommit] + [currentWorkspace, autoCommit] ); const handleCreate = useCallback( async (fileName, initialContent = '') => { + if (!currentWorkspace) return false; + try { - await saveFileContent(fileName, initialContent); + await saveFileContent(currentWorkspace.id, fileName, initialContent); notifications.show({ title: 'Success', message: 'File created successfully', @@ -94,7 +99,7 @@ export const useFileOperations = () => { return false; } }, - [autoCommit] + [currentWorkspace, autoCommit] ); return { handleSave, handleDelete, handleCreate }; diff --git a/frontend/src/hooks/useGitOperations.js b/frontend/src/hooks/useGitOperations.js index 63f2424..40e1669 100644 --- a/frontend/src/hooks/useGitOperations.js +++ b/frontend/src/hooks/useGitOperations.js @@ -1,12 +1,16 @@ import { useCallback } from 'react'; import { notifications } from '@mantine/notifications'; import { pullChanges, commitAndPush } from '../services/api'; +import { useWorkspace } from '../contexts/WorkspaceContext'; + +export const useGitOperations = () => { + const { currentWorkspace, settings } = useWorkspace(); -export const useGitOperations = (gitEnabled) => { const handlePull = useCallback(async () => { - if (!gitEnabled) return false; + if (!currentWorkspace || !settings.gitEnabled) return false; + try { - await pullChanges(); + await pullChanges(currentWorkspace.id); notifications.show({ title: 'Success', message: 'Successfully pulled latest changes', @@ -22,13 +26,14 @@ export const useGitOperations = (gitEnabled) => { }); return false; } - }, [gitEnabled]); + }, [currentWorkspace, settings.gitEnabled]); const handleCommitAndPush = useCallback( async (message) => { - if (!gitEnabled) return false; + if (!currentWorkspace || !settings.gitEnabled) return false; + try { - await commitAndPush(message); + await commitAndPush(currentWorkspace.id, message); notifications.show({ title: 'Success', message: 'Successfully committed and pushed changes', @@ -45,7 +50,7 @@ export const useGitOperations = (gitEnabled) => { return false; } }, - [gitEnabled] + [currentWorkspace, settings.gitEnabled] ); return { handlePull, handleCommitAndPush }; diff --git a/frontend/src/services/api.js b/frontend/src/services/api.js index 8b57ad5..66c1cad 100644 --- a/frontend/src/services/api.js +++ b/frontend/src/services/api.js @@ -16,76 +16,176 @@ const apiCall = async (url, options = {}) => { } }; -export const fetchFileList = async () => { - const response = await apiCall(`${API_BASE_URL}/files`); +export const fetchLastWorkspace = async () => { + const response = await apiCall(`${API_BASE_URL}/users/1/workspaces/last`); return response.json(); }; -export const fetchFileContent = async (filePath) => { - const response = await apiCall(`${API_BASE_URL}/files/${filePath}`); - return response.text(); -}; - -export const saveFileContent = async (filePath, content) => { - const response = await apiCall(`${API_BASE_URL}/files/${filePath}`, { - method: 'POST', - headers: { - 'Content-Type': 'text/plain', - }, - body: content, - }); - return response.text(); -}; - -export const deleteFile = async (filePath) => { - const response = await apiCall(`${API_BASE_URL}/files/${filePath}`, { - method: 'DELETE', - }); - return response.text(); -}; - -export const fetchUserSettings = async (userId) => { - const response = await apiCall(`${API_BASE_URL}/settings?userId=${userId}`); - return response.json(); -}; - -export const saveUserSettings = async (settings) => { - const response = await apiCall(`${API_BASE_URL}/settings`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(settings), - }); - return response.json(); -}; - -export const pullChanges = async () => { - const response = await apiCall(`${API_BASE_URL}/git/pull`, { - method: 'POST', - }); - return response.json(); -}; - -export const commitAndPush = async (message) => { - const response = await apiCall(`${API_BASE_URL}/git/commit`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ message }), - }); - return response.json(); -}; - -export const getFileUrl = (filePath) => { - return `${API_BASE_URL}/files/${filePath}`; -}; - -export const lookupFileByName = async (filename) => { +export const fetchFileList = async (workspaceId) => { const response = await apiCall( - `${API_BASE_URL}/files/lookup?filename=${encodeURIComponent(filename)}` + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/files` + ); + return response.json(); +}; + +export const fetchFileContent = async (workspaceId, filePath) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/files/${filePath}` + ); + return response.text(); +}; + +export const saveFileContent = async (workspaceId, filePath, content) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/files/${filePath}`, + { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + body: content, + } + ); + return response.text(); +}; + +export const deleteFile = async (workspaceId, filePath) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/files/${filePath}`, + { + method: 'DELETE', + } + ); + return response.text(); +}; + +export const fetchWorkspaceSettings = async (workspaceId) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/settings` + ); + return response.json(); +}; + +export const saveWorkspaceSettings = async (workspaceId, settings) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/settings`, + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ settings }), + } + ); + return response.json(); +}; + +export const pullChanges = async (workspaceId) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/git/pull`, + { + method: 'POST', + } + ); + return response.json(); +}; + +export const commitAndPush = async (workspaceId, message) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/git/commit`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ message }), + } + ); + return response.json(); +}; + +export const getFileUrl = (workspaceId, filePath) => { + return `${API_BASE_URL}/users/1/workspaces/${workspaceId}/files/${filePath}`; +}; + +export const lookupFileByName = async (workspaceId, filename) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/files/lookup?filename=${encodeURIComponent( + filename + )}` ); const data = await response.json(); return data.paths; }; + +export const updateLastOpenedFile = async (workspaceId, filePath) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/files/last`, + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ filePath }), + } + ); + return response.json(); +}; + +export const getLastOpenedFile = async (workspaceId) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}/files/last` + ); + return response.json(); +}; + +export const listWorkspaces = async () => { + const response = await apiCall(`${API_BASE_URL}/users/1/workspaces`); + return response.json(); +}; + +export const createWorkspace = async (name) => { + const response = await apiCall(`${API_BASE_URL}/users/1/workspaces`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name }), + }); + return response.json(); +}; + +export const updateWorkspace = async (workspaceId, name) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}`, + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name }), + } + ); + return response.json(); +}; + +export const deleteWorkspace = async (workspaceId) => { + const response = await apiCall( + `${API_BASE_URL}/users/1/workspaces/${workspaceId}`, + { + method: 'DELETE', + } + ); + return response.json(); +}; + +export const updateLastWorkspace = async (workspaceId) => { + const response = await apiCall(`${API_BASE_URL}/users/1/workspaces/last`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ workspaceId }), + }); + return response.json(); +};