mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-06 16:04:23 +00:00
Initial git settings on frontend
This commit is contained in:
@@ -20,7 +20,7 @@ func SetupRoutes(r chi.Router, db *db.DB, fs *filesystem.FileSystem) {
|
|||||||
r.Delete("/*", DeleteFile(fs))
|
r.Delete("/*", DeleteFile(fs))
|
||||||
})
|
})
|
||||||
r.Route("/git", func(r chi.Router) {
|
r.Route("/git", func(r chi.Router) {
|
||||||
r.Post("commit", StageCommitAndPush(fs))
|
r.Post("/commit", StageCommitAndPush(fs))
|
||||||
r.Post("/pull", PullChanges(fs))
|
r.Post("/pull", PullChanges(fs))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import (
|
|||||||
type UserSettings struct {
|
type UserSettings struct {
|
||||||
Theme string `json:"theme" validate:"oneof=light dark"`
|
Theme string `json:"theme" validate:"oneof=light dark"`
|
||||||
AutoSave bool `json:"autoSave"`
|
AutoSave bool `json:"autoSave"`
|
||||||
GitEnabled bool `json:"git_enabled"`
|
GitEnabled bool `json:"gitEnabled"`
|
||||||
GitURL string `json:"git_url" validate:"required_with=GitEnabled"`
|
GitURL string `json:"gitUrl" validate:"required_with=GitEnabled"`
|
||||||
GitUser string `json:"git_user" validate:"required_with=GitEnabled"`
|
GitUser string `json:"gitUser" validate:"required_with=GitEnabled"`
|
||||||
GitToken string `json:"git_token" validate:"required_with=GitEnabled"`
|
GitToken string `json:"gitToken" validate:"required_with=GitEnabled"`
|
||||||
GitAutoCommit bool `json:"git_auto_commit"`
|
GitAutoCommit bool `json:"gitAutoCommit"`
|
||||||
GitCommitMsgTemplate string `json:"git_commit_msg_template"`
|
GitCommitMsgTemplate string `json:"gitCommitMsgTemplate"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
|
|||||||
@@ -1,26 +1,72 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import { Modal, Text, Toggle, Tooltip, Spacer, useTheme, useToasts } from '@geist-ui/core';
|
import { Modal, Text, Toggle, Input, Spacer, useTheme, Button, Dot, useToasts } from '@geist-ui/core';
|
||||||
import { saveUserSettings } from '../services/api';
|
import { saveUserSettings, fetchUserSettings } from '../services/api';
|
||||||
|
|
||||||
const Settings = ({ visible, onClose, currentTheme, onThemeChange }) => {
|
const Settings = ({ visible, onClose, currentTheme, onThemeChange }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [autoSave, setAutoSave] = useState(false);
|
|
||||||
const userId = 1;
|
|
||||||
const { setToast } = useToasts();
|
const { setToast } = useToasts();
|
||||||
|
const [settings, setSettings] = useState({
|
||||||
|
autoSave: false,
|
||||||
|
gitEnabled: false,
|
||||||
|
gitUrl: '',
|
||||||
|
gitUser: '',
|
||||||
|
gitToken: '',
|
||||||
|
gitAutoCommit: false,
|
||||||
|
gitCommitMsgTemplate: '',
|
||||||
|
});
|
||||||
|
const [themeSettings, setThemeSettings] = useState(currentTheme);
|
||||||
|
const [originalSettings, setOriginalSettings] = useState({});
|
||||||
|
const [originalTheme, setOriginalTheme] = useState(currentTheme);
|
||||||
|
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
|
||||||
|
const [isInitialized, setIsInitialized] = useState(false);
|
||||||
|
|
||||||
|
const loadSettings = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
const userSettings = await fetchUserSettings(1); // Assuming user ID 1 for now
|
||||||
|
const { theme, ...otherSettings } = userSettings.settings;
|
||||||
|
setSettings(otherSettings);
|
||||||
|
setThemeSettings(theme);
|
||||||
|
setOriginalSettings(otherSettings);
|
||||||
|
setOriginalTheme(theme);
|
||||||
|
setHasUnsavedChanges(false);
|
||||||
|
setIsInitialized(true);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load user settings:', error);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isInitialized) {
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
}, [isInitialized, loadSettings]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const settingsChanged = JSON.stringify(settings) !== JSON.stringify(originalSettings);
|
||||||
|
const themeChanged = themeSettings !== originalTheme;
|
||||||
|
setHasUnsavedChanges(settingsChanged || themeChanged);
|
||||||
|
}, [settings, themeSettings, originalSettings, originalTheme]);
|
||||||
|
|
||||||
|
const handleInputChange = (key, value) => {
|
||||||
|
setSettings(prev => ({ ...prev, [key]: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleThemeChange = () => {
|
||||||
|
const newTheme = themeSettings === 'dark' ? 'light' : 'dark';
|
||||||
|
setThemeSettings(newTheme);
|
||||||
|
onThemeChange(newTheme);
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
const savedSettings = await saveUserSettings({
|
await saveUserSettings({
|
||||||
userId: userId,
|
userId: 1, // Assuming user ID 1 for now
|
||||||
settings: {
|
settings: { ...settings, theme: themeSettings },
|
||||||
theme: currentTheme,
|
|
||||||
autoSave: autoSave
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
setOriginalSettings(settings);
|
||||||
|
setOriginalTheme(themeSettings);
|
||||||
|
setHasUnsavedChanges(false);
|
||||||
setToast({ text: 'Settings saved successfully', type: 'success' });
|
setToast({ text: 'Settings saved successfully', type: 'success' });
|
||||||
// Update local state with saved settings
|
|
||||||
setAutoSave(savedSettings.settings.autoSave);
|
|
||||||
onThemeChange(savedSettings.settings.theme);
|
|
||||||
onClose();
|
onClose();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to save settings:', error);
|
console.error('Failed to save settings:', error);
|
||||||
@@ -28,22 +74,21 @@ const Settings = ({ visible, onClose, currentTheme, onThemeChange }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleThemeChange = () => {
|
|
||||||
onThemeChange(currentTheme === 'light' ? 'dark' : 'light');
|
|
||||||
};
|
|
||||||
|
|
||||||
const disabledMessage = "This feature is not yet implemented";
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal visible={visible} onClose={onClose}>
|
<Modal visible={visible} onClose={onClose}>
|
||||||
<Modal.Title>Settings</Modal.Title>
|
<Modal.Title>
|
||||||
|
Settings
|
||||||
|
{hasUnsavedChanges && (
|
||||||
|
<Dot type="warning" style={{ marginLeft: '8px' }} />
|
||||||
|
)}
|
||||||
|
</Modal.Title>
|
||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
<div className="setting-group">
|
<div className="setting-group">
|
||||||
<Text h4>Appearance</Text>
|
<Text h4>Appearance</Text>
|
||||||
<div className="setting-item">
|
<div className="setting-item">
|
||||||
<Text>Dark Mode</Text>
|
<Text>Dark Mode</Text>
|
||||||
<Toggle
|
<Toggle
|
||||||
checked={currentTheme === 'dark'}
|
checked={themeSettings === 'dark'}
|
||||||
onChange={handleThemeChange}
|
onChange={handleThemeChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,12 +96,66 @@ const Settings = ({ visible, onClose, currentTheme, onThemeChange }) => {
|
|||||||
<Spacer h={1} />
|
<Spacer h={1} />
|
||||||
<div className="setting-group">
|
<div className="setting-group">
|
||||||
<Text h4>Editor</Text>
|
<Text h4>Editor</Text>
|
||||||
<Tooltip text={disabledMessage} type="dark" placement="left">
|
<div className="setting-item">
|
||||||
<div className="setting-item disabled">
|
|
||||||
<Text>Auto Save</Text>
|
<Text>Auto Save</Text>
|
||||||
<Toggle disabled/>
|
<Toggle
|
||||||
|
checked={settings.autoSave}
|
||||||
|
onChange={(e) => handleInputChange('autoSave', e.target.checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Spacer h={1} />
|
||||||
|
<div className="setting-group">
|
||||||
|
<Text h4>Git Integration</Text>
|
||||||
|
<div className="setting-item">
|
||||||
|
<Text>Enable Git</Text>
|
||||||
|
<Toggle
|
||||||
|
checked={settings.gitEnabled}
|
||||||
|
onChange={(e) => handleInputChange('gitEnabled', e.target.checked)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={settings.gitEnabled ? '' : 'disabled'}>
|
||||||
|
<Input
|
||||||
|
width="100%"
|
||||||
|
label="Git URL"
|
||||||
|
value={settings.gitUrl}
|
||||||
|
onChange={(e) => handleInputChange('gitUrl', e.target.value)}
|
||||||
|
disabled={!settings.gitEnabled}
|
||||||
|
/>
|
||||||
|
<Spacer h={0.5} />
|
||||||
|
<Input
|
||||||
|
width="100%"
|
||||||
|
label="Git Username"
|
||||||
|
value={settings.gitUser}
|
||||||
|
onChange={(e) => handleInputChange('gitUser', e.target.value)}
|
||||||
|
disabled={!settings.gitEnabled}
|
||||||
|
/>
|
||||||
|
<Spacer h={0.5} />
|
||||||
|
<Input.Password
|
||||||
|
width="100%"
|
||||||
|
label="Git Token"
|
||||||
|
value={settings.gitToken}
|
||||||
|
onChange={(e) => handleInputChange('gitToken', e.target.value)}
|
||||||
|
disabled={!settings.gitEnabled}
|
||||||
|
/>
|
||||||
|
<Spacer h={0.5} />
|
||||||
|
<div className="setting-item">
|
||||||
|
<Text>Auto Commit</Text>
|
||||||
|
<Toggle
|
||||||
|
checked={settings.gitAutoCommit}
|
||||||
|
onChange={(e) => handleInputChange('gitAutoCommit', e.target.checked)}
|
||||||
|
disabled={!settings.gitEnabled}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Spacer h={0.5} />
|
||||||
|
<Input
|
||||||
|
width="100%"
|
||||||
|
label="Commit Message Template"
|
||||||
|
value={settings.gitCommitMsgTemplate}
|
||||||
|
onChange={(e) => handleInputChange('gitCommitMsgTemplate', e.target.value)}
|
||||||
|
disabled={!settings.gitEnabled}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
<Modal.Action passive onClick={onClose}>Cancel</Modal.Action>
|
<Modal.Action passive onClick={onClose}>Cancel</Modal.Action>
|
||||||
|
|||||||
@@ -70,8 +70,7 @@ export const saveUserSettings = async (settings) => {
|
|||||||
throw new Error(errorData?.message || `HTTP error! status: ${response.status}`);
|
throw new Error(errorData?.message || `HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const savedSettings = await response.json();
|
return await response.json();
|
||||||
return savedSettings;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error saving user settings:', error);
|
console.error('Error saving user settings:', error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
Reference in New Issue
Block a user