wagtail-enap-designsystem 1.2.1.121__py3-none-any.whl → 1.2.1.123__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.

Files changed (26) hide show
  1. enap_designsystem/blocks/__init__.py +4 -0
  2. enap_designsystem/blocks/form.py +101 -6
  3. enap_designsystem/blocks/html_blocks.py +199 -52
  4. enap_designsystem/blocks/semana_inovacao.py +7 -1
  5. enap_designsystem/middleware/aluno_sso.py +16 -0
  6. enap_designsystem/migrations/0382_alter_areaaluno_body_alter_cursoeadpage_curso_and_more.py +51080 -0
  7. enap_designsystem/migrations/0383_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +50922 -0
  8. enap_designsystem/migrations/0384_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51606 -0
  9. enap_designsystem/migrations/0385_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51947 -0
  10. enap_designsystem/migrations/0386_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51809 -0
  11. enap_designsystem/models.py +0 -27
  12. enap_designsystem/templates/custom_404.html +1 -1
  13. enap_designsystem/templates/enap_designsystem/blocks/apresentacao_block.html +116 -0
  14. enap_designsystem/templates/enap_designsystem/blocks/apresentacao_simple_block.html +236 -0
  15. enap_designsystem/templates/enap_designsystem/form_templates/formulario_page.html +490 -13
  16. enap_designsystem/templates/enap_designsystem/includes/form_field.html +661 -4
  17. enap_designsystem/templates/enap_designsystem/pages/mba_especializacao.html +10 -0
  18. enap_designsystem/templates/enap_designsystem/sistema_votacao_page.html +194 -202
  19. enap_designsystem/urls.py +6 -3
  20. enap_designsystem/views.py +118 -153
  21. enap_designsystem/wagtail_hooks.py +235 -77
  22. {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.123.dist-info}/METADATA +1 -1
  23. {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.123.dist-info}/RECORD +26 -18
  24. {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.123.dist-info}/WHEEL +0 -0
  25. {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.123.dist-info}/licenses/LICENSE +0 -0
  26. {wagtail_enap_designsystem-1.2.1.121.dist-info → wagtail_enap_designsystem-1.2.1.123.dist-info}/top_level.txt +0 -0
@@ -22,19 +22,20 @@
22
22
  margin: 0;
23
23
  padding: 0;
24
24
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
25
- {% if page.background_image %}
26
- {% for block in page.background_image %}
27
- {% if block.block_type == 'background_image' %}
28
- {% image block.value max-1920x1080 as bg_image %}
29
- background: linear-gradient(rgba(0,0,0,0.1), rgba(0,0,0,0.1)), url('{{ bg_image.url }}');
30
- background-size: cover;
31
- background-position: center;
32
- background-attachment: fixed;
33
- {% endif %}
34
- {% endfor %}
35
- {% else %}
36
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
37
- {% endif %}
25
+ {% if page.background_image_fundo %}
26
+ {% for block in page.background_image_fundo %}
27
+ {% if block.block_type == 'background_image_stream' %}
28
+ {% image block.value max-1920x1080 as bg_image %}
29
+ background: linear-gradient(rgba(0,125,122,0.3), rgba(0,105,105,0.3)), url('{{ bg_image.url }}');
30
+ background-size: cover;
31
+ background-position: center;
32
+ background-attachment: fixed;
33
+ {% endif %}
34
+ {% endfor %}
35
+ {% else %}
36
+ /* Gradiente padrão com as novas cores #007D7A e #006969 */
37
+ background: linear-gradient(135deg, #007D7A 0%, #006969 100%);
38
+ {% endif %}
38
39
  min-height: 100vh;
39
40
  }
40
41
 
@@ -2090,8 +2091,484 @@ if (input.classList.contains('cnpj-field') && input.value) {
2090
2091
  });
2091
2092
 
2092
2093
 
