mirror of
https://github.com/Dictionarry-Hub/profilarr.git
synced 2026-02-01 15:20:49 +01:00
fix: ensure data_to_sync has a safe structure and improve sync method handling
This commit is contained in:
@@ -39,6 +39,33 @@ const ArrModal = ({isOpen, onClose, onSubmit, editingArr}) => {
|
||||
{value: 'schedule', label: 'Scheduled'}
|
||||
];
|
||||
|
||||
// Ensure data_to_sync always has the required structure
|
||||
const safeSelectedData = {
|
||||
profiles: formData.data_to_sync?.profiles || [],
|
||||
customFormats: formData.data_to_sync?.customFormats || []
|
||||
};
|
||||
|
||||
// Handle sync method change
|
||||
const handleSyncMethodChange = e => {
|
||||
const newMethod = e.target.value;
|
||||
handleInputChange({
|
||||
target: {
|
||||
id: 'sync_method',
|
||||
value: newMethod
|
||||
}
|
||||
});
|
||||
|
||||
// Reset data_to_sync when switching to manual
|
||||
if (newMethod === 'manual') {
|
||||
handleInputChange({
|
||||
target: {
|
||||
id: 'data_to_sync',
|
||||
value: {profiles: [], customFormats: []}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const inputClasses = errorKey =>
|
||||
`w-full px-3 py-2 text-sm rounded-lg border ${
|
||||
errors[errorKey]
|
||||
@@ -261,7 +288,7 @@ const ArrModal = ({isOpen, onClose, onSubmit, editingArr}) => {
|
||||
<select
|
||||
id='sync_method'
|
||||
value={formData.sync_method}
|
||||
onChange={handleInputChange}
|
||||
onChange={handleSyncMethodChange}
|
||||
className={inputClasses('sync_method')}
|
||||
required>
|
||||
{syncMethods.map(m => (
|
||||
@@ -305,35 +332,35 @@ const ArrModal = ({isOpen, onClose, onSubmit, editingArr}) => {
|
||||
type='button'
|
||||
onClick={() => setIsDataDrawerOpen(true)}
|
||||
className='w-full px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-200
|
||||
bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700
|
||||
rounded-lg transition-colors
|
||||
border border-gray-200 dark:border-gray-700'>
|
||||
bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700
|
||||
rounded-lg transition-colors
|
||||
border border-gray-200 dark:border-gray-700'>
|
||||
<div className='flex flex-col space-y-2'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<span>Select Data to Sync</span>
|
||||
</div>
|
||||
{(formData.data_to_sync.profiles.length > 0 ||
|
||||
formData.data_to_sync.customFormats.length >
|
||||
{(safeSelectedData.profiles.length > 0 ||
|
||||
safeSelectedData.customFormats.length >
|
||||
0) && (
|
||||
<div className='flex flex-wrap gap-2'>
|
||||
{formData.data_to_sync.profiles.map(
|
||||
{safeSelectedData.profiles.map(
|
||||
profile => (
|
||||
<span
|
||||
key={profile}
|
||||
className='inline-flex items-center bg-blue-100 text-blue-800
|
||||
dark:bg-blue-900 dark:text-blue-300
|
||||
text-xs rounded px-2 py-1'>
|
||||
dark:bg-blue-900 dark:text-blue-300
|
||||
text-xs rounded px-2 py-1'>
|
||||
{profile}
|
||||
</span>
|
||||
)
|
||||
)}
|
||||
{formData.data_to_sync.customFormats.map(
|
||||
{safeSelectedData.customFormats.map(
|
||||
format => (
|
||||
<span
|
||||
key={format}
|
||||
className='inline-flex items-center bg-green-100 text-green-800
|
||||
dark:bg-green-900 dark:text-green-300
|
||||
text-xs rounded px-2 py-1'>
|
||||
dark:bg-green-900 dark:text-green-300
|
||||
text-xs rounded px-2 py-1'>
|
||||
{format}
|
||||
</span>
|
||||
)
|
||||
@@ -388,7 +415,7 @@ const ArrModal = ({isOpen, onClose, onSubmit, editingArr}) => {
|
||||
onClose={() => setIsDataDrawerOpen(false)}
|
||||
isLoading={isLoading}
|
||||
availableData={availableData}
|
||||
selectedData={formData.data_to_sync}
|
||||
selectedData={safeSelectedData}
|
||||
onDataToggle={handleDataToggle}
|
||||
error={errors.data_to_sync}
|
||||
/>
|
||||
|
||||
@@ -6,11 +6,15 @@ const DataSelectorModal = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
isLoading,
|
||||
availableData,
|
||||
selectedData,
|
||||
availableData = {profiles: [], customFormats: []},
|
||||
selectedData = {profiles: [], customFormats: []},
|
||||
onDataToggle,
|
||||
error
|
||||
}) => {
|
||||
// Ensure we have safe defaults for selectedData
|
||||
const profiles = selectedData?.profiles || [];
|
||||
const customFormats = selectedData?.customFormats || [];
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
@@ -32,38 +36,40 @@ const DataSelectorModal = ({
|
||||
Quality Profiles
|
||||
</h4>
|
||||
<span className='text-xs text-gray-500 dark:text-gray-400'>
|
||||
{selectedData.profiles.length} selected
|
||||
{profiles.length} selected
|
||||
</span>
|
||||
</div>
|
||||
<div className='grid grid-cols-2 gap-2'>
|
||||
{availableData.profiles.map(profile => (
|
||||
<label
|
||||
key={profile.file_name}
|
||||
className='flex items-center p-2 bg-white dark:bg-gray-800
|
||||
{(availableData?.profiles || []).map(
|
||||
profile => (
|
||||
<label
|
||||
key={profile.file_name}
|
||||
className='flex items-center p-2 bg-white dark:bg-gray-800
|
||||
hover:bg-gray-50 dark:hover:bg-gray-700
|
||||
rounded-lg cursor-pointer group transition-colors
|
||||
border border-gray-200 dark:border-gray-700'>
|
||||
<input
|
||||
type='checkbox'
|
||||
checked={selectedData.profiles.includes(
|
||||
profile.content.name
|
||||
)}
|
||||
onChange={() =>
|
||||
onDataToggle(
|
||||
'profiles',
|
||||
<input
|
||||
type='checkbox'
|
||||
checked={profiles.includes(
|
||||
profile.content.name
|
||||
)
|
||||
}
|
||||
className='rounded border-gray-300 text-blue-600
|
||||
)}
|
||||
onChange={() =>
|
||||
onDataToggle(
|
||||
'profiles',
|
||||
profile.content.name
|
||||
)
|
||||
}
|
||||
className='rounded border-gray-300 text-blue-600
|
||||
focus:ring-blue-500 focus:ring-offset-0'
|
||||
/>
|
||||
<span
|
||||
className='ml-3 text-sm text-gray-700 dark:text-gray-300
|
||||
/>
|
||||
<span
|
||||
className='ml-3 text-sm text-gray-700 dark:text-gray-300
|
||||
group-hover:text-gray-900 dark:group-hover:text-gray-100'>
|
||||
{profile.content.name}
|
||||
</span>
|
||||
</label>
|
||||
))}
|
||||
{profile.content.name}
|
||||
</span>
|
||||
</label>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -75,45 +81,46 @@ const DataSelectorModal = ({
|
||||
Custom Formats
|
||||
</h4>
|
||||
<span className='text-xs text-gray-500 dark:text-gray-400'>
|
||||
{selectedData.customFormats.length}{' '}
|
||||
selected
|
||||
{customFormats.length} selected
|
||||
</span>
|
||||
</div>
|
||||
<p className='text-xs text-gray-500 dark:text-gray-400'>
|
||||
Note: Custom formats used in selected
|
||||
quality profiles are automatically imported
|
||||
and do't need to be selected here.
|
||||
and don't need to be selected here.
|
||||
</p>
|
||||
</div>
|
||||
<div className='grid grid-cols-2 gap-2'>
|
||||
{availableData.customFormats.map(format => (
|
||||
<label
|
||||
key={format.file_name}
|
||||
className='flex items-center p-2 bg-white dark:bg-gray-800
|
||||
{(availableData?.customFormats || []).map(
|
||||
format => (
|
||||
<label
|
||||
key={format.file_name}
|
||||
className='flex items-center p-2 bg-white dark:bg-gray-800
|
||||
hover:bg-gray-50 dark:hover:bg-gray-700
|
||||
rounded-lg cursor-pointer group transition-colors
|
||||
border border-gray-200 dark:border-gray-700'>
|
||||
<input
|
||||
type='checkbox'
|
||||
checked={selectedData.customFormats.includes(
|
||||
format.content.name
|
||||
)}
|
||||
onChange={() =>
|
||||
onDataToggle(
|
||||
'customFormats',
|
||||
<input
|
||||
type='checkbox'
|
||||
checked={customFormats.includes(
|
||||
format.content.name
|
||||
)
|
||||
}
|
||||
className='rounded border-gray-300 text-blue-600
|
||||
)}
|
||||
onChange={() =>
|
||||
onDataToggle(
|
||||
'customFormats',
|
||||
format.content.name
|
||||
)
|
||||
}
|
||||
className='rounded border-gray-300 text-blue-600
|
||||
focus:ring-blue-500 focus:ring-offset-0'
|
||||
/>
|
||||
<span
|
||||
className='ml-3 text-sm text-gray-700 dark:text-gray-300
|
||||
/>
|
||||
<span
|
||||
className='ml-3 text-sm text-gray-700 dark:text-gray-300
|
||||
group-hover:text-gray-900 dark:group-hover:text-gray-100'>
|
||||
{format.content.name}
|
||||
</span>
|
||||
</label>
|
||||
))}
|
||||
{format.content.name}
|
||||
</span>
|
||||
</label>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user