Refactor CreditBalanceViewSet for improved readability and error handling. Update SiteDefinitionView to allow public access without authentication. Enhance Vite configuration for shared component paths and debugging logs. Remove inaccessible shared CSS imports in main.tsx.

This commit is contained in:
IGNY8 VPS (Salman)
2025-11-18 21:02:35 +00:00
parent adc681af8c
commit c4b79802ec
5 changed files with 54 additions and 61 deletions

Binary file not shown.

View File

@@ -41,70 +41,48 @@ class CreditBalanceViewSet(viewsets.ViewSet):
@action(detail=False, methods=['get'])
def balance(self, request):
"""Get current credit balance and usage"""
try:
account = getattr(request, 'account', None)
if not account:
user = getattr(request, 'user', None)
if user and user.is_authenticated:
# Try to get account from user - refresh from DB to ensure we have latest
try:
from igny8_core.auth.models import User as UserModel
# Refresh user from DB to get account relationship
user = UserModel.objects.select_related('account', 'account__plan').get(id=user.id)
account = user.account
# Also set it on request for future use
request.account = account
except (AttributeError, UserModel.DoesNotExist, Exception):
account = None
if not account:
# Return empty balance instead of error - frontend will show "no data" message
return success_response(data={
'credits': 0,
'plan_credits_per_month': 0,
'credits_used_this_month': 0,
'credits_remaining': 0,
}, request=request)
# Get plan credits per month (use get_effective_credits_per_month for Phase 0 compatibility)
plan_credits_per_month = 0
try:
if account.plan:
plan_credits_per_month = account.plan.get_effective_credits_per_month()
except (AttributeError, Exception):
# Plan might not have the method or there's an error accessing it
plan_credits_per_month = 0
# Calculate credits used this month
now = timezone.now()
start_of_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
credits_used_this_month = CreditUsageLog.objects.filter(
account=account,
created_at__gte=start_of_month
).aggregate(total=Sum('credits_used'))['total'] or 0
credits_remaining = getattr(account, 'credits', 0) or 0
data = {
'credits': getattr(account, 'credits', 0) or 0,
'plan_credits_per_month': plan_credits_per_month,
'credits_used_this_month': credits_used_this_month,
'credits_remaining': credits_remaining,
}
serializer = CreditBalanceSerializer(data)
return success_response(data=serializer.data, request=request)
except Exception as e:
import logging
logger = logging.getLogger(__name__)
logger.error(f"Error in credit balance endpoint: {str(e)}", exc_info=True)
# Return empty balance instead of error
account = getattr(request, 'account', None)
if not account:
user = getattr(request, 'user', None)
if user and user.is_authenticated:
from igny8_core.auth.models import User as UserModel
user = UserModel.objects.select_related('account', 'account__plan').get(id=user.id)
account = user.account
request.account = account
if not account:
return success_response(data={
'credits': 0,
'plan_credits_per_month': 0,
'credits_used_this_month': 0,
'credits_remaining': 0,
}, request=request)
# Get plan credits - plan is already associated
plan_credits_per_month = 0
if account.plan:
plan_credits_per_month = account.plan.get_effective_credits_per_month()
# Calculate credits used this month
now = timezone.now()
start_of_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
credits_used_this_month = CreditUsageLog.objects.filter(
account=account,
created_at__gte=start_of_month
).aggregate(total=Sum('credits_used'))['total'] or 0
credits = account.credits or 0
credits_remaining = credits
data = {
'credits': credits,
'plan_credits_per_month': plan_credits_per_month,
'credits_used_this_month': credits_used_this_month,
'credits_remaining': credits_remaining,
}
serializer = CreditBalanceSerializer(data)
return success_response(data=serializer.data, request=request)
@extend_schema_view(

View File

@@ -9,6 +9,8 @@ from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from igny8_core.api.base import SiteSectorModelViewSet
from igny8_core.api.permissions import IsAuthenticatedAndActive, IsEditorOrAbove
@@ -201,6 +203,7 @@ class PublisherViewSet(viewsets.ViewSet):
)
@method_decorator(csrf_exempt, name='dispatch')
class SiteDefinitionView(APIView):
"""
Public endpoint to serve deployed site definitions.
@@ -208,6 +211,7 @@ class SiteDefinitionView(APIView):
No authentication required for public sites.
"""
permission_classes = [] # Public endpoint
authentication_classes = [] # No authentication required
def get(self, request, site_id):
"""

View File

@@ -2,9 +2,12 @@ import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.tsx';
import './index.css';
// Import shared component styles - Vite alias @shared resolves to frontend/src/components/shared
import '@shared/blocks/blocks.css';
import '@shared/layouts/layouts.css';
// Note: Shared component CSS imports removed - CSS files not accessible in container
// Components will work without shared CSS, just without the shared styles
// To add shared styles later, either:
// 1. Copy CSS files to sites/src/styles/shared/
// 2. Or mount frontend directory and use proper path
createRoot(document.getElementById('root')!).render(
<StrictMode>

View File

@@ -10,14 +10,22 @@ const sharedPathCandidates = [
path.resolve(__dirname, '../frontend/src/components/shared'),
path.resolve(__dirname, '../../frontend/src/components/shared'),
'/frontend/src/components/shared',
path.resolve(__dirname, '../../frontend/src/components/shared'), // Try parent of parent
];
const sharedComponentsPath = sharedPathCandidates.find((candidate) => fs.existsSync(candidate)) ?? sharedPathCandidates[0];
// Log for debugging
console.log('Shared components path:', sharedComponentsPath);
console.log('Path exists:', fs.existsSync(sharedComponentsPath));
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@shared': sharedComponentsPath,
// Explicit aliases for CSS files to ensure Vite resolves them
'@shared/blocks/blocks.css': path.join(sharedComponentsPath, 'blocks/blocks.css'),
'@shared/layouts/layouts.css': path.join(sharedComponentsPath, 'layouts/layouts.css'),
},
},
server: {