2094
+ // ========================================
2095
+ // SISTEMA AVANÇADO DE MULTI-REDIRECIONAMENTO
2096
+ // ========================================
2097
+
2098
+ // Variáveis para controle avançado
2099
+ let multiRedirectFields = new Map();
2100
+ let pendingActions = new Map();
2101
+ let conditionalFieldsVisible = new Set();
2102
+
2103
+ // INICIALIZAÇÃO DOS CAMPOS MULTI-REDIRECT
2104
+ function initializeMultiRedirectFields() {
2105
+ console.log('🔀 Inicializando sistema multi-redirecionamento...');
2106
+
2107
+ const multiRedirectGroups = document.querySelectorAll('.checkbox-multi-redirect-group');
2108
+
2109
+ multiRedirectGroups.forEach(group => {
2110
+ try {
2111
+ const configData = group.getAttribute('data-field-config');
2112
+ const config = JSON.parse(configData);
2113
+
2114
+ multiRedirectFields.set(config.fieldId, config);
2115
+
2116
+ // Configurar listeners baseado no tipo de campo
2117
+ if (config.fieldType === 'checkbox') {
2118
+ setupCheckboxListeners(group, config);
2119
+ } else if (config.fieldType === 'radio') {
2120
+ setupRadioListeners(group, config);
2121
+ } else if (config.fieldType === 'dropdown') {
2122
+ setupDropdownListeners(group, config);
2123
+ }
2124
+
2125
+ console.log(`✅ Multi-redirect configurado: ${config.fieldId} (${config.fieldType})`);
2126
+
2127
+ } catch (error) {
2128
+ console.error('❌ Erro configuração multi-redirect:', error);
2129
+ }
2130
+ });
2131
+
2132
+ console.log(`🔀 ${multiRedirectFields.size} campos multi-redirect ativos`);
2133
+ }
2134
+
2135
+ // CONFIGURAR LISTENERS PARA CHECKBOX
2136
+ function setupCheckboxListeners(group, config) {
2137
+ const checkbox = group.querySelector('.multi-redirect-input');
2138
+ const item = group.querySelector('.multi-redirect-item');
2139
+
2140
+ if (checkbox && item) {
2141
+ checkbox.addEventListener('change', function(e) {
2142
+ const isChecked = e.target.checked;
2143
+
2144
+ if (isChecked) {
2145
+ item.classList.add('selected');
2146
+ handleOptionSelected(config, 0, config.options[0]); // Primeira opção
2147
+ } else {
2148
+ item.classList.remove('selected');
2149
+ handleOptionDeselected(config);
2150
+ }
2151
+ });
2152
+ }
2153
+ }
2154
+
2155
+ // CONFIGURAR LISTENERS PARA RADIO
2156
+ function setupRadioListeners(group, config) {
2157
+ const radios = group.querySelectorAll('.multi-redirect-input');
2158
+ const items = group.querySelectorAll('.multi-redirect-item');
2159
+
2160
+ radios.forEach((radio, index) => {
2161
+ radio.addEventListener('change', function(e) {
2162
+ if (e.target.checked) {
2163
+ // Remover seleção anterior
2164
+ items.forEach(item => item.classList.remove('selected'));
2165
+
2166
+ // Adicionar seleção atual
2167
+ const selectedItem = e.target.closest('.multi-redirect-item');
2168
+ if (selectedItem) {
2169
+ selectedItem.classList.add('selected');
2170
+ }
2171
+
2172
+ const optionIndex = parseInt(e.target.getAttribute('data-option-index'));
2173
+ handleOptionSelected(config, optionIndex, config.options[optionIndex]);
2174
+ }
2175
+ });
2176
+ });
2177
+ }
2178
+
2179
+ // CONFIGURAR LISTENERS PARA DROPDOWN
2180
+ function setupDropdownListeners(group, config) {
2181
+ const select = group.querySelector('.multi-redirect-input');
2182
+
2183
+ if (select) {
2184
+ select.addEventListener('change', function(e) {
2185
+ const selectedOption = e.target.selectedOptions[0];
2186
+
2187
+ if (selectedOption && selectedOption.value) {
2188
+ const optionIndex = parseInt(selectedOption.getAttribute('data-option-index'));
2189
+ handleOptionSelected(config, optionIndex, config.options[optionIndex]);
2190
+ } else {
2191
+ handleOptionDeselected(config);
2192
+ }
2193
+ });
2194
+ }
2195
+ }
2196
+
2197
+ // GERENCIAR OPÇÃO SELECIONADA
2198
+ function handleOptionSelected(config, optionIndex, option) {
2199
+ console.log(`🎯 Opção selecionada: "${option.value}" - Ação: ${option.action}`);
2200
+
2201
+ const fieldId = config.fieldId;
2202
+ const group = document.querySelector(`[data-field-id="${fieldId}"]`);
2203
+
2204
+ // Limpar ações anteriores
2205
+ clearPreviousActions(fieldId);
2206
+
2207
+ // Mostrar mensagem se configurada
2208
+ if (option.message) {
2209
+ showRedirectMessage(fieldId, optionIndex, option.message);
2210
+ }
2211
+
2212
+ // Processar ação baseada no tipo
2213
+ switch (option.action) {
2214
+ case 'continue':
2215
+ // Não fazer nada, apenas continuar
2216
+ console.log('➡️ Continuando normalmente');
2217
+ break;
2218
+
2219
+ case 'next_step':
2220
+ schedulePendingAction(fieldId, {
2221
+ type: 'next_step',
2222
+ delay: option.delay || 1,
2223
+ message: option.message
2224
+ });
2225
+ break;
2226
+
2227
+ case 'specific_section':
2228
+ if (option.targetSection) {
2229
+ schedulePendingAction(fieldId, {
2230
+ type: 'specific_section',
2231
+ target: option.targetSection,
2232
+ delay: option.delay || 1,
2233
+ message: option.message
2234
+ });
2235
+ }
2236
+ break;
2237
+
2238
+ case 'skip_to_end':
2239
+ schedulePendingAction(fieldId, {
2240
+ type: 'skip_to_end',
2241
+ delay: option.delay || 2,
2242
+ message: option.message
2243
+ });
2244
+ break;
2245
+
2246
+ case 'show_fields':
2247
+ showConditionalFields(fieldId, option.value);
2248
+ break;
2249
+ }
2250
+ }
2251
+
2252
+ // GERENCIAR OPÇÃO DESELECIONADA
2253
+ function handleOptionDeselected(config) {
2254
+ const fieldId = config.fieldId;
2255
+ console.log(`❌ Opção deselecionada: ${fieldId}`);
2256
+
2257
+ clearPreviousActions(fieldId);
2258
+ hideAllConditionalFields(fieldId);
2259
+ }
2260
+
2261
+ // AGENDAR AÇÃO PENDENTE
2262
+ function schedulePendingAction(fieldId, action) {
2263
+ // Adicionar indicador visual
2264
+ const group = document.querySelector(`[data-field-id="${fieldId}"]`);
2265
+ if (group) {
2266
+ group.classList.add('action-pending');
2267
+
2268
+ let pendingText = '🔄 Processando...';
2269
+ if (action.type === 'next_step') pendingText = '⏩ Próxima etapa...';
2270
+ else if (action.type === 'specific_section') pendingText = '🎯 Redirecionando...';
2271
+ else if (action.type === 'skip_to_end') pendingText = '⏭️ Finalizando...';
2272
+
2273
+ group.setAttribute('data-pending-action', pendingText);
2274
+ }
2275
+
2276
+ // Agendar execução
2277
+ pendingActions.set(fieldId, action);
2278
+
2279
+ console.log(`📅 Ação agendada para ${action.delay}s: ${action.type}`);
2280
+ }
2281
+
2282
+ // LIMPAR AÇÕES ANTERIORES
2283
+ function clearPreviousActions(fieldId) {
2284
+ // Remover ação pendente
2285
+ pendingActions.delete(fieldId);
2286
+
2287
+ // Remover indicador visual
2288
+ const group = document.querySelector(`[data-field-id="${fieldId}"]`);
2289
+ if (group) {
2290
+ group.classList.remove('action-pending');
2291
+ group.removeAttribute('data-pending-action');
2292
+ }
2293
+
2294
+ // Ocultar mensagens
2295
+ hideAllRedirectMessages(fieldId);
2296
+ }
2297
+
2298
+ // MOSTRAR MENSAGEM DE REDIRECIONAMENTO
2299
+ function showRedirectMessage(fieldId, optionIndex, message) {
2300
+ const blockId = fieldId.split('_').pop();
2301
+ const messageElement = document.getElementById(`redirect_message_${blockId}_${optionIndex}`);
2302
+
2303
+ if (messageElement) {
2304
+ messageElement.style.display = 'block';
2305
+
2306
+ setTimeout(() => {
2307
+ messageElement.scrollIntoView({
2308
+ behavior: 'smooth',
2309
+ block: 'center'
2310
+ });
2311
+ }, 100);
2312
+ }
2313
+ }
2093
2314
 
