wagtail-enap-designsystem 1.2.1.121__py3-none-any.whl → 1.2.1.122__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of wagtail-enap-designsystem might be problematic. Click here for more details.
- enap_designsystem/blocks/html_blocks.py +0 -42
- enap_designsystem/models.py +0 -27
- enap_designsystem/templates/enap_designsystem/sistema_votacao_page.html +163 -183
- enap_designsystem/urls.py +6 -3
- enap_designsystem/views.py +118 -153
- enap_designsystem/wagtail_hooks.py +235 -77
- {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.122.dist-info}/METADATA +1 -1
- {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.122.dist-info}/RECORD +11 -12
- enap_designsystem/templates/custom_404.html +0 -372
- {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.122.dist-info}/WHEEL +0 -0
- {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.122.dist-info}/licenses/LICENSE +0 -0
- {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.122.dist-info}/top_level.txt +0 -0
enap_designsystem/urls.py
CHANGED
|
@@ -39,7 +39,10 @@ urlpatterns = [
|
|
|
39
39
|
path('reports/form/<int:page_id>/', views.form_report, name='form_report'),
|
|
40
40
|
|
|
41
41
|
path('votar/', views.votar_projeto, name='votar_projeto'),
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
path('
|
|
42
|
+
|
|
43
|
+
# URLs auxiliares de votação
|
|
44
|
+
path('api/estatisticas/', views.estatisticas_votacao, name='estatisticas_votacao'),
|
|
45
|
+
path('api/ranking/', views.ranking_projetos, name='ranking_projetos'),
|
|
46
|
+
path('api/ranking/<int:categoria_id>/', views.ranking_projetos, name='ranking_projetos_categoria'),
|
|
47
|
+
|
|
45
48
|
]
|
enap_designsystem/views.py
CHANGED
|
@@ -2052,225 +2052,190 @@ def save_file_linked_to_form(uploaded_file, page_id, submission_id, field_name):
|
|
|
2052
2052
|
|
|
2053
2053
|
|
|
2054
2054
|
|
|
2055
|
+
# views.py - View corrigida para votação
|
|
2055
2056
|
|
|
2056
|
-
# views.py - Views completas do Sistema de Votação
|
|
2057
|
-
|
|
2058
|
-
import json
|
|
2059
2057
|
from django.http import JsonResponse
|
|
2060
2058
|
from django.views.decorators.http import require_http_methods
|
|
2061
|
-
from django.
|
|
2062
|
-
from django.
|
|
2063
|
-
|
|
2059
|
+
from django.views.decorators.csrf import csrf_exempt
|
|
2060
|
+
from django.contrib.sessions.models import Session
|
|
2061
|
+
import json
|
|
2062
|
+
import logging
|
|
2063
|
+
|
|
2064
|
+
logger = logging.getLogger(__name__)
|
|
2064
2065
|
|
|
2065
2066
|
|
|
2066
|
-
def get_client_ip(request):
|
|
2067
|
-
"""Extrai o IP real do cliente"""
|
|
2068
|
-
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
|
|
2069
|
-
if x_forwarded_for:
|
|
2070
|
-
ip = x_forwarded_for.split(',')[0].strip()
|
|
2071
|
-
else:
|
|
2072
|
-
ip = request.META.get('REMOTE_ADDR')
|
|
2073
|
-
return ip
|
|
2074
2067
|
|
|
2068
|
+
@require_http_methods(["POST"])
|
|
2069
|
+
@csrf_exempt
|
|
2070
|
+
# views.py - Versão simples sem restrições de tempo
|
|
2075
2071
|
|
|
2076
2072
|
@require_http_methods(["POST"])
|
|
2073
|
+
@csrf_exempt
|
|
2077
2074
|
def votar_projeto(request):
|
|
2078
|
-
"""
|
|
2079
|
-
|
|
2080
|
-
"""
|
|
2075
|
+
"""View simples para votação - sem restrições"""
|
|
2076
|
+
|
|
2081
2077
|
try:
|
|
2082
|
-
|
|
2083
|
-
|
|
2078
|
+
logger.info(f"=== VOTAÇÃO ===")
|
|
2079
|
+
|
|
2080
|
+
# Parse JSON
|
|
2081
|
+
if not request.body:
|
|
2082
|
+
return JsonResponse({
|
|
2083
|
+
'success': False,
|
|
2084
|
+
'message': 'Dados não fornecidos'
|
|
2085
|
+
}, status=400)
|
|
2086
|
+
|
|
2087
|
+
try:
|
|
2088
|
+
data = json.loads(request.body)
|
|
2089
|
+
except json.JSONDecodeError:
|
|
2090
|
+
return JsonResponse({
|
|
2091
|
+
'success': False,
|
|
2092
|
+
'message': 'JSON inválido'
|
|
2093
|
+
}, status=400)
|
|
2094
|
+
|
|
2095
|
+
# Dados obrigatórios
|
|
2084
2096
|
projeto_id = data.get('projeto_id')
|
|
2085
2097
|
categoria_id = data.get('categoria_id')
|
|
2086
2098
|
|
|
2087
2099
|
if not projeto_id or not categoria_id:
|
|
2088
2100
|
return JsonResponse({
|
|
2089
2101
|
'success': False,
|
|
2090
|
-
'message': '
|
|
2102
|
+
'message': 'projeto_id e categoria_id são obrigatórios'
|
|
2091
2103
|
}, status=400)
|
|
2092
2104
|
|
|
2093
|
-
#
|
|
2094
|
-
|
|
2105
|
+
# Dados da requisição
|
|
2106
|
+
ip_address = request.META.get('REMOTE_ADDR', 'unknown')
|
|
2107
|
+
user_agent = request.META.get('HTTP_USER_AGENT', '')
|
|
2108
|
+
|
|
2109
|
+
# Importar e validar
|
|
2110
|
+
from .models import VotoRegistrado, ProjetoVotacao, CategoriaVotacao
|
|
2095
2111
|
|
|
2096
|
-
|
|
2097
|
-
|
|
2112
|
+
try:
|
|
2113
|
+
projeto = ProjetoVotacao.objects.get(id=projeto_id, ativo=True)
|
|
2114
|
+
categoria = CategoriaVotacao.objects.get(id=categoria_id, ativo=True)
|
|
2115
|
+
except (ProjetoVotacao.DoesNotExist, CategoriaVotacao.DoesNotExist):
|
|
2098
2116
|
return JsonResponse({
|
|
2099
2117
|
'success': False,
|
|
2100
|
-
'message': 'Projeto
|
|
2101
|
-
}, status=
|
|
2102
|
-
|
|
2103
|
-
# Obter dados do request
|
|
2104
|
-
ip_address = get_client_ip(request)
|
|
2105
|
-
user_agent = request.META.get('HTTP_USER_AGENT', '')[:500]
|
|
2118
|
+
'message': 'Projeto ou categoria não encontrados'
|
|
2119
|
+
}, status=404)
|
|
2106
2120
|
|
|
2107
|
-
#
|
|
2121
|
+
# REGISTRAR VOTO - SEM VERIFICAÇÕES DE DUPLICAÇÃO
|
|
2108
2122
|
voto = VotoRegistrado.objects.create(
|
|
2109
2123
|
projeto=projeto,
|
|
2124
|
+
categoria_nome=categoria.nome,
|
|
2110
2125
|
ip_address=ip_address,
|
|
2111
|
-
user_agent=user_agent
|
|
2112
|
-
categoria_nome=projeto.categoria.nome
|
|
2126
|
+
user_agent=user_agent[:500] if user_agent else ''
|
|
2113
2127
|
)
|
|
2114
2128
|
|
|
2115
|
-
|
|
2129
|
+
logger.info(f"Voto registrado: {voto.id}")
|
|
2130
|
+
|
|
2131
|
+
# Estatísticas
|
|
2132
|
+
total_votos_projeto = VotoRegistrado.objects.filter(projeto=projeto).count()
|
|
2133
|
+
total_votos_categoria = VotoRegistrado.objects.filter(
|
|
2134
|
+
projeto__categoria=categoria
|
|
2135
|
+
).count()
|
|
2136
|
+
|
|
2116
2137
|
return JsonResponse({
|
|
2117
2138
|
'success': True,
|
|
2118
2139
|
'message': 'Voto registrado com sucesso!',
|
|
2119
|
-
'voto_id':
|
|
2120
|
-
'
|
|
2121
|
-
'
|
|
2122
|
-
'
|
|
2123
|
-
'timestamp': voto.timestamp.isoformat()
|
|
2140
|
+
'voto_id': voto.id,
|
|
2141
|
+
'total_votos': total_votos_projeto,
|
|
2142
|
+
'total_votos_categoria': total_votos_categoria,
|
|
2143
|
+
'projeto_titulo': projeto.titulo
|
|
2124
2144
|
})
|
|
2125
2145
|
|
|
2126
|
-
except json.JSONDecodeError:
|
|
2127
|
-
return JsonResponse({
|
|
2128
|
-
'success': False,
|
|
2129
|
-
'message': 'Dados JSON inválidos.'
|
|
2130
|
-
}, status=400)
|
|
2131
|
-
|
|
2132
|
-
except ProjetoVotacao.DoesNotExist:
|
|
2133
|
-
return JsonResponse({
|
|
2134
|
-
'success': False,
|
|
2135
|
-
'message': 'Projeto não encontrado ou inativo.'
|
|
2136
|
-
}, status=404)
|
|
2137
|
-
|
|
2138
2146
|
except Exception as e:
|
|
2139
|
-
|
|
2140
|
-
import logging
|
|
2141
|
-
logger = logging.getLogger(__name__)
|
|
2142
|
-
logger.error(f"Erro ao processar voto: {str(e)}", exc_info=True)
|
|
2143
|
-
|
|
2147
|
+
logger.error(f"Erro: {str(e)}", exc_info=True)
|
|
2144
2148
|
return JsonResponse({
|
|
2145
2149
|
'success': False,
|
|
2146
|
-
'message': 'Erro interno
|
|
2150
|
+
'message': f'Erro interno: {str(e)}'
|
|
2147
2151
|
}, status=500)
|
|
2148
|
-
|
|
2152
|
+
# Views auxiliares também corrigidas
|
|
2149
2153
|
|
|
2150
2154
|
@require_http_methods(["GET"])
|
|
2151
2155
|
def estatisticas_votacao(request):
|
|
2152
|
-
"""
|
|
2153
|
-
View AJAX para obter estatísticas da votação
|
|
2154
|
-
"""
|
|
2156
|
+
"""Estatísticas da votação"""
|
|
2155
2157
|
try:
|
|
2158
|
+
from .models import VotoRegistrado, CategoriaVotacao, ProjetoVotacao
|
|
2159
|
+
from django.db.models import Count
|
|
2160
|
+
|
|
2156
2161
|
# Estatísticas gerais
|
|
2157
2162
|
total_votos = VotoRegistrado.objects.count()
|
|
2158
|
-
total_projetos = ProjetoVotacao.objects.filter(ativo=True).count()
|
|
2159
2163
|
total_categorias = CategoriaVotacao.objects.filter(ativo=True).count()
|
|
2164
|
+
total_projetos = ProjetoVotacao.objects.filter(ativo=True).count()
|
|
2160
2165
|
|
|
2161
|
-
#
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
# Projeto mais votado da categoria
|
|
2168
|
-
projeto_top = None
|
|
2169
|
-
if projetos_categoria.exists():
|
|
2170
|
-
projeto_mais_votado = max(projetos_categoria, key=lambda p: p.total_votos)
|
|
2171
|
-
if projeto_mais_votado.total_votos > 0:
|
|
2172
|
-
projeto_top = {
|
|
2173
|
-
'id': projeto_mais_votado.id,
|
|
2174
|
-
'titulo': projeto_mais_votado.titulo,
|
|
2175
|
-
'votos': projeto_mais_votado.total_votos
|
|
2176
|
-
}
|
|
2177
|
-
|
|
2178
|
-
categorias_stats.append({
|
|
2179
|
-
'id': categoria.id,
|
|
2180
|
-
'nome': categoria.nome,
|
|
2181
|
-
'total_projetos': projetos_categoria.count(),
|
|
2182
|
-
'total_votos': votos_categoria,
|
|
2183
|
-
'projeto_top': projeto_top
|
|
2184
|
-
})
|
|
2185
|
-
|
|
2186
|
-
# Projetos mais votados (top 5)
|
|
2187
|
-
projetos_top = []
|
|
2188
|
-
for projeto in ProjetoVotacao.objects.filter(ativo=True):
|
|
2189
|
-
projetos_top.append({
|
|
2190
|
-
'id': projeto.id,
|
|
2191
|
-
'titulo': projeto.titulo,
|
|
2192
|
-
'categoria': projeto.categoria.nome,
|
|
2193
|
-
'votos': projeto.total_votos
|
|
2194
|
-
})
|
|
2166
|
+
# Votos por categoria (usando relacionamento)
|
|
2167
|
+
votos_categoria = (VotoRegistrado.objects
|
|
2168
|
+
.values('projeto__categoria__nome', 'projeto__categoria__id')
|
|
2169
|
+
.annotate(total=Count('id'))
|
|
2170
|
+
.order_by('-total'))
|
|
2195
2171
|
|
|
2196
|
-
#
|
|
2197
|
-
projetos_top =
|
|
2172
|
+
# Projetos mais votados
|
|
2173
|
+
projetos_top = (VotoRegistrado.objects
|
|
2174
|
+
.values('projeto__titulo', 'projeto__id', 'projeto__categoria__nome')
|
|
2175
|
+
.annotate(total=Count('id'))
|
|
2176
|
+
.order_by('-total')[:10])
|
|
2198
2177
|
|
|
2199
2178
|
return JsonResponse({
|
|
2200
2179
|
'success': True,
|
|
2201
|
-
'
|
|
2202
|
-
'
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
'categorias': categorias_stats,
|
|
2208
|
-
'projetos_top': projetos_top,
|
|
2209
|
-
'timestamp': timezone.now().isoformat()
|
|
2180
|
+
'estatisticas': {
|
|
2181
|
+
'total_votos': total_votos,
|
|
2182
|
+
'total_categorias': total_categorias,
|
|
2183
|
+
'total_projetos': total_projetos,
|
|
2184
|
+
'votos_por_categoria': list(votos_categoria),
|
|
2185
|
+
'projetos_mais_votados': list(projetos_top)
|
|
2210
2186
|
}
|
|
2211
2187
|
})
|
|
2212
2188
|
|
|
2213
2189
|
except Exception as e:
|
|
2214
|
-
|
|
2215
|
-
logger = logging.getLogger(__name__)
|
|
2216
|
-
logger.error(f"Erro ao obter estatísticas: {str(e)}", exc_info=True)
|
|
2217
|
-
|
|
2190
|
+
logger.error(f"Erro estatísticas: {e}")
|
|
2218
2191
|
return JsonResponse({
|
|
2219
2192
|
'success': False,
|
|
2220
|
-
'message': 'Erro ao
|
|
2193
|
+
'message': 'Erro ao buscar estatísticas'
|
|
2221
2194
|
}, status=500)
|
|
2222
2195
|
|
|
2223
2196
|
|
|
2224
|
-
@require_http_methods(["GET"])
|
|
2197
|
+
@require_http_methods(["GET"])
|
|
2225
2198
|
def ranking_projetos(request, categoria_id=None):
|
|
2226
|
-
"""
|
|
2227
|
-
View AJAX para obter ranking de projetos
|
|
2228
|
-
"""
|
|
2199
|
+
"""Ranking de projetos por categoria"""
|
|
2229
2200
|
try:
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
categoria = get_object_or_404(CategoriaVotacao, id=categoria_id, ativo=True)
|
|
2233
|
-
projetos = ProjetoVotacao.objects.filter(categoria=categoria, ativo=True)
|
|
2234
|
-
else:
|
|
2235
|
-
projetos = ProjetoVotacao.objects.filter(ativo=True)
|
|
2236
|
-
|
|
2237
|
-
# Criar lista com dados dos projetos
|
|
2238
|
-
ranking = []
|
|
2239
|
-
for projeto in projetos:
|
|
2240
|
-
ranking.append({
|
|
2241
|
-
'id': projeto.id,
|
|
2242
|
-
'titulo': projeto.titulo,
|
|
2243
|
-
'categoria': projeto.categoria.nome,
|
|
2244
|
-
'equipe': projeto.nome_equipe,
|
|
2245
|
-
'total_votos': projeto.total_votos,
|
|
2246
|
-
'destacado': projeto.destacado
|
|
2247
|
-
})
|
|
2201
|
+
from .models import VotoRegistrado, ProjetoVotacao, CategoriaVotacao
|
|
2202
|
+
from django.db.models import Count
|
|
2248
2203
|
|
|
2249
|
-
#
|
|
2250
|
-
|
|
2204
|
+
# Base query
|
|
2205
|
+
queryset = VotoRegistrado.objects.select_related('projeto', 'projeto__categoria')
|
|
2206
|
+
|
|
2207
|
+
# Filtrar por categoria se fornecida
|
|
2208
|
+
if categoria_id:
|
|
2209
|
+
try:
|
|
2210
|
+
categoria = CategoriaVotacao.objects.get(id=categoria_id, ativo=True)
|
|
2211
|
+
queryset = queryset.filter(projeto__categoria=categoria)
|
|
2212
|
+
except CategoriaVotacao.DoesNotExist:
|
|
2213
|
+
return JsonResponse({
|
|
2214
|
+
'success': False,
|
|
2215
|
+
'message': 'Categoria não encontrada'
|
|
2216
|
+
}, status=404)
|
|
2217
|
+
|
|
2218
|
+
# Ranking
|
|
2219
|
+
ranking = (queryset
|
|
2220
|
+
.values(
|
|
2221
|
+
'projeto__id',
|
|
2222
|
+
'projeto__titulo',
|
|
2223
|
+
'projeto__categoria__nome',
|
|
2224
|
+
'projeto__categoria__id',
|
|
2225
|
+
'projeto__nome_equipe'
|
|
2226
|
+
)
|
|
2227
|
+
.annotate(total_votos=Count('id'))
|
|
2228
|
+
.order_by('-total_votos'))
|
|
2251
2229
|
|
|
2252
2230
|
return JsonResponse({
|
|
2253
2231
|
'success': True,
|
|
2254
|
-
'
|
|
2255
|
-
|
|
2256
|
-
'categoria': categoria.nome if categoria_id else 'Todas',
|
|
2257
|
-
'total_projetos': len(ranking),
|
|
2258
|
-
'timestamp': timezone.now().isoformat()
|
|
2259
|
-
}
|
|
2232
|
+
'ranking': list(ranking),
|
|
2233
|
+
'categoria_id': categoria_id
|
|
2260
2234
|
})
|
|
2261
2235
|
|
|
2262
|
-
except CategoriaVotacao.DoesNotExist:
|
|
2263
|
-
return JsonResponse({
|
|
2264
|
-
'success': False,
|
|
2265
|
-
'message': 'Categoria não encontrada.'
|
|
2266
|
-
}, status=404)
|
|
2267
|
-
|
|
2268
2236
|
except Exception as e:
|
|
2269
|
-
|
|
2270
|
-
logger = logging.getLogger(__name__)
|
|
2271
|
-
logger.error(f"Erro ao obter ranking: {str(e)}", exc_info=True)
|
|
2272
|
-
|
|
2237
|
+
logger.error(f"Erro ranking: {e}")
|
|
2273
2238
|
return JsonResponse({
|
|
2274
2239
|
'success': False,
|
|
2275
|
-
'message': 'Erro ao
|
|
2240
|
+
'message': 'Erro ao buscar ranking'
|
|
2276
2241
|
}, status=500)
|