mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-06 07:54:22 +00:00
Rename root folders
This commit is contained in:
48
app/src/hooks/useAdminData.js
Normal file
48
app/src/hooks/useAdminData.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { getUsers, getWorkspaces, getSystemStats } from '../services/adminApi';
|
||||
|
||||
// Hook for admin data fetching (stats and workspaces)
|
||||
export const useAdminData = (type) => {
|
||||
const [data, setData] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const loadData = async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
let response;
|
||||
switch (type) {
|
||||
case 'stats':
|
||||
response = await getSystemStats();
|
||||
break;
|
||||
case 'workspaces':
|
||||
response = await getWorkspaces();
|
||||
break;
|
||||
case 'users':
|
||||
response = await getUsers();
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid data type');
|
||||
}
|
||||
setData(response);
|
||||
} catch (err) {
|
||||
const message = err.response?.data?.error || err.message;
|
||||
setError(message);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: `Failed to load ${type}: ${message}`,
|
||||
color: 'red',
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
}, [type]);
|
||||
|
||||
return { data, loading, error, reload: loadData };
|
||||
};
|
||||
61
app/src/hooks/useFileContent.js
Normal file
61
app/src/hooks/useFileContent.js
Normal file
@@ -0,0 +1,61 @@
|
||||
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) => {
|
||||
if (!currentWorkspace) return;
|
||||
|
||||
try {
|
||||
let newContent;
|
||||
if (filePath === DEFAULT_FILE.path) {
|
||||
newContent = DEFAULT_FILE.content;
|
||||
} else if (!isImageFile(filePath)) {
|
||||
newContent = await fetchFileContent(currentWorkspace.name, 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);
|
||||
}
|
||||
},
|
||||
[currentWorkspace]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedFile && currentWorkspace) {
|
||||
loadFileContent(selectedFile);
|
||||
}
|
||||
}, [selectedFile, currentWorkspace, loadFileContent]);
|
||||
|
||||
const handleContentChange = useCallback(
|
||||
(newContent) => {
|
||||
setContent(newContent);
|
||||
setHasUnsavedChanges(newContent !== originalContent);
|
||||
},
|
||||
[originalContent]
|
||||
);
|
||||
|
||||
return {
|
||||
content,
|
||||
setContent,
|
||||
hasUnsavedChanges,
|
||||
setHasUnsavedChanges,
|
||||
loadFileContent,
|
||||
handleContentChange,
|
||||
};
|
||||
};
|
||||
26
app/src/hooks/useFileList.js
Normal file
26
app/src/hooks/useFileList.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { fetchFileList } from '../services/api';
|
||||
import { useWorkspace } from '../contexts/WorkspaceContext';
|
||||
|
||||
export const useFileList = () => {
|
||||
const [files, setFiles] = useState([]);
|
||||
const { currentWorkspace, loading: workspaceLoading } = useWorkspace();
|
||||
|
||||
const loadFileList = useCallback(async () => {
|
||||
if (!currentWorkspace || workspaceLoading) return;
|
||||
|
||||
try {
|
||||
const fileList = await fetchFileList(currentWorkspace.name);
|
||||
if (Array.isArray(fileList)) {
|
||||
setFiles(fileList);
|
||||
} else {
|
||||
throw new Error('File list is not an array');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load file list:', error);
|
||||
setFiles([]);
|
||||
}
|
||||
}, [currentWorkspace, workspaceLoading]);
|
||||
|
||||
return { files, loadFileList };
|
||||
};
|
||||
45
app/src/hooks/useFileNavigation.js
Normal file
45
app/src/hooks/useFileNavigation.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import { DEFAULT_FILE } from '../utils/constants';
|
||||
import { useWorkspace } from '../contexts/WorkspaceContext';
|
||||
import { useLastOpenedFile } from './useLastOpenedFile';
|
||||
|
||||
export const useFileNavigation = () => {
|
||||
const [selectedFile, setSelectedFile] = useState(DEFAULT_FILE.path);
|
||||
const [isNewFile, setIsNewFile] = useState(true);
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { loadLastOpenedFile, saveLastOpenedFile } = useLastOpenedFile();
|
||||
|
||||
const handleFileSelect = useCallback(
|
||||
async (filePath) => {
|
||||
const newPath = filePath || DEFAULT_FILE.path;
|
||||
setSelectedFile(newPath);
|
||||
setIsNewFile(!filePath);
|
||||
|
||||
if (filePath) {
|
||||
await saveLastOpenedFile(filePath);
|
||||
}
|
||||
},
|
||||
[saveLastOpenedFile]
|
||||
);
|
||||
|
||||
// Load last opened file when workspace changes
|
||||
useEffect(() => {
|
||||
const initializeFile = async () => {
|
||||
setSelectedFile(DEFAULT_FILE.path);
|
||||
setIsNewFile(true);
|
||||
|
||||
const lastFile = await loadLastOpenedFile();
|
||||
if (lastFile) {
|
||||
handleFileSelect(lastFile);
|
||||
} else {
|
||||
handleFileSelect(null);
|
||||
}
|
||||
};
|
||||
|
||||
if (currentWorkspace) {
|
||||
initializeFile();
|
||||
}
|
||||
}, [currentWorkspace, loadLastOpenedFile, handleFileSelect]);
|
||||
|
||||
return { selectedFile, isNewFile, handleFileSelect };
|
||||
};
|
||||
106
app/src/hooks/useFileOperations.js
Normal file
106
app/src/hooks/useFileOperations.js
Normal file
@@ -0,0 +1,106 @@
|
||||
import { useCallback } from 'react';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { saveFileContent, deleteFile } from '../services/api';
|
||||
import { useWorkspace } from '../contexts/WorkspaceContext';
|
||||
import { useGitOperations } from './useGitOperations';
|
||||
|
||||
export const useFileOperations = () => {
|
||||
const { currentWorkspace, settings } = useWorkspace();
|
||||
const { handleCommitAndPush } = useGitOperations();
|
||||
|
||||
const autoCommit = useCallback(
|
||||
async (filePath, action) => {
|
||||
if (settings.gitAutoCommit && settings.gitEnabled) {
|
||||
let commitMessage = settings.gitCommitMsgTemplate
|
||||
.replace('${filename}', filePath)
|
||||
.replace('${action}', action);
|
||||
|
||||
commitMessage =
|
||||
commitMessage.charAt(0).toUpperCase() + commitMessage.slice(1);
|
||||
|
||||
await handleCommitAndPush(commitMessage);
|
||||
}
|
||||
},
|
||||
[settings]
|
||||
);
|
||||
|
||||
const handleSave = useCallback(
|
||||
async (filePath, content) => {
|
||||
if (!currentWorkspace) return false;
|
||||
|
||||
try {
|
||||
await saveFileContent(currentWorkspace.name, filePath, content);
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'File saved successfully',
|
||||
color: 'green',
|
||||
});
|
||||
autoCommit(filePath, 'update');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error saving file:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to save file',
|
||||
color: 'red',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[currentWorkspace, autoCommit]
|
||||
);
|
||||
|
||||
const handleDelete = useCallback(
|
||||
async (filePath) => {
|
||||
if (!currentWorkspace) return false;
|
||||
|
||||
try {
|
||||
await deleteFile(currentWorkspace.name, filePath);
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'File deleted successfully',
|
||||
color: 'green',
|
||||
});
|
||||
autoCommit(filePath, 'delete');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error deleting file:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to delete file',
|
||||
color: 'red',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[currentWorkspace, autoCommit]
|
||||
);
|
||||
|
||||
const handleCreate = useCallback(
|
||||
async (fileName, initialContent = '') => {
|
||||
if (!currentWorkspace) return false;
|
||||
|
||||
try {
|
||||
await saveFileContent(currentWorkspace.name, fileName, initialContent);
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'File created successfully',
|
||||
color: 'green',
|
||||
});
|
||||
autoCommit(fileName, 'create');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error creating new file:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to create new file',
|
||||
color: 'red',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[currentWorkspace, autoCommit]
|
||||
);
|
||||
|
||||
return { handleSave, handleDelete, handleCreate };
|
||||
};
|
||||
57
app/src/hooks/useGitOperations.js
Normal file
57
app/src/hooks/useGitOperations.js
Normal file
@@ -0,0 +1,57 @@
|
||||
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();
|
||||
|
||||
const handlePull = useCallback(async () => {
|
||||
if (!currentWorkspace || !settings.gitEnabled) return false;
|
||||
|
||||
try {
|
||||
await pullChanges(currentWorkspace.name);
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'Successfully pulled latest changes',
|
||||
color: 'green',
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to pull latest changes:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to pull latest changes',
|
||||
color: 'red',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}, [currentWorkspace, settings.gitEnabled]);
|
||||
|
||||
const handleCommitAndPush = useCallback(
|
||||
async (message) => {
|
||||
if (!currentWorkspace || !settings.gitEnabled) return false;
|
||||
|
||||
try {
|
||||
await commitAndPush(currentWorkspace.name, message);
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'Successfully committed and pushed changes',
|
||||
color: 'green',
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to commit and push changes:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to commit and push changes',
|
||||
color: 'red',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[currentWorkspace, settings.gitEnabled]
|
||||
);
|
||||
|
||||
return { handlePull, handleCommitAndPush };
|
||||
};
|
||||
37
app/src/hooks/useLastOpenedFile.js
Normal file
37
app/src/hooks/useLastOpenedFile.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { useCallback } from 'react';
|
||||
import { getLastOpenedFile, updateLastOpenedFile } from '../services/api';
|
||||
import { useWorkspace } from '../contexts/WorkspaceContext';
|
||||
|
||||
export const useLastOpenedFile = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
const loadLastOpenedFile = useCallback(async () => {
|
||||
if (!currentWorkspace) return null;
|
||||
|
||||
try {
|
||||
const response = await getLastOpenedFile(currentWorkspace.name);
|
||||
return response.lastOpenedFilePath || null;
|
||||
} catch (error) {
|
||||
console.error('Failed to load last opened file:', error);
|
||||
return null;
|
||||
}
|
||||
}, [currentWorkspace]);
|
||||
|
||||
const saveLastOpenedFile = useCallback(
|
||||
async (filePath) => {
|
||||
if (!currentWorkspace) return;
|
||||
|
||||
try {
|
||||
await updateLastOpenedFile(currentWorkspace.name, filePath);
|
||||
} catch (error) {
|
||||
console.error('Failed to save last opened file:', error);
|
||||
}
|
||||
},
|
||||
[currentWorkspace]
|
||||
);
|
||||
|
||||
return {
|
||||
loadLastOpenedFile,
|
||||
saveLastOpenedFile,
|
||||
};
|
||||
};
|
||||
71
app/src/hooks/useProfileSettings.js
Normal file
71
app/src/hooks/useProfileSettings.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { updateProfile, deleteProfile } from '../services/api';
|
||||
|
||||
export function useProfileSettings() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleProfileUpdate = useCallback(async (updates) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const updatedUser = await updateProfile(updates);
|
||||
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'Profile updated successfully',
|
||||
color: 'green',
|
||||
});
|
||||
|
||||
return { success: true, user: updatedUser };
|
||||
} catch (error) {
|
||||
let errorMessage = 'Failed to update profile';
|
||||
|
||||
if (error.message.includes('password')) {
|
||||
errorMessage = 'Current password is incorrect';
|
||||
} else if (error.message.includes('email')) {
|
||||
errorMessage = 'Email is already in use';
|
||||
}
|
||||
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: errorMessage,
|
||||
color: 'red',
|
||||
});
|
||||
|
||||
return { success: false, error: error.message };
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleAccountDeletion = useCallback(async (password) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
await deleteProfile(password);
|
||||
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'Account deleted successfully',
|
||||
color: 'green',
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: error.message || 'Failed to delete account',
|
||||
color: 'red',
|
||||
});
|
||||
|
||||
return { success: false, error: error.message };
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return {
|
||||
loading,
|
||||
updateProfile: handleProfileUpdate,
|
||||
deleteAccount: handleAccountDeletion,
|
||||
};
|
||||
}
|
||||
79
app/src/hooks/useUserAdmin.js
Normal file
79
app/src/hooks/useUserAdmin.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import { useAdminData } from './useAdminData';
|
||||
import { createUser, updateUser, deleteUser } from '../services/adminApi';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
|
||||
export const useUserAdmin = () => {
|
||||
const { data: users, loading, error, reload } = useAdminData('users');
|
||||
|
||||
const handleCreate = async (userData) => {
|
||||
try {
|
||||
await createUser(userData);
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'User created successfully',
|
||||
color: 'green',
|
||||
});
|
||||
reload();
|
||||
return { success: true };
|
||||
} catch (err) {
|
||||
const message = err.response?.data?.error || err.message;
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: `Failed to create user: ${message}`,
|
||||
color: 'red',
|
||||
});
|
||||
return { success: false, error: message };
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpdate = async (userId, userData) => {
|
||||
try {
|
||||
await updateUser(userId, userData);
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'User updated successfully',
|
||||
color: 'green',
|
||||
});
|
||||
reload();
|
||||
return { success: true };
|
||||
} catch (err) {
|
||||
const message = err.response?.data?.error || err.message;
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: `Failed to update user: ${message}`,
|
||||
color: 'red',
|
||||
});
|
||||
return { success: false, error: message };
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = async (userId) => {
|
||||
try {
|
||||
await deleteUser(userId);
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: 'User deleted successfully',
|
||||
color: 'green',
|
||||
});
|
||||
reload();
|
||||
return { success: true };
|
||||
} catch (err) {
|
||||
const message = err.response?.data?.error || err.message;
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: `Failed to delete user: ${message}`,
|
||||
color: 'red',
|
||||
});
|
||||
return { success: false, error: message };
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
users,
|
||||
loading,
|
||||
error,
|
||||
create: handleCreate,
|
||||
update: handleUpdate,
|
||||
delete: handleDelete,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user