mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-05 23:44:22 +00:00
Migrate ModalContext and WorkspaceContext
This commit is contained in:
@@ -1,11 +1,6 @@
|
|||||||
import { API_BASE_URL } from '@/types/authApi';
|
import { API_BASE_URL } from '@/types/authApi';
|
||||||
import { apiCall } from './api';
|
import { apiCall } from './api';
|
||||||
import {
|
import { isWorkspace, Workspace } from '@/types/workspace';
|
||||||
DeleteWorkspaceResponse,
|
|
||||||
isWorkspace,
|
|
||||||
LastWorkspaceNameResponse,
|
|
||||||
Workspace,
|
|
||||||
} from '@/types/workspace';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* listWorkspaces fetches the list of workspaces
|
* listWorkspaces fetches the list of workspaces
|
||||||
@@ -97,12 +92,12 @@ export const updateWorkspace = async (
|
|||||||
/**
|
/**
|
||||||
* deleteWorkspace deletes the workspace with the given name
|
* deleteWorkspace deletes the workspace with the given name
|
||||||
* @param workspaceName - The name of the workspace to delete
|
* @param workspaceName - The name of the workspace to delete
|
||||||
* @returns {Promise<DeleteWorkspaceResponse>} A promise that resolves to the response object
|
* @returns {Promise<string>} A promise that resolves to the next workspace name to switch to
|
||||||
* @throws {Error} If the API call fails or returns an invalid response
|
* @throws {Error} If the API call fails or returns an invalid response
|
||||||
*/
|
*/
|
||||||
export const deleteWorkspace = async (
|
export const deleteWorkspace = async (
|
||||||
workspaceName: string
|
workspaceName: string
|
||||||
): Promise<DeleteWorkspaceResponse> => {
|
): Promise<string> => {
|
||||||
const response = await apiCall(
|
const response = await apiCall(
|
||||||
`${API_BASE_URL}/workspaces/${encodeURIComponent(workspaceName)}`,
|
`${API_BASE_URL}/workspaces/${encodeURIComponent(workspaceName)}`,
|
||||||
{
|
{
|
||||||
@@ -113,23 +108,22 @@ export const deleteWorkspace = async (
|
|||||||
if (!('nextWorkspaceName' in data)) {
|
if (!('nextWorkspaceName' in data)) {
|
||||||
throw new Error('Invalid delete workspace response received from API');
|
throw new Error('Invalid delete workspace response received from API');
|
||||||
}
|
}
|
||||||
return data as DeleteWorkspaceResponse;
|
return data.nextWorkspaceName as string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getLastWorkspaceName fetches the last workspace name
|
* getLastWorkspaceName fetches the last workspace name
|
||||||
* @returns {Promise<LastWorkspaceNameResponse>} A promise that resolves to the last workspace name
|
* @returns {Promise<string>} A promise that resolves to the last workspace name
|
||||||
* @throws {Error} If the API call fails or returns an invalid response
|
* @throws {Error} If the API call fails or returns an invalid response
|
||||||
*/
|
*/
|
||||||
export const getLastWorkspaceName =
|
export const getLastWorkspaceName = async (): Promise<string> => {
|
||||||
async (): Promise<LastWorkspaceNameResponse> => {
|
|
||||||
const response = await apiCall(`${API_BASE_URL}/workspaces/last`);
|
const response = await apiCall(`${API_BASE_URL}/workspaces/last`);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (!('lastWorkspaceName' in data)) {
|
if (!('lastWorkspaceName' in data)) {
|
||||||
throw new Error('Invalid last workspace name response received from API');
|
throw new Error('Invalid last workspace name response received from API');
|
||||||
}
|
}
|
||||||
return data as LastWorkspaceNameResponse;
|
return data.lastWorkspaceName as string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* updateLastWorkspaceName updates the last workspace name
|
* updateLastWorkspaceName updates the last workspace name
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
import React, { createContext, useContext, useState } from 'react';
|
|
||||||
|
|
||||||
const ModalContext = createContext();
|
|
||||||
|
|
||||||
export const ModalProvider = ({ children }) => {
|
|
||||||
const [newFileModalVisible, setNewFileModalVisible] = useState(false);
|
|
||||||
const [deleteFileModalVisible, setDeleteFileModalVisible] = useState(false);
|
|
||||||
const [commitMessageModalVisible, setCommitMessageModalVisible] =
|
|
||||||
useState(false);
|
|
||||||
const [settingsModalVisible, setSettingsModalVisible] = useState(false);
|
|
||||||
const [switchWorkspaceModalVisible, setSwitchWorkspaceModalVisible] =
|
|
||||||
useState(false);
|
|
||||||
const [createWorkspaceModalVisible, setCreateWorkspaceModalVisible] =
|
|
||||||
useState(false);
|
|
||||||
|
|
||||||
const value = {
|
|
||||||
newFileModalVisible,
|
|
||||||
setNewFileModalVisible,
|
|
||||||
deleteFileModalVisible,
|
|
||||||
setDeleteFileModalVisible,
|
|
||||||
commitMessageModalVisible,
|
|
||||||
setCommitMessageModalVisible,
|
|
||||||
settingsModalVisible,
|
|
||||||
setSettingsModalVisible,
|
|
||||||
switchWorkspaceModalVisible,
|
|
||||||
setSwitchWorkspaceModalVisible,
|
|
||||||
createWorkspaceModalVisible,
|
|
||||||
setCreateWorkspaceModalVisible,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModalContext.Provider value={value}>{children}</ModalContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useModalContext = () => useContext(ModalContext);
|
|
||||||
62
app/src/contexts/ModalContext.tsx
Normal file
62
app/src/contexts/ModalContext.tsx
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import React, { createContext, useContext, useState, ReactNode } from 'react';
|
||||||
|
|
||||||
|
interface ModalContextType {
|
||||||
|
newFileModalVisible: boolean;
|
||||||
|
setNewFileModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
deleteFileModalVisible: boolean;
|
||||||
|
setDeleteFileModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
commitMessageModalVisible: boolean;
|
||||||
|
setCommitMessageModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
settingsModalVisible: boolean;
|
||||||
|
setSettingsModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
switchWorkspaceModalVisible: boolean;
|
||||||
|
setSwitchWorkspaceModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
createWorkspaceModalVisible: boolean;
|
||||||
|
setCreateWorkspaceModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the context with a default undefined value
|
||||||
|
const ModalContext = createContext<ModalContextType | null>(null);
|
||||||
|
|
||||||
|
interface ModalProviderProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ModalProvider: React.FC<ModalProviderProps> = ({ children }) => {
|
||||||
|
const [newFileModalVisible, setNewFileModalVisible] = useState(false);
|
||||||
|
const [deleteFileModalVisible, setDeleteFileModalVisible] = useState(false);
|
||||||
|
const [commitMessageModalVisible, setCommitMessageModalVisible] =
|
||||||
|
useState(false);
|
||||||
|
const [settingsModalVisible, setSettingsModalVisible] = useState(false);
|
||||||
|
const [switchWorkspaceModalVisible, setSwitchWorkspaceModalVisible] =
|
||||||
|
useState(false);
|
||||||
|
const [createWorkspaceModalVisible, setCreateWorkspaceModalVisible] =
|
||||||
|
useState(false);
|
||||||
|
|
||||||
|
const value: ModalContextType = {
|
||||||
|
newFileModalVisible,
|
||||||
|
setNewFileModalVisible,
|
||||||
|
deleteFileModalVisible,
|
||||||
|
setDeleteFileModalVisible,
|
||||||
|
commitMessageModalVisible,
|
||||||
|
setCommitMessageModalVisible,
|
||||||
|
settingsModalVisible,
|
||||||
|
setSettingsModalVisible,
|
||||||
|
switchWorkspaceModalVisible,
|
||||||
|
setSwitchWorkspaceModalVisible,
|
||||||
|
createWorkspaceModalVisible,
|
||||||
|
setCreateWorkspaceModalVisible,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalContext.Provider value={value}>{children}</ModalContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useModalContext = (): ModalContextType => {
|
||||||
|
const context = useContext(ModalContext);
|
||||||
|
if (context === null) {
|
||||||
|
throw new Error('useModalContext must be used within a ModalProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
@@ -4,28 +4,53 @@ import React, {
|
|||||||
useState,
|
useState,
|
||||||
useEffect,
|
useEffect,
|
||||||
useCallback,
|
useCallback,
|
||||||
|
ReactNode,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { useMantineColorScheme } from '@mantine/core';
|
import { MantineColorScheme, useMantineColorScheme } from '@mantine/core';
|
||||||
import { notifications } from '@mantine/notifications';
|
import { notifications } from '@mantine/notifications';
|
||||||
import {
|
import {
|
||||||
fetchLastWorkspaceName,
|
getLastWorkspaceName,
|
||||||
getWorkspace,
|
getWorkspace,
|
||||||
updateWorkspace,
|
updateWorkspace,
|
||||||
updateLastWorkspaceName,
|
updateLastWorkspaceName,
|
||||||
deleteWorkspace,
|
deleteWorkspace,
|
||||||
listWorkspaces,
|
listWorkspaces,
|
||||||
} from '../api/git';
|
} from '@/api/workspace';
|
||||||
import { DEFAULT_WORKSPACE_SETTINGS } from '../utils/constants';
|
import {
|
||||||
|
Workspace,
|
||||||
|
DEFAULT_WORKSPACE_SETTINGS,
|
||||||
|
WorkspaceSettings,
|
||||||
|
} from '@/types/workspace';
|
||||||
|
|
||||||
const WorkspaceContext = createContext();
|
interface WorkspaceContextType {
|
||||||
|
currentWorkspace: Workspace | null;
|
||||||
|
workspaces: Workspace[];
|
||||||
|
settings: Workspace | typeof DEFAULT_WORKSPACE_SETTINGS;
|
||||||
|
updateSettings: (newSettings: Partial<Workspace>) => Promise<void>;
|
||||||
|
loading: boolean;
|
||||||
|
colorScheme: MantineColorScheme;
|
||||||
|
updateColorScheme: (newTheme: MantineColorScheme) => void;
|
||||||
|
switchWorkspace: (workspaceName: string) => Promise<void>;
|
||||||
|
deleteCurrentWorkspace: () => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
export const WorkspaceProvider = ({ children }) => {
|
const WorkspaceContext = createContext<WorkspaceContextType | null>(null);
|
||||||
const [currentWorkspace, setCurrentWorkspace] = useState(null);
|
|
||||||
const [workspaces, setWorkspaces] = useState([]);
|
interface WorkspaceProviderProps {
|
||||||
const [loading, setLoading] = useState(true);
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WorkspaceProvider: React.FC<WorkspaceProviderProps> = ({
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const [currentWorkspace, setCurrentWorkspace] = useState<Workspace | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const [workspaces, setWorkspaces] = useState<Workspace[]>([]);
|
||||||
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
const { colorScheme, setColorScheme } = useMantineColorScheme();
|
const { colorScheme, setColorScheme } = useMantineColorScheme();
|
||||||
|
|
||||||
const loadWorkspaces = useCallback(async () => {
|
const loadWorkspaces = useCallback(async (): Promise<Workspace[]> => {
|
||||||
try {
|
try {
|
||||||
const workspaceList = await listWorkspaces();
|
const workspaceList = await listWorkspaces();
|
||||||
setWorkspaces(workspaceList);
|
setWorkspaces(workspaceList);
|
||||||
@@ -41,11 +66,12 @@ export const WorkspaceProvider = ({ children }) => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const loadWorkspaceData = useCallback(async (workspaceName) => {
|
const loadWorkspaceData = useCallback(
|
||||||
|
async (workspaceName: string): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const workspace = await getWorkspace(workspaceName);
|
const workspace = await getWorkspace(workspaceName);
|
||||||
setCurrentWorkspace(workspace);
|
setCurrentWorkspace(workspace);
|
||||||
setColorScheme(workspace.theme);
|
setColorScheme(workspace.theme as MantineColorScheme);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load workspace data:', error);
|
console.error('Failed to load workspace data:', error);
|
||||||
notifications.show({
|
notifications.show({
|
||||||
@@ -54,9 +80,11 @@ export const WorkspaceProvider = ({ children }) => {
|
|||||||
color: 'red',
|
color: 'red',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const loadFirstAvailableWorkspace = useCallback(async () => {
|
const loadFirstAvailableWorkspace = useCallback(async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const allWorkspaces = await listWorkspaces();
|
const allWorkspaces = await listWorkspaces();
|
||||||
if (allWorkspaces.length > 0) {
|
if (allWorkspaces.length > 0) {
|
||||||
@@ -75,9 +103,9 @@ export const WorkspaceProvider = ({ children }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initializeWorkspace = async () => {
|
const initializeWorkspace = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const { lastWorkspaceName } = await fetchLastWorkspaceName();
|
const lastWorkspaceName = await getLastWorkspaceName();
|
||||||
if (lastWorkspaceName) {
|
if (lastWorkspaceName) {
|
||||||
await loadWorkspaceData(lastWorkspaceName);
|
await loadWorkspaceData(lastWorkspaceName);
|
||||||
} else {
|
} else {
|
||||||
@@ -95,7 +123,8 @@ export const WorkspaceProvider = ({ children }) => {
|
|||||||
initializeWorkspace();
|
initializeWorkspace();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const switchWorkspace = useCallback(async (workspaceName) => {
|
const switchWorkspace = useCallback(
|
||||||
|
async (workspaceName: string): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
await updateLastWorkspaceName(workspaceName);
|
await updateLastWorkspaceName(workspaceName);
|
||||||
@@ -111,9 +140,11 @@ export const WorkspaceProvider = ({ children }) => {
|
|||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, []);
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
const deleteCurrentWorkspace = useCallback(async () => {
|
const deleteCurrentWorkspace = useCallback(async (): Promise<void> => {
|
||||||
if (!currentWorkspace) return;
|
if (!currentWorkspace) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -129,10 +160,12 @@ export const WorkspaceProvider = ({ children }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete workspace and get the next workspace ID
|
// Delete workspace and get the next workspace ID
|
||||||
const response = await deleteWorkspace(currentWorkspace.name);
|
const nextWorkspaceName: string = await deleteWorkspace(
|
||||||
|
currentWorkspace.name
|
||||||
|
);
|
||||||
|
|
||||||
// Load the new workspace data
|
// Load the new workspace data
|
||||||
await loadWorkspaceData(response.nextWorkspaceName);
|
await loadWorkspaceData(nextWorkspaceName);
|
||||||
|
|
||||||
notifications.show({
|
notifications.show({
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
@@ -152,7 +185,7 @@ export const WorkspaceProvider = ({ children }) => {
|
|||||||
}, [currentWorkspace]);
|
}, [currentWorkspace]);
|
||||||
|
|
||||||
const updateSettings = useCallback(
|
const updateSettings = useCallback(
|
||||||
async (newSettings) => {
|
async (newSettings: Partial<Workspace>): Promise<void> => {
|
||||||
if (!currentWorkspace) return;
|
if (!currentWorkspace) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -177,13 +210,13 @@ export const WorkspaceProvider = ({ children }) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const updateColorScheme = useCallback(
|
const updateColorScheme = useCallback(
|
||||||
(newTheme) => {
|
(newTheme: MantineColorScheme): void => {
|
||||||
setColorScheme(newTheme);
|
setColorScheme(newTheme);
|
||||||
},
|
},
|
||||||
[setColorScheme]
|
[setColorScheme]
|
||||||
);
|
);
|
||||||
|
|
||||||
const value = {
|
const value: WorkspaceContextType = {
|
||||||
currentWorkspace,
|
currentWorkspace,
|
||||||
workspaces,
|
workspaces,
|
||||||
settings: currentWorkspace || DEFAULT_WORKSPACE_SETTINGS,
|
settings: currentWorkspace || DEFAULT_WORKSPACE_SETTINGS,
|
||||||
@@ -202,9 +235,9 @@ export const WorkspaceProvider = ({ children }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useWorkspace = () => {
|
export const useWorkspace = (): WorkspaceContextType => {
|
||||||
const context = useContext(WorkspaceContext);
|
const context = useContext(WorkspaceContext);
|
||||||
if (context === undefined) {
|
if (!context) {
|
||||||
throw new Error('useWorkspace must be used within a WorkspaceProvider');
|
throw new Error('useWorkspace must be used within a WorkspaceProvider');
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
@@ -1,13 +1,5 @@
|
|||||||
import { Theme } from './theme';
|
import { Theme } from './theme';
|
||||||
|
|
||||||
export interface DeleteWorkspaceResponse {
|
|
||||||
nextWorkspaceName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LastWorkspaceNameResponse {
|
|
||||||
lastWorkspaceName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WorkspaceSettings {
|
export interface WorkspaceSettings {
|
||||||
theme: Theme;
|
theme: Theme;
|
||||||
autoSave: boolean;
|
autoSave: boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user