diff --git a/backend/app/arr/__init__.py b/backend/app/arr/__init__.py index d05c081..30dc1d8 100644 --- a/backend/app/arr/__init__.py +++ b/backend/app/arr/__init__.py @@ -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//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 diff --git a/frontend/src/api/arr.js b/frontend/src/api/arr.js index b899fe6..e2f7517 100644 --- a/frontend/src/api/arr.js +++ b/frontend/src/api/arr.js @@ -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}; + } +}; diff --git a/frontend/src/components/settings/arrs/ArrModal.jsx b/frontend/src/components/settings/arrs/ArrModal.jsx index c3788b4..c32a325 100644 --- a/frontend/src/components/settings/arrs/ArrModal.jsx +++ b/frontend/src/components/settings/arrs/ArrModal.jsx @@ -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 && ( + { + setShowSyncConfirm(false); + onSubmit(); + }} + title='Run Initial Sync' + width='md'> +
+

+ Would you like to run an initial sync now to get + started? +

+
+ + +
+
+
+ )} ); diff --git a/frontend/src/hooks/useArrModal.js b/frontend/src/hooks/useArrModal.js index 9088e5f..1a41aa1 100644 --- a/frontend/src/hooks/useArrModal.js +++ b/frontend/src/hooks/useArrModal.js @@ -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 }; };