fix: ensure data_to_sync has a safe structure and improve sync method handling

This commit is contained in:
Sam Chau
2025-01-08 16:17:40 +10:30
parent f3a483ecf2
commit ee8cf74384
3 changed files with 152 additions and 86 deletions

View File

@@ -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}
/>

View File

@@ -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>