refactor: move branch functionality into repo container. Add some icons

This commit is contained in:
Sam Chau
2024-09-19 08:44:42 +09:30
parent 5c8c647be1
commit c1f90b3c37
3 changed files with 159 additions and 68 deletions

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react';
import React, {useState, useEffect, useRef} from 'react';
import {
getSettings,
getGitStatus,
@@ -8,15 +8,17 @@ import {
pullBranch,
checkDevMode
} from '../../api/api';
import {
Loader,
} from 'lucide-react';
import {Loader} from 'lucide-react';
import ViewBranches from './git/modal/ViewBranches';
import Alert from '../ui/Alert';
import ArrContainer from './arrs/ArrContainer';
import RepoContainer from './git/RepoContainer';
import StatusContainer from './git/StatusContainer';
import { statusLoadingMessages, noChangesMessages, getRandomMessage } from '../../utils/messages';
import {
statusLoadingMessages,
noChangesMessages,
getRandomMessage
} from '../../utils/messages';
const SettingsPage = () => {
const [settings, setSettings] = useState(null);
@@ -27,8 +29,8 @@ const SettingsPage = () => {
const [statusLoading, setStatusLoading] = useState(true);
const [statusLoadingMessage, setStatusLoadingMessage] = useState('');
const [noChangesMessage, setNoChangesMessage] = useState('');
const [activeTab, setActiveTab] = useState('git'); // New state for tab navigation
const tabsRef = useRef({}); // Ref for tabs
const [activeTab, setActiveTab] = useState('git'); // New state for tab navigation
const tabsRef = useRef({}); // Ref for tabs
useEffect(() => {
fetchSettings();
@@ -66,10 +68,14 @@ const SettingsPage = () => {
if (result.success) {
setChanges({
...result.data,
outgoing_changes: Array.isArray(result.data.outgoing_changes)
outgoing_changes: Array.isArray(
result.data.outgoing_changes
)
? result.data.outgoing_changes
: [],
incoming_changes: Array.isArray(result.data.incoming_changes)
incoming_changes: Array.isArray(
result.data.incoming_changes
)
? result.data.incoming_changes
: []
});
@@ -82,11 +88,11 @@ const SettingsPage = () => {
}
};
const handleTabChange = (tab) => {
const handleTabChange = tab => {
setActiveTab(tab);
};
const handleStageSelectedChanges = async (selectedChanges) => {
const handleStageSelectedChanges = async selectedChanges => {
setLoadingAction('stage_selected');
try {
const response = await addFiles(selectedChanges);
@@ -104,7 +110,10 @@ const SettingsPage = () => {
}
};
const handleCommitSelectedChanges = async (selectedChanges, commitMessage) => {
const handleCommitSelectedChanges = async (
selectedChanges,
commitMessage
) => {
setLoadingAction('commit_selected');
try {
const response = await pushFiles(selectedChanges, commitMessage);
@@ -115,33 +124,43 @@ const SettingsPage = () => {
Alert.error(response.error);
}
} catch (error) {
Alert.error('An unexpected error occurred while committing changes.');
Alert.error(
'An unexpected error occurred while committing changes.'
);
console.error('Error committing changes:', error);
} finally {
setLoadingAction('');
}
};
const handleRevertSelectedChanges = async (selectedChanges) => {
const handleRevertSelectedChanges = async selectedChanges => {
setLoadingAction('revert_selected');
try {
const response = await Promise.all(selectedChanges.map(filePath => revertFile(filePath)));
const response = await Promise.all(
selectedChanges.map(filePath => revertFile(filePath))
);
const allSuccessful = response.every(res => res.success);
if (allSuccessful) {
await fetchGitStatus();
Alert.success('Selected changes have been reverted successfully.');
Alert.success(
'Selected changes have been reverted successfully.'
);
} else {
Alert.error('Some changes could not be reverted. Please try again.');
Alert.error(
'Some changes could not be reverted. Please try again.'
);
}
} catch (error) {
Alert.error('An unexpected error occurred while reverting changes.');
Alert.error(
'An unexpected error occurred while reverting changes.'
);
console.error('Error reverting changes:', error);
} finally {
setLoadingAction('');
}
};
const handlePullSelectedChanges = async (selectedChanges) => {
const handlePullSelectedChanges = async selectedChanges => {
setLoadingAction('pull_changes');
try {
const response = await pullBranch(changes.branch, selectedChanges);
@@ -161,51 +180,62 @@ const SettingsPage = () => {
return (
<div>
<nav className="flex space-x-4">
<nav className='flex space-x-4'>
<div
onClick={() => handleTabChange('git')}
ref={(el) => (tabsRef.current['git'] = el)}
ref={el => (tabsRef.current['git'] = el)}
className={`cursor-pointer px-3 py-2 rounded-md text-sm font-medium mb-4 ${
activeTab === 'git' ? 'text-white dark:bg-gray-600 border border-gray-200 dark:border-gray-600' : 'text-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700'
}`}
>
activeTab === 'git'
? 'text-white dark:bg-gray-600 border border-gray-200 dark:border-gray-600'
: 'text-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700'
}`}>
Git Settings
</div>
<div
onClick={() => handleTabChange('app')}
ref={(el) => (tabsRef.current['app'] = el)}
ref={el => (tabsRef.current['app'] = el)}
className={`cursor-pointer px-3 py-2 rounded-md text-sm font-medium mb-4 ${
activeTab === 'app' ? 'text-white dark:bg-gray-600 border border-gray-200 dark:border-gray-600' : 'text-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700'
}`}
>
activeTab === 'app'
? 'text-white dark:bg-gray-600 border border-gray-200 dark:border-gray-600'
: 'text-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700'
}`}>
App Settings
</div>
</nav>
{activeTab === 'git' && (
<>
<RepoContainer
settings={settings}
setSettings={setSettings}
fetchGitStatus={fetchGitStatus}
status={changes}
isDevMode={isDevMode}
/>
{settings && (
<div className="space-y-4">
<div className='space-y-4'>
{statusLoading ? (
<div className="flex items-left justify-left dark:bg-gray-800 p-4 rounded-md border border-gray-200 dark:border-gray-700 text-sm">
<Loader className="animate-spin mr-2" size={16} />
<span className="text-gray-300">{statusLoadingMessage}</span>
<div className='flex items-left justify-left dark:bg-gray-800 p-4 rounded-md border border-gray-200 dark:border-gray-700 text-sm'>
<Loader
className='animate-spin mr-2'
size={16}
/>
<span className='text-gray-300'>
{statusLoadingMessage}
</span>
</div>
) : (
) : (
<StatusContainer
status={changes}
isDevMode={isDevMode}
onViewBranches={() => setShowBranchModal(true)}
onStageSelected={handleStageSelectedChanges}
onCommitSelected={handleCommitSelectedChanges}
onRevertSelected={handleRevertSelectedChanges}
onCommitSelected={
handleCommitSelectedChanges
}
onRevertSelected={
handleRevertSelectedChanges
}
onPullSelected={handlePullSelectedChanges}
loadingAction={loadingAction}
/>
@@ -228,7 +258,7 @@ const SettingsPage = () => {
{activeTab === 'app' && (
<>
<h2 className="text-xl font-bold mb-4 text-gray-100 mt-3">
<h2 className='text-xl font-bold mb-4 text-gray-100 mt-3'>
App Settings
</h2>
<ArrContainer />

View File

@@ -1,22 +1,38 @@
import React, { useState } from 'react';
import { Loader, Unlink, Link } from 'lucide-react';
import React, {useState} from 'react';
import {
Loader,
Unlink,
Link,
GitBranch,
Eye,
GitFork,
GitCommit
} from 'lucide-react';
import Tooltip from '../../ui/Tooltip';
import { unlinkRepo, getSettings } from '../../../api/api';
import {unlinkRepo, getSettings} from '../../../api/api';
import Alert from '../../ui/Alert';
import LinkRepo from './modal/LinkRepo';
import UnlinkRepo from './modal/UnlinkRepo';
import ViewBranches from './modal/ViewBranches';
const RepoContainer = ({ settings, setSettings, fetchGitStatus }) => {
const RepoContainer = ({
settings,
setSettings,
fetchGitStatus,
status,
isDevMode
}) => {
const [loadingAction, setLoadingAction] = useState('');
const [showLinkModal, setShowLinkModal] = useState(false);
const [showUnlinkRepo, setShowUnlinkRepo] = useState(false);
const [showBranchModal, setShowBranchModal] = useState(false);
const handleLinkRepo = () => {
setLoadingAction('link_repo');
setShowLinkModal(true);
};
const handleUnlinkRepo = async (removeFiles) => {
const handleUnlinkRepo = async removeFiles => {
setLoadingAction('unlink_repo');
try {
const response = await unlinkRepo(removeFiles);
@@ -64,25 +80,43 @@ const RepoContainer = ({ settings, setSettings, fetchGitStatus }) => {
<div className='dark:bg-gray-800 border border-gray-200 dark:border-gray-700 p-5 rounded-lg shadow-md'>
<div className='flex flex-col sm:flex-row items-start sm:items-center justify-between space-y-3 sm:space-y-0'>
<div className='flex flex-col sm:flex-row sm:items-center'>
<h3 className='text-sm font-semibold text-gray-100 mr-2 mb-1 sm:mb-0'>
{settings ? 'Connected Repository:' : 'Repository:'}
</h3>
<div className='flex items-center'>
<GitFork className='mr-2 text-blue-400' size={14} />
<h3 className='text-m font-semibold text-gray-100 mr-2 mb-1 sm:mb-0'>
{settings
? 'Connected Repository:'
: 'Repository:'}
</h3>
</div>
{settings ? (
<a
href={settings.gitRepo}
target='_blank'
rel='noopener noreferrer'
className='text-blue-400 hover:text-blue-300 transition-colors text-sm font-medium truncate max-w-xs sm:max-w-md'>
className='text-blue-400 hover:text-blue-300 transition-colors text-m font-medium truncate max-w-xs sm:max-w-md'>
{settings.gitRepo}
</a>
) : (
<span className='text-gray-400 text-sm'>No repository linked</span>
<span className='text-gray-400 text-sm'>
No repository linked
</span>
)}
</div>
<Tooltip content={settings ? 'Unlink Repository' : 'Link Repository'}>
<Tooltip
content={
settings ? 'Unlink Repository' : 'Link Repository'
}>
<button
onClick={settings ? () => setShowUnlinkRepo(true) : handleLinkRepo}
className={`flex items-center px-4 py-2 ${settings ? 'bg-red-600 hover:bg-red-700' : 'bg-blue-600 hover:bg-blue-700'} text-white rounded-md transition-colors duration-200 ease-in-out text-sm font-medium shadow-sm`}
onClick={
settings
? () => setShowUnlinkRepo(true)
: handleLinkRepo
}
className={`flex items-center px-4 py-2 ${
settings
? 'bg-red-600 hover:bg-red-700'
: 'bg-blue-600 hover:bg-blue-700'
} text-white rounded-md transition-colors duration-200 ease-in-out text-m font-medium shadow-sm`}
disabled={loadingAction !== ''}>
{settings ? (
<Unlink size={16} className='mr-2' />
@@ -93,6 +127,39 @@ const RepoContainer = ({ settings, setSettings, fetchGitStatus }) => {
</button>
</Tooltip>
</div>
{settings && (
<div className='flex items-center justify-between mt-4'>
<div className='flex items-center'>
<GitCommit
className='mr-2 text-green-400'
size={14}
/>
<h3 className='text-m font-semibold text-gray-100 mr-2'>
Current Branch:
</h3>
{status ? (
<span className='text-blue-400 hover:text-blue-300 transition-colors text-m font-medium'>
{status.branch}
</span>
) : (
<span className='text-gray-400 text-m flex items-center'>
<Loader
className='animate-spin mr-2'
size={14}
/>
Loading branch information...
</span>
)}
</div>
<button
onClick={() => setShowBranchModal(true)}
className='flex items-center px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors duration-200 ease-in-out text-m'
disabled={!status}>
<Eye size={14} className='mr-2' />
View Branches
</button>
</div>
)}
</div>
<LinkRepo
isOpen={showLinkModal}
@@ -104,6 +171,16 @@ const RepoContainer = ({ settings, setSettings, fetchGitStatus }) => {
onClose={closeUnlinkModal}
onSubmit={handleUnlinkRepo}
/>
{settings && status && (
<ViewBranches
isOpen={showBranchModal}
onClose={() => setShowBranchModal(false)}
repoUrl={settings.gitRepo}
currentBranch={status.branch}
onBranchChange={fetchGitStatus}
isDevMode={isDevMode}
/>
)}
</div>
);
};

View File

@@ -5,8 +5,7 @@ import {
RotateCcw,
Download,
CheckCircle,
Plus,
Eye
Plus
} from 'lucide-react';
import ChangeTable from './ChangeTable';
import Tooltip from '../../ui/Tooltip';
@@ -15,7 +14,6 @@ import CommitSection from './CommitMessage';
const StatusContainer = ({
status,
isDevMode,
onViewBranches,
onStageSelected,
onCommitSelected,
onRevertSelected,
@@ -112,20 +110,6 @@ const StatusContainer = ({
<h3 className='text-sm font-semibold text-gray-100 mb-2'>
Git Status
</h3>
<div className='flex items-center justify-between mb-4'>
<div className='flex items-center'>
<GitBranch className='mr-2 text-green-400' size={14} />
<span className='text-gray-200 text-sm'>
Current Branch: {status.branch}
</span>
</div>
<button
onClick={onViewBranches}
className='flex items-center px-3 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors duration-200 ease-in-out text-xs'>
<Eye size={14} className='mr-2' />
View Branches
</button>
</div>
{status.incoming_changes.length > 0 && (
<ChangeTable