mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-05 23:44:22 +00:00
Add Workspace context
This commit is contained in:
@@ -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 <div>Loading...</div>;
|
||||
}
|
||||
|
||||
return <Layout />;
|
||||
}
|
||||
|
||||
@@ -26,11 +20,11 @@ function App() {
|
||||
<MantineProvider defaultColorScheme="light">
|
||||
<Notifications />
|
||||
<ModalsProvider>
|
||||
<SettingsProvider>
|
||||
<WorkspaceProvider>
|
||||
<ModalProvider>
|
||||
<AppContent />
|
||||
</ModalProvider>
|
||||
</SettingsProvider>
|
||||
</WorkspaceProvider>
|
||||
</ModalsProvider>
|
||||
</MantineProvider>
|
||||
</>
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 (
|
||||
<Center style={{ height: '100vh' }}>
|
||||
<Loader size="xl" />
|
||||
</Center>
|
||||
);
|
||||
}
|
||||
|
||||
if (!currentWorkspace) {
|
||||
return <div>No workspace found. Please create a workspace.</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<AppShell header={{ height: 60 }} padding="md">
|
||||
<AppShell.Header>
|
||||
@@ -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',
|
||||
}}
|
||||
>
|
||||
<Sidebar
|
||||
|
||||
@@ -10,7 +10,7 @@ import CommitMessageModal from './modals/CommitMessageModal';
|
||||
import { useFileContent } from '../hooks/useFileContent';
|
||||
import { useFileOperations } from '../hooks/useFileOperations';
|
||||
import { useGitOperations } from '../hooks/useGitOperations';
|
||||
import { useSettings } from '../contexts/SettingsContext';
|
||||
import { useWorkspace } from '../contexts/WorkspaceContext';
|
||||
|
||||
const MainContent = ({
|
||||
selectedFile,
|
||||
@@ -19,7 +19,7 @@ const MainContent = ({
|
||||
loadFileList,
|
||||
}) => {
|
||||
const [activeTab, setActiveTab] = useState('source');
|
||||
const { settings } = useSettings();
|
||||
const { settings } = useWorkspace();
|
||||
const {
|
||||
content,
|
||||
hasUnsavedChanges,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
92
frontend/src/contexts/WorkspaceContext.js
Normal file
92
frontend/src/contexts/WorkspaceContext.js
Normal 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;
|
||||
};
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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 };
|
||||
};
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user