mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-06 07:54:22 +00:00
Migrate Settings to Mantine ui
This commit is contained in:
@@ -1,15 +1,28 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { GeistProvider, CssBaseline } from '@geist-ui/core';
|
||||
import { MantineProvider, AppShell, Container } from '@mantine/core';
|
||||
import {
|
||||
MantineProvider,
|
||||
createTheme,
|
||||
AppShell,
|
||||
Container,
|
||||
} from '@mantine/core';
|
||||
import { Notifications } from '@mantine/notifications';
|
||||
import { ModalsProvider } from '@mantine/modals';
|
||||
import Header from './components/Header';
|
||||
import MainContent from './components/MainContent';
|
||||
import { SettingsProvider, useSettings } from './contexts/SettingsContext';
|
||||
import { ModalProvider } from './contexts/ModalContext';
|
||||
import '@mantine/core/styles.css';
|
||||
import '@mantine/notifications/styles.css';
|
||||
import './App.scss';
|
||||
|
||||
const mantineTheme = createTheme({
|
||||
/** You can add your Mantine theme overrides here */
|
||||
});
|
||||
|
||||
function AppContent() {
|
||||
const { settings, loading } = useSettings();
|
||||
const [opened, setOpened] = useState(false);
|
||||
|
||||
if (loading) {
|
||||
return <div>Loading...</div>;
|
||||
@@ -17,40 +30,21 @@ function AppContent() {
|
||||
|
||||
return (
|
||||
<GeistProvider themeType={settings.theme}>
|
||||
<MantineProvider
|
||||
withGlobalStyles
|
||||
withNormalizeCSS
|
||||
theme={{
|
||||
colorScheme: settings.theme,
|
||||
components: {
|
||||
Container: {
|
||||
defaultProps: {
|
||||
sizes: {
|
||||
xs: 540,
|
||||
sm: 720,
|
||||
md: 960,
|
||||
lg: 1140,
|
||||
xl: 1320,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<CssBaseline />
|
||||
<AppShell header={{ height: 60 }} padding="md">
|
||||
<AppShell.Header>
|
||||
<Container size="xl">
|
||||
<CssBaseline />
|
||||
<MantineProvider theme={mantineTheme} defaultColorScheme={settings.theme}>
|
||||
<Notifications />
|
||||
<ModalsProvider>
|
||||
<AppShell header={{ height: 60 }} padding="md">
|
||||
<AppShell.Header>
|
||||
<Header />
|
||||
</Container>
|
||||
</AppShell.Header>
|
||||
|
||||
<AppShell.Main>
|
||||
<Container size="xl">
|
||||
<MainContent />
|
||||
</Container>
|
||||
</AppShell.Main>
|
||||
</AppShell>
|
||||
</AppShell.Header>
|
||||
<AppShell.Main>
|
||||
<Container size="xl">
|
||||
<MainContent />
|
||||
</Container>
|
||||
</AppShell.Main>
|
||||
</AppShell>
|
||||
</ModalsProvider>
|
||||
</MantineProvider>
|
||||
</GeistProvider>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React, { useReducer, useEffect, useCallback, useRef } from 'react';
|
||||
import { Modal, Spacer, Dot, useToasts } from '@geist-ui/core';
|
||||
import { Modal, Badge, Button, Group } from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { useSettings } from '../contexts/SettingsContext';
|
||||
import AppearanceSettings from './settings/AppearanceSettings';
|
||||
import EditorSettings from './settings/EditorSettings';
|
||||
@@ -51,7 +53,6 @@ function settingsReducer(state, action) {
|
||||
const Settings = () => {
|
||||
const { settings, updateSettings, updateTheme } = useSettings();
|
||||
const { settingsModalVisible, setSettingsModalVisible } = useModalContext();
|
||||
const { setToast } = useToasts();
|
||||
const [state, dispatch] = useReducer(settingsReducer, initialState);
|
||||
const isInitialMount = useRef(true);
|
||||
const updateThemeTimeoutRef = useRef(null);
|
||||
@@ -71,7 +72,6 @@ const Settings = () => {
|
||||
const newTheme = state.localSettings.theme === 'dark' ? 'light' : 'dark';
|
||||
dispatch({ type: 'UPDATE_LOCAL_SETTINGS', payload: { theme: newTheme } });
|
||||
|
||||
// Debounce the theme update
|
||||
if (updateThemeTimeoutRef.current) {
|
||||
clearTimeout(updateThemeTimeoutRef.current);
|
||||
}
|
||||
@@ -84,20 +84,23 @@ const Settings = () => {
|
||||
try {
|
||||
await updateSettings(state.localSettings);
|
||||
dispatch({ type: 'MARK_SAVED' });
|
||||
setToast({ text: 'Settings saved successfully', type: 'success' });
|
||||
notifications.show({
|
||||
message: 'Settings saved successfully',
|
||||
color: 'green',
|
||||
});
|
||||
setSettingsModalVisible(false);
|
||||
} catch (error) {
|
||||
console.error('Failed to save settings:', error);
|
||||
setToast({
|
||||
text: 'Failed to save settings: ' + error.message,
|
||||
type: 'error',
|
||||
notifications.show({
|
||||
message: 'Failed to save settings: ' + error.message,
|
||||
color: 'red',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
if (state.hasUnsavedChanges) {
|
||||
updateTheme(state.initialSettings.theme); // Revert theme if not saved
|
||||
updateTheme(state.initialSettings.theme);
|
||||
dispatch({ type: 'RESET' });
|
||||
}
|
||||
setSettingsModalVisible(false);
|
||||
@@ -117,38 +120,41 @@ const Settings = () => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Modal visible={settingsModalVisible} onClose={handleClose}>
|
||||
<Modal.Title>
|
||||
Settings
|
||||
{state.hasUnsavedChanges && (
|
||||
<Dot type="warning" style={{ marginLeft: '8px' }} />
|
||||
)}
|
||||
</Modal.Title>
|
||||
<Modal.Content>
|
||||
<AppearanceSettings
|
||||
themeSettings={state.localSettings.theme}
|
||||
onThemeChange={handleThemeChange}
|
||||
/>
|
||||
<Spacer h={1} />
|
||||
<EditorSettings
|
||||
autoSave={state.localSettings.autoSave}
|
||||
onAutoSaveChange={(value) => handleInputChange('autoSave', value)}
|
||||
/>
|
||||
<Spacer h={1} />
|
||||
<GitSettings
|
||||
gitEnabled={state.localSettings.gitEnabled}
|
||||
gitUrl={state.localSettings.gitUrl}
|
||||
gitUser={state.localSettings.gitUser}
|
||||
gitToken={state.localSettings.gitToken}
|
||||
gitAutoCommit={state.localSettings.gitAutoCommit}
|
||||
gitCommitMsgTemplate={state.localSettings.gitCommitMsgTemplate}
|
||||
onInputChange={handleInputChange}
|
||||
/>
|
||||
</Modal.Content>
|
||||
<Modal.Action passive onClick={handleClose}>
|
||||
Cancel
|
||||
</Modal.Action>
|
||||
<Modal.Action onClick={handleSubmit}>Save Changes</Modal.Action>
|
||||
<Modal
|
||||
opened={settingsModalVisible}
|
||||
onClose={handleClose}
|
||||
title="Settings"
|
||||
centered
|
||||
size="lg"
|
||||
>
|
||||
{state.hasUnsavedChanges && (
|
||||
<Badge color="yellow" variant="light" mb="md">
|
||||
Unsaved Changes
|
||||
</Badge>
|
||||
)}
|
||||
<AppearanceSettings
|
||||
themeSettings={state.localSettings.theme}
|
||||
onThemeChange={handleThemeChange}
|
||||
/>
|
||||
<EditorSettings
|
||||
autoSave={state.localSettings.autoSave}
|
||||
onAutoSaveChange={(value) => handleInputChange('autoSave', value)}
|
||||
/>
|
||||
<GitSettings
|
||||
gitEnabled={state.localSettings.gitEnabled}
|
||||
gitUrl={state.localSettings.gitUrl}
|
||||
gitUser={state.localSettings.gitUser}
|
||||
gitToken={state.localSettings.gitToken}
|
||||
gitAutoCommit={state.localSettings.gitAutoCommit}
|
||||
gitCommitMsgTemplate={state.localSettings.gitCommitMsgTemplate}
|
||||
onInputChange={handleInputChange}
|
||||
/>
|
||||
<Group justify="flex-end" mt="xl">
|
||||
<Button variant="default" onClick={handleClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleSubmit}>Save Changes</Button>
|
||||
</Group>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import React from 'react';
|
||||
import { Text, Toggle } from '@geist-ui/core';
|
||||
import { Text, Switch, Stack } from '@mantine/core';
|
||||
|
||||
const AppearanceSettings = ({ themeSettings, onThemeChange }) => {
|
||||
return (
|
||||
<div className="setting-group">
|
||||
<Text h4>Appearance</Text>
|
||||
<div className="setting-item">
|
||||
<Text>Dark Mode</Text>
|
||||
<Toggle checked={themeSettings === 'dark'} onChange={onThemeChange} />
|
||||
</div>
|
||||
</div>
|
||||
<Stack spacing="xs">
|
||||
<Text fw={500} size="lg">
|
||||
Appearance
|
||||
</Text>
|
||||
<Switch
|
||||
label="Dark Mode"
|
||||
checked={themeSettings === 'dark'}
|
||||
onChange={onThemeChange}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,25 +1,21 @@
|
||||
import React from 'react';
|
||||
import { Text, Toggle, Tooltip } from '@geist-ui/core';
|
||||
import { Text, Switch, Stack, Tooltip } from '@mantine/core';
|
||||
|
||||
const EditorSettings = ({ autoSave, onAutoSaveChange }) => {
|
||||
return (
|
||||
<div className="setting-group">
|
||||
<Text h4>Editor</Text>
|
||||
<div className="setting-item">
|
||||
<Text>Auto Save</Text>
|
||||
<Tooltip
|
||||
text="Auto Save feature is coming soon!"
|
||||
type="dark"
|
||||
placement="left"
|
||||
>
|
||||
<Toggle
|
||||
checked={autoSave}
|
||||
onChange={(e) => onAutoSaveChange(e.target.checked)}
|
||||
disabled
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<Stack spacing="xs" mt="md">
|
||||
<Text fw={500} size="lg">
|
||||
Editor
|
||||
</Text>
|
||||
<Tooltip label="Auto Save feature is coming soon!" position="left">
|
||||
<Switch
|
||||
label="Auto Save"
|
||||
checked={autoSave}
|
||||
onChange={(event) => onAutoSaveChange(event.currentTarget.checked)}
|
||||
disabled
|
||||
/>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Text, Toggle, Input, Spacer } from '@geist-ui/core';
|
||||
import { Text, Switch, TextInput, Stack, PasswordInput } from '@mantine/core';
|
||||
|
||||
const GitSettings = ({
|
||||
gitEnabled,
|
||||
@@ -11,60 +11,56 @@ const GitSettings = ({
|
||||
onInputChange,
|
||||
}) => {
|
||||
return (
|
||||
<div className="setting-group">
|
||||
<Text h4>Git Integration</Text>
|
||||
<div className="setting-item">
|
||||
<Text>Enable Git</Text>
|
||||
<Toggle
|
||||
checked={gitEnabled}
|
||||
onChange={(e) => onInputChange('gitEnabled', e.target.checked)}
|
||||
/>
|
||||
</div>
|
||||
<div className={gitEnabled ? '' : 'disabled'}>
|
||||
<Input
|
||||
width="100%"
|
||||
label="Git URL"
|
||||
value={gitUrl}
|
||||
onChange={(e) => onInputChange('gitUrl', e.target.value)}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
<Spacer h={0.5} />
|
||||
<Input
|
||||
width="100%"
|
||||
label="Git Username"
|
||||
value={gitUser}
|
||||
onChange={(e) => onInputChange('gitUser', e.target.value)}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
<Spacer h={0.5} />
|
||||
<Input.Password
|
||||
width="100%"
|
||||
label="Git Token"
|
||||
value={gitToken}
|
||||
onChange={(e) => onInputChange('gitToken', e.target.value)}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
<Spacer h={0.5} />
|
||||
<div className="setting-item">
|
||||
<Text>Auto Commit</Text>
|
||||
<Toggle
|
||||
checked={gitAutoCommit}
|
||||
onChange={(e) => onInputChange('gitAutoCommit', e.target.checked)}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
</div>
|
||||
<Spacer h={0.5} />
|
||||
<Input
|
||||
width="100%"
|
||||
label="Commit Message Template"
|
||||
value={gitCommitMsgTemplate}
|
||||
onChange={(e) =>
|
||||
onInputChange('gitCommitMsgTemplate', e.target.value)
|
||||
}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Stack spacing="xs" mt="md">
|
||||
<Text fw={500} size="lg">
|
||||
Git Integration
|
||||
</Text>
|
||||
<Switch
|
||||
label="Enable Git"
|
||||
checked={gitEnabled}
|
||||
onChange={(event) =>
|
||||
onInputChange('gitEnabled', event.currentTarget.checked)
|
||||
}
|
||||
/>
|
||||
<TextInput
|
||||
label="Git URL"
|
||||
value={gitUrl}
|
||||
onChange={(event) => onInputChange('gitUrl', event.currentTarget.value)}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
<TextInput
|
||||
label="Git Username"
|
||||
value={gitUser}
|
||||
onChange={(event) =>
|
||||
onInputChange('gitUser', event.currentTarget.value)
|
||||
}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
<PasswordInput
|
||||
label="Git Token"
|
||||
value={gitToken}
|
||||
onChange={(event) =>
|
||||
onInputChange('gitToken', event.currentTarget.value)
|
||||
}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
<Switch
|
||||
label="Auto Commit"
|
||||
checked={gitAutoCommit}
|
||||
onChange={(event) =>
|
||||
onInputChange('gitAutoCommit', event.currentTarget.checked)
|
||||
}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
<TextInput
|
||||
label="Commit Message Template"
|
||||
value={gitCommitMsgTemplate}
|
||||
onChange={(event) =>
|
||||
onInputChange('gitCommitMsgTemplate', event.currentTarget.value)
|
||||
}
|
||||
disabled={!gitEnabled}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user