mirror of
https://github.com/narrrl/holy-flavor-rater.git
synced 2026-11-04 17:07:01 +01:00
Merge branch 'main' into narl.io
This commit is contained in:
commit
7aa3a5b434
4 files changed
+38
-7
No files matched your search
@@ -4,6 +4,7 @@ from datetime import datetime, timedelta
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.core.management import call_command
|
||||
from django.utils import timezone
|
||||
from django.db import models
|
||||
from api.models import Job
|
||||
from io import StringIO
|
||||
|
||||
@@ -70,5 +71,3 @@ class Command(BaseCommand):
|
||||
job.error_message = error
|
||||
job.save()
|
||||
self.stdout.write(self.style.SUCCESS(f"Job finished: {job.status}"))
|
||||
|
||||
from django.db import models # Needed for the Q object inside handle
|
||||
@@ -75,7 +75,10 @@ class FlavorSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Flavor
|
||||
fields = ['id', 'name', 'category', 'category_name', 'category_slug', 'description', 'average_rating', 'followed_average_rating', 'user_rating', 'ratings', 'image_url', 'is_available', 'is_legacy', 'shop_url']
|
||||
fields = ['id', 'name', 'category', 'category_name', 'category_slug', 'description', 'average_rating', 'followed_average_rating', 'user_rating', 'ratings', 'image_url', 'image', 'is_available', 'is_legacy', 'shop_url']
|
||||
extra_kwargs = {
|
||||
'image': {'write_only': True}
|
||||
}
|
||||
|
||||
def get_image_url(self, obj):
|
||||
if obj.image:
|
||||
|
||||
@@ -8,12 +8,12 @@ from django_filters.rest_framework import DjangoFilterBackend
|
||||
from django_ratelimit.decorators import ratelimit
|
||||
from django.utils.decorators import method_decorator
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
from .models import User, Flavor, Category, Rating, Reply, Notification, Ticket, TicketMessage, UserIP, ProfileComment, Banner
|
||||
from .models import User, Flavor, Category, Rating, Reply, Notification, Ticket, TicketMessage, UserIP, ProfileComment, Banner, SystemConfig, Job
|
||||
from .serializers import (
|
||||
UserSerializer, FlavorSerializer, CategorySerializer, RatingSerializer,
|
||||
ReplySerializer, NotificationSerializer, TicketSerializer,
|
||||
TicketMessageSerializer, AdminUserListSerializer, AdminUserDetailSerializer,
|
||||
ProfileCommentSerializer, BannerSerializer
|
||||
ProfileCommentSerializer, BannerSerializer, SystemConfigSerializer, JobSerializer
|
||||
)
|
||||
|
||||
def log_user_ip(user, request):
|
||||
@@ -870,8 +870,8 @@ class AdminViewSet(viewsets.ViewSet):
|
||||
'debug': settings.DEBUG,
|
||||
'allowed_hosts': settings.ALLOWED_HOSTS,
|
||||
'frontend_url': getattr(settings, 'FRONTEND_URL', 'Not set'),
|
||||
'media_root': settings.MEDIA_ROOT,
|
||||
'static_root': settings.STATIC_ROOT,
|
||||
'media_root': str(settings.MEDIA_ROOT),
|
||||
'static_root': str(settings.STATIC_ROOT),
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ const FlavorDetail: React.FC<FlavorDetailProps> = ({ adminMode }) => {
|
||||
|
||||
// Product Edit state (Admin)
|
||||
const [isAdminEditing, setIsAdminEditing] = useState(false);
|
||||
const [uploadingImage, setUploadingImage] = useState(false);
|
||||
const [editFlavorData, setEditFlavorData] = useState({
|
||||
name: '',
|
||||
description: '',
|
||||
@@ -148,6 +149,26 @@ const FlavorDetail: React.FC<FlavorDetailProps> = ({ adminMode }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (!file) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('image', file);
|
||||
|
||||
try {
|
||||
setUploadingImage(true);
|
||||
await api.patch(`flavors/${id}/`, formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
});
|
||||
fetchFlavor();
|
||||
} catch (err) {
|
||||
alert('Image upload failed');
|
||||
} finally {
|
||||
setUploadingImage(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRatingSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!newScore) {
|
||||
@@ -337,6 +358,14 @@ const FlavorDetail: React.FC<FlavorDetailProps> = ({ adminMode }) => {
|
||||
value={editFlavorData.shop_url}
|
||||
onChange={(e) => setEditFlavorData({...editFlavorData, shop_url: e.target.value})}
|
||||
/>
|
||||
|
||||
<Box>
|
||||
<Button variant="outlined" component="label" size="small" fullWidth disabled={uploadingImage}>
|
||||
{uploadingImage ? 'Uploading...' : 'Upload Custom Image'}
|
||||
<input type="file" hidden accept="image/*" onChange={handleImageUpload} />
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<FormControlLabel
|
||||
control={<Switch checked={editFlavorData.is_available} onChange={(e) => setEditFlavorData({...editFlavorData, is_available: e.target.checked})} />}
|
||||
label="In Stock"
|
||||
|
||||
Reference in new issue
Block a user