2315
+ // OCULTAR TODAS AS MENSAGENS
2316
+ function hideAllRedirectMessages(fieldId) {
2317
+ const blockId = fieldId.split('_').pop();
2318
+ const messages = document.querySelectorAll(`[id^="redirect_message_${blockId}_"]`);
2319
+
2320
+ messages.forEach(message => {
2321
+ message.style.display = 'none';
2322
+ });
2323
+ }
2324
+
2325
+ // MOSTRAR CAMPOS CONDICIONAIS
2326
+ function showConditionalFields(fieldId, optionValue) {
2327
+ const conditionalField = document.querySelector(`[data-parent-field="${fieldId}"][data-option-value="${optionValue}"]`);
2328
+
2329
+ if (conditionalField) {
2330
+ conditionalField.style.display = 'block';
2331
+ conditionalFieldsVisible.add(`${fieldId}_${optionValue}`);
2332
+
2333
+ console.log(`👁️ Campos condicionais mostrados para: ${optionValue}`);
2334
+
2335
+ setTimeout(() => {
2336
+ conditionalField.scrollIntoView({
2337
+ behavior: 'smooth',
2338
+ block: 'center'
2339
+ });
2340
+ }, 200);
2341
+ }
2342
+ }
2343
+
2344
+ // OCULTAR TODOS OS CAMPOS CONDICIONAIS
2345
+ function hideAllConditionalFields(fieldId) {
2346
+ const conditionalFields = document.querySelectorAll(`[data-parent-field="${fieldId}"]`);
2347
+
2348
+ conditionalFields.forEach(field => {
2349
+ field.style.display = 'none';
2350
+ });
2351
+
2352
+ // Limpar controle
2353
+ Array.from(conditionalFieldsVisible).forEach(key => {
2354
+ if (key.startsWith(fieldId)) {
2355
+ conditionalFieldsVisible.delete(key);
2356
+ }
2357
+ });
2358
+ }
2359
+
2360
+ // EXECUTAR AÇÃO PENDENTE
2361
+ function executePendingAction(action) {
2362
+ console.log(`🚀 Executando ação: ${action.type}`);
2363
+
2364
+ switch (action.type) {
2365
+ case 'next_step':
2366
+ executeNextStep();
2367
+ break;
2368
+
2369
+ case 'specific_section':
2370
+ executeSpecificSection(action.target);
2371
+ break;
2372
+
2373
+ case 'skip_to_end':
2374
+ executeSkipToEnd();
2375
+ break;
2376
+ }
2377
+ }
2378
+
2379
+ // EXECUTAR PRÓXIMA ETAPA
2380
+ function executeNextStep() {
2381
+ console.log(`➡️ Indo para próxima etapa`);
2382
+
2383
+ if (currentStep < formSteps) {
2384
+ currentStep++;
2385
+ showStep(currentStep);
2386
+ } else {
2387
+ const form = document.getElementById('wagtailForm');
2388
+ if (form) {
2389
+ form.submit();
2390
+ }
2391
+ }
2392
+ }
2393
+
2394
+ // EXECUTAR SEÇÃO ESPECÍFICA
2395
+ function executeSpecificSection(sectionTitle) {
2396
+ console.log(`🎯 Redirecionando para: "${sectionTitle}"`);
2397
+
2398
+ const success = redirectToSpecificSection(sectionTitle);
2399
+ if (!success) {
2400
+ console.log(`⚠️ Seção não encontrada, indo para próxima etapa`);
2401
+ executeNextStep();
2402
+ }
2403
+ }
2404
+
2405
+ // EXECUTAR PULAR PARA O FINAL
2406
+ function executeSkipToEnd() {
2407
+ console.log(`⏭️ Pulando para o final`);
2408
+
2409
+ const form = document.getElementById('wagtailForm');
2410
+ if (form) {
2411
+ let skipField = form.querySelector('input[name="form_multi_redirected"]');
2412
+ if (!skipField) {
2413
+ skipField = document.createElement('input');
2414
+ skipField.type = 'hidden';
2415
+ skipField.name = 'form_multi_redirected';
2416
+ form.appendChild(skipField);
2417
+ }
2418
+ skipField.value = 'true';
2419
+ }
2420
+
2421
+ currentStep = totalSteps - 1;
2422
+ showStep(currentStep);
2423
+
2424
+ // Auto-submeter após delay
2425
+ setTimeout(() => {
2426
+ if (form) {
2427
+ console.log('📨 Auto-submetendo formulário');
2428
+ form.submit();
2429
+ }
2430
+ }, 1500);
2431
+ }
2432
+
2433
+ // MODIFICAR VALIDAÇÃO PARA CONSIDERAR AÇÕES PENDENTES
2434
+ const originalValidateCurrentStep = validateCurrentStep;
2435
+ validateCurrentStep = function() {
2436
+ // Executar ações pendentes antes da validação
2437
+ if (pendingActions.size > 0) {
2438
+ console.log(`🔀 ${pendingActions.size} ações pendentes`);
2439
+
2440
+ const actions = Array.from(pendingActions.values());
2441
+ pendingActions.clear();
2442
+
2443
+ // Limpar indicadores visuais
2444
+ document.querySelectorAll('.action-pending').forEach(group => {
2445
+ group.classList.remove('action-pending');
2446
+ group.removeAttribute('data-pending-action');
2447
+ });
2448
+
2449
+ if (actions.length > 0) {
2450
+ setTimeout(() => executePendingAction(actions[0]), (actions[0].delay || 1) * 1000);
2451
+ return true;
2452
+ }
2453
+ }
2454
+
2455
+ return originalValidateCurrentStep();
2456
+ };
2457
+
2458
+ // MODIFICAR NEXTSTEP PARA CONSIDERAR AÇÕES
2459
+ const originalNextStep = nextStep;
2460
+ nextStep = function() {
2461
+ if (pendingActions.size > 0) {
2462
+ console.log('🔀 Executando ações pendentes...');
2463
+
2464
+ const actions = Array.from(pendingActions.values());
2465
+ pendingActions.clear();
2466
+
2467
+ // Limpar indicadores visuais
2468
+ document.querySelectorAll('.action-pending').forEach(group => {
2469
+ group.classList.remove('action-pending');
2470
+ group.removeAttribute('data-pending-action');
2471
+ });
2472
+
2473
+ if (actions.length > 0) {
2474
+ executePendingAction(actions[0]);
2475
+ return;
2476
+ }
2477
+ }
2478
+
2479
+ originalNextStep();
2480
+ };
2481
+
2482
+ // FUNÇÃO PARA REDIRECIONAR PARA SEÇÃO ESPECÍFICA (reutilizada)
2483
+ function redirectToSpecificSection(sectionTitle) {
2484
+ console.log(`🎯 Procurando seção: "${sectionTitle}"`);
2485
+
2486
+ const dividers = document.querySelectorAll('[data-block-type="divider"], .divider-title');
2487
+
2488
+ for (const divider of dividers) {
2489
+ let dividerTitle = '';
2490
+
2491
+ if (divider.classList.contains('divider-title')) {
2492
+ dividerTitle = divider.textContent?.trim() || '';
2493
+ } else {
2494
+ const titleElement = divider.querySelector('.divider-title');
2495
+ if (titleElement) {
2496
+ dividerTitle = titleElement.textContent?.trim() || '';
2497
+ }
2498
+ }
2499
+
2500
+ if (dividerTitle.toLowerCase().includes(sectionTitle.toLowerCase()) ||
2501
+ sectionTitle.toLowerCase().includes(dividerTitle.toLowerCase())) {
2502
+
2503
+ console.log(`✅ Seção encontrada: "${dividerTitle}"`);
2504
+
2505
+ let stepElement = divider;
2506
+ while (stepElement && !stepElement.classList.contains('step-content')) {
2507
+ stepElement = stepElement.parentElement;
2508
+ }
2509
+
2510
+ if (stepElement && stepElement.id) {
2511
+ const stepMatch = stepElement.id.match(/step(\d+)/);
2512
+ if (stepMatch) {
2513
+ const targetStep = parseInt(stepMatch[1]);
2514
+
2515
+ if (targetStep >= 1 && targetStep <= formSteps) {
2516
+ currentStep = targetStep;
2517
+ showStep(currentStep);
2518
+
2519
+ setTimeout(() => {
2520
+ const formContent = document.getElementById('formContent');
2521
+ if (formContent) {
2522
+ const offset = 150;
2523
+ const elementTop = divider.offsetTop - offset;
2524
+
2525
+ formContent.scrollTo({
2526
+ top: Math.max(0, elementTop),
2527
+ behavior: 'smooth'
2528
+ });
2529
+ }
2530
+ }, 300);
2531
+
2532
+ return true;
2533
+ }
2534
+ }
2535
+ }
2536
+ }
2537
+ }
2538
+
2539
+ console.log(`❌ Seção "${sectionTitle}" não encontrada`);
2540
+ return false;
2541
+ }
2542
+
2543
+ // INICIALIZAÇÃO
2544
+ document.addEventListener('DOMContentLoaded', function() {
2545
+ setTimeout(() => {
2546
+ initializeMultiRedirectFields();
2547
+ }, 300);
2548
+ });
2549
+
2550
+ // DEBUGGING
2551
+ window.debugMultiRedirect = {
2552
+ fields: () => multiRedirectFields,
2553
+ pending: () => pendingActions,
2554
+ conditionals: () => conditionalFieldsVisible,
2555
+ testSection: (name) => redirectToSpecificSection(name),
2556
+ clearAll: () => {
2557
+ pendingActions.clear();
2558
+ conditionalFieldsVisible.clear();
2559
+ document.querySelectorAll('.action-pending').forEach(group => {
2560
+ group.classList.remove('action-pending');
2561
+ group.removeAttribute('data-pending-action');
2562
+ });
2563
+ console.log('🧹 Multi-redirect limpo');
2564
+ },
2565
+ executeAction: (type, target) => {
2566
+ executePendingAction({ type: type, target: target });
2567
+ }
2568
+ };
2094
2569
 
2570
+ console.log('🔀 Sistema Multi-Redirecionamento Avançado carregado');
2571
+ console.log('🔧 Debug: window.debugMultiRedirect');
2095
2572
 
2096
2573
  </script>
2097
2574
  {% endif %}