From 9125cbdad311f18e267a17bfd385c98782fac9f3 Mon Sep 17 00:00:00 2001 From: LordMathis Date: Sun, 18 May 2025 12:21:18 +0200 Subject: [PATCH] Migrate workspace settings to ts --- ...ordionControl.jsx => AccordionControl.tsx} | 6 +- ...nceSettings.jsx => AppearanceSettings.tsx} | 17 +++- ...oneSettings.jsx => DangerZoneSettings.tsx} | 6 +- ...{EditorSettings.jsx => EditorSettings.tsx} | 9 +- ...eneralSettings.jsx => GeneralSettings.tsx} | 15 +++- .../{GitSettings.jsx => GitSettings.tsx} | 17 +++- ...paceSettings.jsx => WorkspaceSettings.tsx} | 90 ++++++++++++------- app/src/types/workspace.ts | 6 ++ 8 files changed, 118 insertions(+), 48 deletions(-) rename app/src/components/settings/{AccordionControl.jsx => AccordionControl.tsx} (58%) rename app/src/components/settings/workspace/{AppearanceSettings.jsx => AppearanceSettings.tsx} (54%) rename app/src/components/settings/workspace/{DangerZoneSettings.jsx => DangerZoneSettings.tsx} (87%) rename app/src/components/settings/workspace/{EditorSettings.jsx => EditorSettings.tsx} (79%) rename app/src/components/settings/workspace/{GeneralSettings.jsx => GeneralSettings.tsx} (60%) rename app/src/components/settings/workspace/{GitSettings.jsx => GitSettings.tsx} (91%) rename app/src/components/settings/workspace/{WorkspaceSettings.jsx => WorkspaceSettings.tsx} (73%) diff --git a/app/src/components/settings/AccordionControl.jsx b/app/src/components/settings/AccordionControl.tsx similarity index 58% rename from app/src/components/settings/AccordionControl.jsx rename to app/src/components/settings/AccordionControl.tsx index 03cd02e..b366554 100644 --- a/app/src/components/settings/AccordionControl.jsx +++ b/app/src/components/settings/AccordionControl.tsx @@ -1,7 +1,11 @@ import React from 'react'; import { Accordion, Title } from '@mantine/core'; -const AccordionControl = ({ children }) => ( +interface AccordionControlProps { + children: React.ReactNode; +} + +const AccordionControl: React.FC = ({ children }) => ( {children} diff --git a/app/src/components/settings/workspace/AppearanceSettings.jsx b/app/src/components/settings/workspace/AppearanceSettings.tsx similarity index 54% rename from app/src/components/settings/workspace/AppearanceSettings.jsx rename to app/src/components/settings/workspace/AppearanceSettings.tsx index 79e2055..a695c5b 100644 --- a/app/src/components/settings/workspace/AppearanceSettings.jsx +++ b/app/src/components/settings/workspace/AppearanceSettings.tsx @@ -1,12 +1,21 @@ import React from 'react'; -import { Text, Switch, Group, Box, Title } from '@mantine/core'; +import { Text, Switch, Group, Box } from '@mantine/core'; import { useWorkspace } from '../../../contexts/WorkspaceContext'; +import { Theme } from '@/types/theme'; -const AppearanceSettings = ({ themeSettings, onThemeChange }) => { +interface AppearanceSettingsProps { + themeSettings?: Theme; + onThemeChange: (newTheme: Theme) => void; +} + +const AppearanceSettings: React.FC = ({ + themeSettings, + onThemeChange, +}) => { const { colorScheme, updateColorScheme } = useWorkspace(); - const handleThemeChange = () => { - const newTheme = colorScheme === 'dark' ? 'light' : 'dark'; + const handleThemeChange = (): void => { + const newTheme = colorScheme === 'dark' ? Theme.Light : Theme.Dark; updateColorScheme(newTheme); onThemeChange(newTheme); }; diff --git a/app/src/components/settings/workspace/DangerZoneSettings.jsx b/app/src/components/settings/workspace/DangerZoneSettings.tsx similarity index 87% rename from app/src/components/settings/workspace/DangerZoneSettings.jsx rename to app/src/components/settings/workspace/DangerZoneSettings.tsx index dbc0e30..94a9f3d 100644 --- a/app/src/components/settings/workspace/DangerZoneSettings.jsx +++ b/app/src/components/settings/workspace/DangerZoneSettings.tsx @@ -4,13 +4,13 @@ import DeleteWorkspaceModal from '../../modals/workspace/DeleteWorkspaceModal'; import { useWorkspace } from '../../../contexts/WorkspaceContext'; import { useModalContext } from '../../../contexts/ModalContext'; -const DangerZoneSettings = () => { +const DangerZoneSettings: React.FC = () => { const { currentWorkspace, workspaces, deleteCurrentWorkspace } = useWorkspace(); const { setSettingsModalVisible } = useModalContext(); - const [deleteModalOpened, setDeleteModalOpened] = useState(false); + const [deleteModalOpened, setDeleteModalOpened] = useState(false); - const handleDelete = async () => { + const handleDelete = async (): Promise => { await deleteCurrentWorkspace(); setDeleteModalOpened(false); setSettingsModalVisible(false); diff --git a/app/src/components/settings/workspace/EditorSettings.jsx b/app/src/components/settings/workspace/EditorSettings.tsx similarity index 79% rename from app/src/components/settings/workspace/EditorSettings.jsx rename to app/src/components/settings/workspace/EditorSettings.tsx index 13a76d2..62b58f9 100644 --- a/app/src/components/settings/workspace/EditorSettings.jsx +++ b/app/src/components/settings/workspace/EditorSettings.tsx @@ -1,7 +1,14 @@ import React from 'react'; import { Text, Switch, Tooltip, Group, Box } from '@mantine/core'; -const EditorSettings = ({ +interface EditorSettingsProps { + autoSave: boolean; + showHiddenFiles: boolean; + onAutoSaveChange: (value: boolean) => void; + onShowHiddenFilesChange: (value: boolean) => void; +} + +const EditorSettings: React.FC = ({ autoSave, showHiddenFiles, onAutoSaveChange, diff --git a/app/src/components/settings/workspace/GeneralSettings.jsx b/app/src/components/settings/workspace/GeneralSettings.tsx similarity index 60% rename from app/src/components/settings/workspace/GeneralSettings.jsx rename to app/src/components/settings/workspace/GeneralSettings.tsx index 0ada3e9..83b4a8a 100644 --- a/app/src/components/settings/workspace/GeneralSettings.jsx +++ b/app/src/components/settings/workspace/GeneralSettings.tsx @@ -1,7 +1,16 @@ import React from 'react'; -import { Title, Box, TextInput, Text, Grid } from '@mantine/core'; +import { Box, TextInput, Text, Grid } from '@mantine/core'; +import { Workspace } from '@/types/workspace'; -const GeneralSettings = ({ name, onInputChange }) => { +interface GeneralSettingsProps { + name: string; + onInputChange: (key: keyof Workspace, value: string) => void; +} + +const GeneralSettings: React.FC = ({ + name, + onInputChange, +}) => { return ( @@ -10,7 +19,7 @@ const GeneralSettings = ({ name, onInputChange }) => { onInputChange('name', event.currentTarget.value) } diff --git a/app/src/components/settings/workspace/GitSettings.jsx b/app/src/components/settings/workspace/GitSettings.tsx similarity index 91% rename from app/src/components/settings/workspace/GitSettings.jsx rename to app/src/components/settings/workspace/GitSettings.tsx index 1c5867c..214beb5 100644 --- a/app/src/components/settings/workspace/GitSettings.jsx +++ b/app/src/components/settings/workspace/GitSettings.tsx @@ -8,8 +8,21 @@ import { Group, Grid, } from '@mantine/core'; +import { Workspace } from '@/types/workspace'; -const GitSettings = ({ +interface GitSettingsProps { + gitEnabled: boolean; + gitUrl: string; + gitUser: string; + gitToken: string; + gitAutoCommit: boolean; + gitCommitMsgTemplate: string; + gitCommitName: string; + gitCommitEmail: string; + onInputChange: (key: keyof Workspace, value: any) => void; +} + +const GitSettings: React.FC = ({ gitEnabled, gitUrl, gitUser, @@ -21,7 +34,7 @@ const GitSettings = ({ onInputChange, }) => { return ( - + Enable Git Repository diff --git a/app/src/components/settings/workspace/WorkspaceSettings.jsx b/app/src/components/settings/workspace/WorkspaceSettings.tsx similarity index 73% rename from app/src/components/settings/workspace/WorkspaceSettings.jsx rename to app/src/components/settings/workspace/WorkspaceSettings.tsx index 34bc7b8..d5d00a6 100644 --- a/app/src/components/settings/workspace/WorkspaceSettings.jsx +++ b/app/src/components/settings/workspace/WorkspaceSettings.tsx @@ -17,23 +17,35 @@ import GeneralSettings from './GeneralSettings'; import { useModalContext } from '../../../contexts/ModalContext'; import DangerZoneSettings from './DangerZoneSettings'; import AccordionControl from '../AccordionControl'; +import { SettingsActionType, SettingsAction } from '../../../types/settings'; +import { Workspace } from '../../../types/workspace'; -const initialState = { +// State and reducer for workspace settings +interface WorkspaceSettingsState { + localSettings: Partial; + initialSettings: Partial; + hasUnsavedChanges: boolean; +} + +const initialState: WorkspaceSettingsState = { localSettings: {}, initialSettings: {}, hasUnsavedChanges: false, }; -function settingsReducer(state, action) { +function settingsReducer( + state: WorkspaceSettingsState, + action: SettingsAction> +): WorkspaceSettingsState { switch (action.type) { - case 'INIT_SETTINGS': + case SettingsActionType.INIT_SETTINGS: return { ...state, - localSettings: action.payload, - initialSettings: action.payload, + localSettings: action.payload || {}, + initialSettings: action.payload || {}, hasUnsavedChanges: false, }; - case 'UPDATE_LOCAL_SETTINGS': + case SettingsActionType.UPDATE_LOCAL_SETTINGS: const newLocalSettings = { ...state.localSettings, ...action.payload }; const hasChanges = JSON.stringify(newLocalSettings) !== @@ -43,7 +55,7 @@ function settingsReducer(state, action) { localSettings: newLocalSettings, hasUnsavedChanges: hasChanges, }; - case 'MARK_SAVED': + case SettingsActionType.MARK_SAVED: return { ...state, initialSettings: state.localSettings, @@ -54,16 +66,16 @@ function settingsReducer(state, action) { } } -const WorkspaceSettings = () => { +const WorkspaceSettings: React.FC = () => { const { currentWorkspace, updateSettings } = useWorkspace(); const { settingsModalVisible, setSettingsModalVisible } = useModalContext(); const [state, dispatch] = useReducer(settingsReducer, initialState); - const isInitialMount = useRef(true); + const isInitialMount = useRef(true); useEffect(() => { - if (isInitialMount.current) { + if (isInitialMount.current && currentWorkspace) { isInitialMount.current = false; - const settings = { + const settings: Partial = { name: currentWorkspace.name, theme: currentWorkspace.theme, autoSave: currentWorkspace.autoSave, @@ -77,15 +89,21 @@ const WorkspaceSettings = () => { gitCommitName: currentWorkspace.gitCommitName, gitCommitEmail: currentWorkspace.gitCommitEmail, }; - dispatch({ type: 'INIT_SETTINGS', payload: settings }); + dispatch({ type: SettingsActionType.INIT_SETTINGS, payload: settings }); } }, [currentWorkspace]); - const handleInputChange = useCallback((key, value) => { - dispatch({ type: 'UPDATE_LOCAL_SETTINGS', payload: { [key]: value } }); - }, []); + const handleInputChange = useCallback( + (key: keyof Workspace, value: any): void => { + dispatch({ + type: SettingsActionType.UPDATE_LOCAL_SETTINGS, + payload: { [key]: value } as Partial, + }); + }, + [] + ); - const handleSubmit = async () => { + const handleSubmit = async (): Promise => { try { if (!state.localSettings.name?.trim()) { notifications.show({ @@ -96,7 +114,7 @@ const WorkspaceSettings = () => { } await updateSettings(state.localSettings); - dispatch({ type: 'MARK_SAVED' }); + dispatch({ type: SettingsActionType.MARK_SAVED }); notifications.show({ message: 'Settings saved successfully', color: 'green', @@ -105,7 +123,9 @@ const WorkspaceSettings = () => { } catch (error) { console.error('Failed to save settings:', error); notifications.show({ - message: 'Failed to save settings: ' + error.message, + message: + 'Failed to save settings: ' + + (error instanceof Error ? error.message : String(error)), color: 'red', }); } @@ -123,7 +143,7 @@ const WorkspaceSettings = () => { centered size="lg" > - + {state.hasUnsavedChanges && ( Unsaved Changes @@ -133,7 +153,7 @@ const WorkspaceSettings = () => { ({ + styles={(theme: any) => ({ control: { paddingTop: theme.spacing.md, paddingBottom: theme.spacing.md, @@ -162,7 +182,7 @@ const WorkspaceSettings = () => { General @@ -173,7 +193,7 @@ const WorkspaceSettings = () => { + onThemeChange={(newTheme: string) => handleInputChange('theme', newTheme) } /> @@ -184,12 +204,12 @@ const WorkspaceSettings = () => { Editor + autoSave={state.localSettings.autoSave || false} + onAutoSaveChange={(value: boolean) => handleInputChange('autoSave', value) } - showHiddenFiles={state.localSettings.showHiddenFiles} - onShowHiddenFilesChange={(value) => + showHiddenFiles={state.localSettings.showHiddenFiles || false} + onShowHiddenFilesChange={(value: boolean) => handleInputChange('showHiddenFiles', value) } /> @@ -200,14 +220,16 @@ const WorkspaceSettings = () => { Git Integration diff --git a/app/src/types/workspace.ts b/app/src/types/workspace.ts index 15ec4f2..83f780a 100644 --- a/app/src/types/workspace.ts +++ b/app/src/types/workspace.ts @@ -3,23 +3,29 @@ import { Theme } from './theme'; export interface WorkspaceSettings { theme: Theme; autoSave: boolean; + showHiddenFiles: boolean; gitEnabled: boolean; gitUrl: string; gitUser: string; gitToken: string; gitAutoCommit: boolean; gitCommitMsgTemplate: string; + gitCommitName: string; + gitCommitEmail: string; } export const DEFAULT_WORKSPACE_SETTINGS: WorkspaceSettings = { theme: Theme.Light, autoSave: false, + showHiddenFiles: false, gitEnabled: false, gitUrl: '', gitUser: '', gitToken: '', gitAutoCommit: false, gitCommitMsgTemplate: '${action} ${filename}', + gitCommitName: '', + gitCommitEmail: '', }; export interface Workspace extends WorkspaceSettings {