diff --git a/frontend/src/components/settings/git/ActionButtons.jsx b/frontend/src/components/settings/git/ActionButtons.jsx index 30c00ba..3ab84db 100644 --- a/frontend/src/components/settings/git/ActionButtons.jsx +++ b/frontend/src/components/settings/git/ActionButtons.jsx @@ -2,6 +2,37 @@ import React from 'react'; import {Loader, RotateCcw, Download, CheckCircle, Plus} from 'lucide-react'; import Tooltip from '../../ui/Tooltip'; +const ActionButton = ({ + onClick, + disabled, + loading, + icon, + text, + className, + disabledTooltip +}) => { + const baseClassName = + 'flex items-center px-4 py-2 text-white rounded-md transition-all duration-200 ease-in-out text-xs'; + const enabledClassName = `${baseClassName} ${className} hover:opacity-80`; + const disabledClassName = `${baseClassName} ${className} opacity-50 cursor-not-allowed`; + + return ( + + + + ); +}; + const ActionButtons = ({ isDevMode, selectedOutgoingChanges, @@ -12,106 +43,67 @@ const ActionButtons = ({ onStageSelected, onCommitSelected, onRevertSelected, - onPullSelected, - getStageButtonTooltip, - getCommitButtonTooltip, - getRevertButtonTooltip + onPullSelected }) => { + const canStage = + isDevMode && + selectedOutgoingChanges.length > 0 && + selectionType !== 'staged'; + const canCommit = + isDevMode && + selectedOutgoingChanges.length > 0 && + commitMessage.trim() && + selectionType !== 'unstaged'; + const canRevert = selectedOutgoingChanges.length > 0; + const canPull = selectedIncomingChanges.length > 0; + return ( -
+
{isDevMode && ( <> - {/* Stage */} - {selectedOutgoingChanges.length > 0 && - selectionType !== 'staged' && ( - - - - )} - {/* Commit */} - {selectedOutgoingChanges.length > 0 && - commitMessage.trim() && - selectionType !== 'unstaged' && ( - - - - )} + onStageSelected(selectedOutgoingChanges)} + disabled={!canStage} + loading={loadingAction === 'stage_selected'} + icon={} + text='Stage' + className='bg-green-600' + disabledTooltip='Select unstaged files to enable staging' + /> + + onCommitSelected( + selectedOutgoingChanges, + commitMessage + ) + } + disabled={!canCommit} + loading={loadingAction === 'commit_selected'} + icon={} + text='Commit' + className='bg-blue-600' + disabledTooltip='Select staged files and enter a commit message to enable committing' + /> )} - {/* Revert */} - {selectedOutgoingChanges.length > 0 && ( - - - - )} - {/* Pull */} - {selectedIncomingChanges.length > 0 && ( - - - - )} + onRevertSelected(selectedOutgoingChanges)} + disabled={!canRevert} + loading={loadingAction === 'revert_selected'} + icon={} + text='Revert' + className='bg-red-600' + disabledTooltip='Select files to revert' + /> + onPullSelected(selectedIncomingChanges)} + disabled={!canPull} + loading={loadingAction === 'pull_changes'} + icon={} + text='Pull' + className='bg-yellow-600' + disabledTooltip='Select incoming changes to pull' + />
); }; diff --git a/frontend/src/components/settings/git/StatusContainer.jsx b/frontend/src/components/settings/git/StatusContainer.jsx index a6526b3..e29393b 100644 --- a/frontend/src/components/settings/git/StatusContainer.jsx +++ b/frontend/src/components/settings/git/StatusContainer.jsx @@ -109,22 +109,46 @@ const StatusContainer = ({ } }, [status]); + const hasChanges = + status.incoming_changes.length > 0 || + status.outgoing_changes.length > 0; + return (
-
- -

- Sync Status: -

- {status.incoming_changes.length === 0 && - status.outgoing_changes.length === 0 ? ( - - {noChangesMessage} - - ) : ( - - Out of Date! - +
+
+ +

+ Sync Status: +

+ {!hasChanges ? ( + + {noChangesMessage} + + ) : ( + + Out of Date! + + )} +
+ {!hasChanges && ( +
+ +
)}
@@ -160,30 +184,36 @@ const StatusContainer = ({ /> )} - 0} - isDevMode={isDevMode} - /> + {hasChanges && ( + <> + 0} + isDevMode={isDevMode} + /> - +
+ +
+ + )}
); }; diff --git a/frontend/src/utils/messages.js b/frontend/src/utils/messages.js index 6100989..798fae2 100644 --- a/frontend/src/utils/messages.js +++ b/frontend/src/utils/messages.js @@ -14,18 +14,18 @@ export const statusLoadingMessages = [ ]; export const noChangesMessages = [ - 'No changes detected. Your regex is so precise, it could find a needle in a haystack... made of needles. ๐Ÿงต๐Ÿ”', - 'All quiet on the commit front. Your custom formats are so perfect, even perfectionists are jealous. ๐Ÿ†', - "No updates needed. Your media automation is running so smoothly, it's making butter jealous. ๐Ÿงˆ", - 'Zero modifications. Your torrent setup is seeding so efficiently, farmers are asking for advice. ๐ŸŒพ', - "No edits required. Your regex fu is so strong, it's bench-pressing parentheses for fun. ๐Ÿ’ช()", - 'Unchanged status. Your Plex library is so well-organized, librarians are taking notes. ๐Ÿ“š๐Ÿค“', - "No alterations found. Your file naming scheme is so consistent, it's bringing tears to OCD eyes. ๐Ÿ˜ข๐Ÿ‘€", - "All systems nominal. Your download queue is so orderly, it's making Marie Kondo question her career. ๐Ÿงนโœจ", - "No revisions necessary. Your automation scripts are so smart, they're solving captchas for fun. ๐Ÿค–๐Ÿงฉ", - 'Steady as she goes. Your media collection is so complete, Netflix is asking you for recommendations. ๐ŸŽฌ๐Ÿ‘‘' + 'All synced up! Smooth sailing ahead.', + "No changes detected. We're all good here.", + "Everything's in order. Carry on!", + 'Up to date and ready to go.', + 'All quiet on the regex front!', + 'Perfectly synced! Nice work.', + "No updates needed. You're all set.", + "Everything's hunky-dory in your repository.", + 'All good in the code neighborhood.', + 'Sync complete! Ship-Shape.' ]; -export const getRandomMessage = (messages) => { +export const getRandomMessage = messages => { return messages[Math.floor(Math.random() * messages.length)]; };