feat: add manual sync functionality with confirmation modal in ArrModal component

This commit is contained in:
Sam Chau
2025-01-09 19:46:41 +10:30
parent 2c19df5503
commit fba319eee2
4 changed files with 125 additions and 4 deletions

View File

@@ -112,3 +112,39 @@ def handle_config(id):
except Exception as e:
logger.error(f"Error handling arr config {id}: {str(e)}")
return jsonify({'success': False, 'error': str(e)}), 400
@bp.route('/config/<int:id>/sync', methods=['POST', 'OPTIONS'])
@cross_origin()
def trigger_sync(id):
if request.method == 'OPTIONS':
return jsonify({}), 200
try:
# Get the config first
config_result = get_arr_config(id)
if not config_result.get('success'):
logger.error(f"Config not found for sync: {id}")
return jsonify({
'success': False,
'error': 'Configuration not found'
}), 404
config_data = config_result.get('data')
if not config_data:
logger.error(f"Invalid config data for sync: {id}")
return jsonify({
'success': False,
'error': 'Invalid configuration data'
}), 400
# Run the import
from .manager import run_import_for_config
run_import_for_config(config_data)
logger.debug(f"Manual sync triggered for arr config: {id}")
return jsonify({'success': True}), 200
except Exception as e:
logger.error(f"Error triggering sync for arr config {id}: {str(e)}")
return jsonify({'success': False, 'error': str(e)}), 400

View File

@@ -72,3 +72,18 @@ export const deleteArrConfig = async id => {
throw error;
}
};
export const triggerSync = async configId => {
try {
const response = await fetch(`/api/arr/config/${configId}/sync`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
return await response.json();
} catch (error) {
console.error('Error triggering sync:', error);
return {success: false, error: error.message};
}
};

View File

@@ -25,7 +25,10 @@ const ArrModal = ({isOpen, onClose, onSubmit, editingArr}) => {
handleTagInputKeyDown,
handleTestConnection,
handleSubmit,
handleDelete
handleDelete,
showSyncConfirm,
setShowSyncConfirm,
handleManualSync
} = useArrModal({isOpen, onSubmit, editingArr});
const arrTypes = [
@@ -444,6 +447,43 @@ const ArrModal = ({isOpen, onClose, onSubmit, editingArr}) => {
onDataToggle={handleDataToggle}
error={errors.data_to_sync}
/>
{showSyncConfirm && (
<Modal
isOpen={showSyncConfirm}
onClose={() => {
setShowSyncConfirm(false);
onSubmit();
}}
title='Run Initial Sync'
width='md'>
<div className='space-y-4'>
<p className='text-gray-700 dark:text-gray-300'>
Would you like to run an initial sync now to get
started?
</p>
<div className='flex justify-end space-x-3'>
<button
type='button'
onClick={() => {
setShowSyncConfirm(false);
onSubmit();
}}
className='px-3 py-2 text-sm rounded-lg bg-gray-200 hover:bg-gray-300
dark:bg-gray-700 dark:hover:bg-gray-600
text-gray-700 dark:text-gray-200 font-medium transition-colors'>
Skip
</button>
<button
type='button'
onClick={handleManualSync}
className='px-3 py-2 text-sm rounded-lg bg-blue-600 hover:bg-blue-700
text-white font-medium transition-colors'>
Start Sync
</button>
</div>
</div>
</Modal>
)}
</form>
</Modal>
);

View File

@@ -4,7 +4,8 @@ import {
pingService,
saveArrConfig,
updateArrConfig,
deleteArrConfig
deleteArrConfig,
triggerSync
} from '@api/arr';
import {Profiles, CustomFormats} from '@api/data';
import Alert from '@ui/Alert';
@@ -38,6 +39,7 @@ export const useArrModal = ({isOpen, onSubmit, editingArr}) => {
const [saveConfirm, setSaveConfirm] = useState(false);
const [testConfirm, setTestConfirm] = useState(false);
const [isDataDrawerOpen, setIsDataDrawerOpen] = useState(false);
const [showSyncConfirm, setShowSyncConfirm] = useState(false);
useEffect(() => {
if (editingArr) {
@@ -214,10 +216,17 @@ export const useArrModal = ({isOpen, onSubmit, editingArr}) => {
editingArr ? 'updated' : 'saved'
} successfully`
);
onSubmit();
// If it's not a manual sync method, show the sync confirmation
if (formData.sync_method !== 'manual') {
setShowSyncConfirm(true);
} else {
onSubmit();
}
}
} catch (error) {
Alert.error('Failed to save configuration');
onSubmit();
}
setSaveConfirm(false);
} else {
@@ -226,6 +235,24 @@ export const useArrModal = ({isOpen, onSubmit, editingArr}) => {
}
};
const handleManualSync = async () => {
try {
const configId = editingArr ? editingArr.id : result.id;
const syncResult = await triggerSync(configId);
if (syncResult.success) {
Alert.success('Manual sync complete!');
} else {
Alert.error(syncResult.error || 'Failed to start manual sync');
}
} catch (error) {
Alert.error('Failed to start manual sync');
} finally {
setShowSyncConfirm(false);
onSubmit();
}
};
const handleDelete = async () => {
if (deleteConfirm) {
try {
@@ -346,6 +373,9 @@ export const useArrModal = ({isOpen, onSubmit, editingArr}) => {
handleTagInputKeyDown,
handleTestConnection,
handleSubmit,
handleDelete
handleDelete,
showSyncConfirm,
setShowSyncConfirm,
handleManualSync
};
};