mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-08-02 23:02:37 +00:00
Allow deleting logos that are assigned to channels.
This commit is contained in:
parent
23bd5484ee
commit
e7771d5b67
4 changed files with 38 additions and 21 deletions
|
|
@ -1053,24 +1053,27 @@ class BulkDeleteLogosAPIView(APIView):
|
|||
def delete(self, request):
|
||||
logo_ids = request.data.get("logo_ids", [])
|
||||
|
||||
# Check if any logos are being used by channels
|
||||
used_logos = Logo.objects.filter(
|
||||
id__in=logo_ids,
|
||||
channels__isnull=False
|
||||
).distinct()
|
||||
# Get logos and their usage info before deletion
|
||||
logos_to_delete = Logo.objects.filter(id__in=logo_ids)
|
||||
total_channels_affected = 0
|
||||
|
||||
for logo in logos_to_delete:
|
||||
if logo.channels.exists():
|
||||
channel_count = logo.channels.count()
|
||||
total_channels_affected += channel_count
|
||||
# Remove logo from channels
|
||||
logo.channels.update(logo=None)
|
||||
logger.info(f"Removed logo {logo.name} from {channel_count} channels before deletion")
|
||||
|
||||
if used_logos.exists():
|
||||
used_names = list(used_logos.values_list('name', flat=True))
|
||||
return Response(
|
||||
{"error": f"Cannot delete logos that are in use: {', '.join(used_names)}"},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
# Delete logos
|
||||
deleted_count = logos_to_delete.delete()[0]
|
||||
|
||||
# Delete logos that are not in use
|
||||
deleted_count = Logo.objects.filter(id__in=logo_ids).delete()[0]
|
||||
message = f"Successfully deleted {deleted_count} logos"
|
||||
if total_channels_affected > 0:
|
||||
message += f" and removed them from {total_channels_affected} channels"
|
||||
|
||||
return Response(
|
||||
{"message": f"Successfully deleted {deleted_count} logos"},
|
||||
{"message": message},
|
||||
status=status.HTTP_204_NO_CONTENT
|
||||
)
|
||||
|
||||
|
|
@ -1152,15 +1155,14 @@ class LogoViewSet(viewsets.ModelViewSet):
|
|||
return super().update(request, *args, **kwargs)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
"""Delete a logo"""
|
||||
"""Delete a logo and remove it from any channels using it"""
|
||||
logo = self.get_object()
|
||||
|
||||
# Check if logo is being used by any channels
|
||||
# Instead of preventing deletion, remove the logo from channels
|
||||
if logo.channels.exists():
|
||||
return Response(
|
||||
{"error": f"Cannot delete logo as it is used by {logo.channels.count()} channel(s)"},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
channel_count = logo.channels.count()
|
||||
logo.channels.update(logo=None)
|
||||
logger.info(f"Removed logo {logo.name} from {channel_count} channels before deletion")
|
||||
|
||||
return super().destroy(request, *args, **kwargs)
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,16 @@ class LogoSerializer(serializers.ModelSerializer):
|
|||
model = Logo
|
||||
fields = ["id", "name", "url", "cache_url", "channel_count", "is_used", "channel_names"]
|
||||
|
||||
def validate_url(self, value):
|
||||
"""Validate that the URL is unique for creation or update"""
|
||||
if self.instance and self.instance.url == value:
|
||||
return value
|
||||
|
||||
if Logo.objects.filter(url=value).exists():
|
||||
raise serializers.ValidationError("A logo with this URL already exists.")
|
||||
|
||||
return value
|
||||
|
||||
def get_cache_url(self, obj):
|
||||
# return f"/api/channels/logos/{obj.id}/cache/"
|
||||
request = self.context.get("request")
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ const LogoForm = ({ logo = null, isOpen, onClose }) => {
|
|||
// Handle specific timeout errors
|
||||
if (error.code === 'NETWORK_ERROR' || error.message?.includes('timeout')) {
|
||||
errorMessage = 'Request timed out. Please try again.';
|
||||
} else if (error.response?.data?.error) {
|
||||
errorMessage = error.response.data.error;
|
||||
}
|
||||
|
||||
notifications.show({
|
||||
|
|
|
|||
|
|
@ -718,6 +718,9 @@ const LogosTable = () => {
|
|||
isBulkDelete ? (
|
||||
<div>
|
||||
Are you sure you want to delete {selectedRows.size} selected logos?
|
||||
<Text size="sm" c="dimmed" mt="xs">
|
||||
Any channels using these logos will have their logo removed.
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed" mt="xs">
|
||||
This action cannot be undone.
|
||||
</Text>
|
||||
|
|
@ -727,7 +730,7 @@ const LogosTable = () => {
|
|||
Are you sure you want to delete the logo "{logoToDelete.name}"?
|
||||
{logoToDelete.channel_count > 0 && (
|
||||
<Text size="sm" c="orange" mt="xs">
|
||||
Warning: This logo is currently used by {logoToDelete.channel_count} channel{logoToDelete.channel_count !== 1 ? 's' : ''}.
|
||||
This logo is currently used by {logoToDelete.channel_count} channel{logoToDelete.channel_count !== 1 ? 's' : ''}. They will have their logo removed.
|
||||
</Text>
|
||||
)}
|
||||
<Text size="sm" c="dimmed" mt="xs">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue