Add Workspace context

This commit is contained in:
2024-10-19 13:48:37 +02:00
parent 3b7bf83073
commit 6eb3eecb24
16 changed files with 356 additions and 210 deletions

View File

@@ -3,19 +3,13 @@ import { MantineProvider, ColorSchemeScript } from '@mantine/core';
import { Notifications } from '@mantine/notifications'; import { Notifications } from '@mantine/notifications';
import { ModalsProvider } from '@mantine/modals'; import { ModalsProvider } from '@mantine/modals';
import Layout from './components/Layout'; import Layout from './components/Layout';
import { SettingsProvider, useSettings } from './contexts/SettingsContext'; import { WorkspaceProvider } from './contexts/WorkspaceContext';
import { ModalProvider } from './contexts/ModalContext'; import { ModalProvider } from './contexts/ModalContext';
import '@mantine/core/styles.css'; import '@mantine/core/styles.css';
import '@mantine/notifications/styles.css'; import '@mantine/notifications/styles.css';
import './App.scss'; import './App.scss';
function AppContent() { function AppContent() {
const { loading } = useSettings();
if (loading) {
return <div>Loading...</div>;
}
return <Layout />; return <Layout />;
} }
@@ -26,11 +20,11 @@ function App() {
<MantineProvider defaultColorScheme="light"> <MantineProvider defaultColorScheme="light">
<Notifications /> <Notifications />
<ModalsProvider> <ModalsProvider>
<SettingsProvider> <WorkspaceProvider>
<ModalProvider> <ModalProvider>
<AppContent /> <AppContent />
</ModalProvider> </ModalProvider>
</SettingsProvider> </WorkspaceProvider>
</ModalsProvider> </ModalsProvider>
</MantineProvider> </MantineProvider>
</> </>

View File

@@ -5,10 +5,10 @@ import { EditorView, keymap } from '@codemirror/view';
import { markdown } from '@codemirror/lang-markdown'; import { markdown } from '@codemirror/lang-markdown';
import { defaultKeymap } from '@codemirror/commands'; import { defaultKeymap } from '@codemirror/commands';
import { oneDark } from '@codemirror/theme-one-dark'; import { oneDark } from '@codemirror/theme-one-dark';
import { useSettings } from '../contexts/SettingsContext'; import { useWorkspace } from '../contexts/WorkspaceContext';
const Editor = ({ content, handleContentChange, handleSave, selectedFile }) => { const Editor = ({ content, handleContentChange, handleSave, selectedFile }) => {
const { settings } = useSettings(); const { settings } = useWorkspace();
const editorRef = useRef(); const editorRef = useRef();
const viewRef = useRef(); const viewRef = useRef();

View File

@@ -6,11 +6,11 @@ import {
IconGitPullRequest, IconGitPullRequest,
IconGitCommit, IconGitCommit,
} from '@tabler/icons-react'; } from '@tabler/icons-react';
import { useSettings } from '../contexts/SettingsContext';
import { useModalContext } from '../contexts/ModalContext'; import { useModalContext } from '../contexts/ModalContext';
import { useWorkspace } from '../contexts/WorkspaceContext';
const FileActions = ({ handlePullChanges, selectedFile }) => { const FileActions = ({ handlePullChanges, selectedFile }) => {
const { settings } = useSettings(); const { settings } = useWorkspace();
const { const {
setNewFileModalVisible, setNewFileModalVisible,
setDeleteFileModalVisible, setDeleteFileModalVisible,

View File

@@ -1,16 +1,30 @@
import React from 'react'; import React from 'react';
import { AppShell, Container } from '@mantine/core'; import { AppShell, Container, Loader, Center } from '@mantine/core';
import Header from './Header'; import Header from './Header';
import Sidebar from './Sidebar'; import Sidebar from './Sidebar';
import MainContent from './MainContent'; import MainContent from './MainContent';
import { useFileNavigation } from '../hooks/useFileNavigation'; import { useFileNavigation } from '../hooks/useFileNavigation';
import { useFileList } from '../hooks/useFileList'; import { useFileList } from '../hooks/useFileList';
import { useWorkspace } from '../contexts/WorkspaceContext';
const Layout = () => { const Layout = () => {
const { currentWorkspace, loading: workspaceLoading } = useWorkspace();
const { selectedFile, handleFileSelect, handleLinkClick } = const { selectedFile, handleFileSelect, handleLinkClick } =
useFileNavigation(); useFileNavigation();
const { files, loadFileList } = useFileList(); const { files, loadFileList } = useFileList();
if (workspaceLoading) {
return (
<Center style={{ height: '100vh' }}>
<Loader size="xl" />
</Center>
);
}
if (!currentWorkspace) {
return <div>No workspace found. Please create a workspace.</div>;
}
return ( return (
<AppShell header={{ height: 60 }} padding="md"> <AppShell header={{ height: 60 }} padding="md">
<AppShell.Header> <AppShell.Header>
@@ -22,8 +36,8 @@ const Layout = () => {
p={0} p={0}
style={{ style={{
display: 'flex', display: 'flex',
height: 'calc(100vh - 60px - 2rem)', // Subtracting header height and vertical padding height: 'calc(100vh - 60px - 2rem)',
overflow: 'hidden', // Prevent scrolling in the container overflow: 'hidden',
}} }}
> >
<Sidebar <Sidebar

View File

@@ -10,7 +10,7 @@ import CommitMessageModal from './modals/CommitMessageModal';
import { useFileContent } from '../hooks/useFileContent'; import { useFileContent } from '../hooks/useFileContent';
import { useFileOperations } from '../hooks/useFileOperations'; import { useFileOperations } from '../hooks/useFileOperations';
import { useGitOperations } from '../hooks/useGitOperations'; import { useGitOperations } from '../hooks/useGitOperations';
import { useSettings } from '../contexts/SettingsContext'; import { useWorkspace } from '../contexts/WorkspaceContext';
const MainContent = ({ const MainContent = ({
selectedFile, selectedFile,
@@ -19,7 +19,7 @@ const MainContent = ({
loadFileList, loadFileList,
}) => { }) => {
const [activeTab, setActiveTab] = useState('source'); const [activeTab, setActiveTab] = useState('source');
const { settings } = useSettings(); const { settings } = useWorkspace();
const { const {
content, content,
hasUnsavedChanges, hasUnsavedChanges,

View File

@@ -1,7 +1,7 @@
import React, { useReducer, useEffect, useCallback, useRef } from 'react'; import React, { useReducer, useEffect, useCallback, useRef } from 'react';
import { Modal, Badge, Button, Group, Title } from '@mantine/core'; import { Modal, Badge, Button, Group, Title } from '@mantine/core';
import { notifications } from '@mantine/notifications'; import { notifications } from '@mantine/notifications';
import { useSettings } from '../contexts/SettingsContext'; import { useWorkspace } from '../contexts/WorkspaceContext';
import AppearanceSettings from './settings/AppearanceSettings'; import AppearanceSettings from './settings/AppearanceSettings';
import EditorSettings from './settings/EditorSettings'; import EditorSettings from './settings/EditorSettings';
import GitSettings from './settings/GitSettings'; import GitSettings from './settings/GitSettings';
@@ -50,7 +50,7 @@ function settingsReducer(state, action) {
} }
const Settings = () => { const Settings = () => {
const { settings, updateSettings, colorScheme } = useSettings(); const { settings, updateSettings, colorScheme } = useWorkspace();
const { settingsModalVisible, setSettingsModalVisible } = useModalContext(); const { settingsModalVisible, setSettingsModalVisible } = useModalContext();
const [state, dispatch] = useReducer(settingsReducer, initialState); const [state, dispatch] = useReducer(settingsReducer, initialState);
const isInitialMount = useRef(true); const isInitialMount = useRef(true);

View File

@@ -3,10 +3,10 @@ import { Box } from '@mantine/core';
import FileActions from './FileActions'; import FileActions from './FileActions';
import FileTree from './FileTree'; import FileTree from './FileTree';
import { useGitOperations } from '../hooks/useGitOperations'; import { useGitOperations } from '../hooks/useGitOperations';
import { useSettings } from '../contexts/SettingsContext'; import { useWorkspace } from '../contexts/WorkspaceContext';
const Sidebar = ({ selectedFile, handleFileSelect, files, loadFileList }) => { const Sidebar = ({ selectedFile, handleFileSelect, files, loadFileList }) => {
const { settings } = useSettings(); const { settings } = useWorkspace();
const { handlePull } = useGitOperations(settings.gitEnabled); const { handlePull } = useGitOperations(settings.gitEnabled);
useEffect(() => { useEffect(() => {

View File

@@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
import { Text, Switch, Group, Box, Title } from '@mantine/core'; import { Text, Switch, Group, Box, Title } from '@mantine/core';
import { useSettings } from '../../contexts/SettingsContext'; import { useWorkspace } from '../../contexts/WorkspaceContext';
const AppearanceSettings = ({ onThemeChange }) => { const AppearanceSettings = ({ onThemeChange }) => {
const { colorScheme, toggleColorScheme } = useSettings(); const { colorScheme, toggleColorScheme } = useWorkspace();
const handleThemeChange = () => { const handleThemeChange = () => {
toggleColorScheme(); toggleColorScheme();

View File

@@ -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 (
<SettingsContext.Provider value={contextValue}>
{children}
</SettingsContext.Provider>
);
};

View File

@@ -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 (
<WorkspaceContext.Provider value={value}>
{children}
</WorkspaceContext.Provider>
);
};
export const useWorkspace = () => {
const context = useContext(WorkspaceContext);
if (context === undefined) {
throw new Error('useWorkspace must be used within a WorkspaceProvider');
}
return context;
};

View File

@@ -2,38 +2,45 @@ import { useState, useCallback, useEffect } from 'react';
import { fetchFileContent } from '../services/api'; import { fetchFileContent } from '../services/api';
import { isImageFile } from '../utils/fileHelpers'; import { isImageFile } from '../utils/fileHelpers';
import { DEFAULT_FILE } from '../utils/constants'; import { DEFAULT_FILE } from '../utils/constants';
import { useWorkspace } from '../contexts/WorkspaceContext';
export const useFileContent = (selectedFile) => { export const useFileContent = (selectedFile) => {
const { currentWorkspace } = useWorkspace();
const [content, setContent] = useState(DEFAULT_FILE.content); const [content, setContent] = useState(DEFAULT_FILE.content);
const [originalContent, setOriginalContent] = useState(DEFAULT_FILE.content); const [originalContent, setOriginalContent] = useState(DEFAULT_FILE.content);
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const loadFileContent = useCallback(async (filePath) => { const loadFileContent = useCallback(
try { async (filePath) => {
let newContent; if (!currentWorkspace) return;
if (filePath === DEFAULT_FILE.path) {
newContent = DEFAULT_FILE.content; try {
} else if (!isImageFile(filePath)) { let newContent;
newContent = await fetchFileContent(filePath); if (filePath === DEFAULT_FILE.path) {
} else { newContent = DEFAULT_FILE.content;
newContent = ''; // Set empty content for image files } 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); [currentWorkspace]
setHasUnsavedChanges(false); );
} catch (err) {
console.error('Error loading file content:', err);
setContent(''); // Set empty content on error
setOriginalContent('');
setHasUnsavedChanges(false);
}
}, []);
useEffect(() => { useEffect(() => {
if (selectedFile) { if (selectedFile && currentWorkspace) {
loadFileContent(selectedFile); loadFileContent(selectedFile);
} }
}, [selectedFile, loadFileContent]); }, [selectedFile, currentWorkspace, loadFileContent]);
const handleContentChange = useCallback( const handleContentChange = useCallback(
(newContent) => { (newContent) => {

View File

@@ -1,12 +1,16 @@
import { useState, useCallback } from 'react'; import { useState, useCallback } from 'react';
import { fetchFileList } from '../services/api'; import { fetchFileList } from '../services/api';
import { useWorkspace } from '../contexts/WorkspaceContext';
export const useFileList = () => { export const useFileList = () => {
const [files, setFiles] = useState([]); const [files, setFiles] = useState([]);
const { currentWorkspace } = useWorkspace();
const loadFileList = useCallback(async () => { const loadFileList = useCallback(async () => {
if (!currentWorkspace) return;
try { try {
const fileList = await fetchFileList(); const fileList = await fetchFileList(currentWorkspace.id);
if (Array.isArray(fileList)) { if (Array.isArray(fileList)) {
setFiles(fileList); setFiles(fileList);
} else { } else {
@@ -15,7 +19,7 @@ export const useFileList = () => {
} catch (error) { } catch (error) {
console.error('Failed to load file list:', error); console.error('Failed to load file list:', error);
} }
}, []); }, [currentWorkspace]);
return { files, loadFileList }; return { files, loadFileList };
}; };

View File

@@ -2,10 +2,12 @@ import { useState, useCallback } from 'react';
import { notifications } from '@mantine/notifications'; import { notifications } from '@mantine/notifications';
import { lookupFileByName } from '../services/api'; import { lookupFileByName } from '../services/api';
import { DEFAULT_FILE } from '../utils/constants'; import { DEFAULT_FILE } from '../utils/constants';
import { useWorkspace } from '../contexts/WorkspaceContext';
export const useFileNavigation = () => { export const useFileNavigation = () => {
const [selectedFile, setSelectedFile] = useState(DEFAULT_FILE.path); const [selectedFile, setSelectedFile] = useState(DEFAULT_FILE.path);
const [isNewFile, setIsNewFile] = useState(true); const [isNewFile, setIsNewFile] = useState(true);
const { currentWorkspace } = useWorkspace();
const handleFileSelect = useCallback((filePath) => { const handleFileSelect = useCallback((filePath) => {
setSelectedFile(filePath); setSelectedFile(filePath);
@@ -14,8 +16,10 @@ export const useFileNavigation = () => {
const handleLinkClick = useCallback( const handleLinkClick = useCallback(
async (filename) => { async (filename) => {
if (!currentWorkspace) return;
try { try {
const filePaths = await lookupFileByName(filename); const filePaths = await lookupFileByName(currentWorkspace.id, filename);
if (filePaths.length >= 1) { if (filePaths.length >= 1) {
handleFileSelect(filePaths[0]); handleFileSelect(filePaths[0]);
} else { } else {
@@ -34,7 +38,7 @@ export const useFileNavigation = () => {
}); });
} }
}, },
[handleFileSelect] [currentWorkspace, handleFileSelect]
); );
return { handleLinkClick, selectedFile, isNewFile, handleFileSelect }; return { handleLinkClick, selectedFile, isNewFile, handleFileSelect };

View File

@@ -1,12 +1,12 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { notifications } from '@mantine/notifications'; import { notifications } from '@mantine/notifications';
import { saveFileContent, deleteFile } from '../services/api'; import { saveFileContent, deleteFile } from '../services/api';
import { useSettings } from '../contexts/SettingsContext'; import { useWorkspace } from '../contexts/WorkspaceContext';
import { useGitOperations } from './useGitOperations'; import { useGitOperations } from './useGitOperations';
export const useFileOperations = () => { export const useFileOperations = () => {
const { settings } = useSettings(); const { currentWorkspace, settings } = useWorkspace();
const { handleCommitAndPush } = useGitOperations(settings.gitEnabled); const { handleCommitAndPush } = useGitOperations();
const autoCommit = useCallback( const autoCommit = useCallback(
async (filePath, action) => { async (filePath, action) => {
@@ -15,7 +15,6 @@ export const useFileOperations = () => {
.replace('${filename}', filePath) .replace('${filename}', filePath)
.replace('${action}', action); .replace('${action}', action);
// Capitalize the first letter of the commit message
commitMessage = commitMessage =
commitMessage.charAt(0).toUpperCase() + commitMessage.slice(1); commitMessage.charAt(0).toUpperCase() + commitMessage.slice(1);
@@ -27,8 +26,10 @@ export const useFileOperations = () => {
const handleSave = useCallback( const handleSave = useCallback(
async (filePath, content) => { async (filePath, content) => {
if (!currentWorkspace) return false;
try { try {
await saveFileContent(filePath, content); await saveFileContent(currentWorkspace.id, filePath, content);
notifications.show({ notifications.show({
title: 'Success', title: 'Success',
message: 'File saved successfully', message: 'File saved successfully',
@@ -46,13 +47,15 @@ export const useFileOperations = () => {
return false; return false;
} }
}, },
[autoCommit] [currentWorkspace, autoCommit]
); );
const handleDelete = useCallback( const handleDelete = useCallback(
async (filePath) => { async (filePath) => {
if (!currentWorkspace) return false;
try { try {
await deleteFile(filePath); await deleteFile(currentWorkspace.id, filePath);
notifications.show({ notifications.show({
title: 'Success', title: 'Success',
message: 'File deleted successfully', message: 'File deleted successfully',
@@ -70,13 +73,15 @@ export const useFileOperations = () => {
return false; return false;
} }
}, },
[autoCommit] [currentWorkspace, autoCommit]
); );
const handleCreate = useCallback( const handleCreate = useCallback(
async (fileName, initialContent = '') => { async (fileName, initialContent = '') => {
if (!currentWorkspace) return false;
try { try {
await saveFileContent(fileName, initialContent); await saveFileContent(currentWorkspace.id, fileName, initialContent);
notifications.show({ notifications.show({
title: 'Success', title: 'Success',
message: 'File created successfully', message: 'File created successfully',
@@ -94,7 +99,7 @@ export const useFileOperations = () => {
return false; return false;
} }
}, },
[autoCommit] [currentWorkspace, autoCommit]
); );
return { handleSave, handleDelete, handleCreate }; return { handleSave, handleDelete, handleCreate };

View File

@@ -1,12 +1,16 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { notifications } from '@mantine/notifications'; import { notifications } from '@mantine/notifications';
import { pullChanges, commitAndPush } from '../services/api'; 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 () => { const handlePull = useCallback(async () => {
if (!gitEnabled) return false; if (!currentWorkspace || !settings.gitEnabled) return false;
try { try {
await pullChanges(); await pullChanges(currentWorkspace.id);
notifications.show({ notifications.show({
title: 'Success', title: 'Success',
message: 'Successfully pulled latest changes', message: 'Successfully pulled latest changes',
@@ -22,13 +26,14 @@ export const useGitOperations = (gitEnabled) => {
}); });
return false; return false;
} }
}, [gitEnabled]); }, [currentWorkspace, settings.gitEnabled]);
const handleCommitAndPush = useCallback( const handleCommitAndPush = useCallback(
async (message) => { async (message) => {
if (!gitEnabled) return false; if (!currentWorkspace || !settings.gitEnabled) return false;
try { try {
await commitAndPush(message); await commitAndPush(currentWorkspace.id, message);
notifications.show({ notifications.show({
title: 'Success', title: 'Success',
message: 'Successfully committed and pushed changes', message: 'Successfully committed and pushed changes',
@@ -45,7 +50,7 @@ export const useGitOperations = (gitEnabled) => {
return false; return false;
} }
}, },
[gitEnabled] [currentWorkspace, settings.gitEnabled]
); );
return { handlePull, handleCommitAndPush }; return { handlePull, handleCommitAndPush };

View File

@@ -16,76 +16,176 @@ const apiCall = async (url, options = {}) => {
} }
}; };
export const fetchFileList = async () => { export const fetchLastWorkspace = async () => {
const response = await apiCall(`${API_BASE_URL}/files`); const response = await apiCall(`${API_BASE_URL}/users/1/workspaces/last`);
return response.json(); return response.json();
}; };
export const fetchFileContent = async (filePath) => { export const fetchFileList = async (workspaceId) => {
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) => {
const response = await apiCall( 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(); const data = await response.json();
return data.paths; 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();
};