Sistema de Apoio ao Processo Legislativo
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

127 lines
4.5 KiB

// frontend/src/__apps/painel/ws/normalizePainel.js
//
// Normaliza o payload `type: "data"` recebido via WebSocket para um shape
// estável e tolerante a payload parcial. A partir da adoção do backend de
// feat/painel-websockets, o payload é o dict flat produzido por
// sapl/painel/views.py::build_dados_painel() — o mesmo usado pelo polling
// HTTP legado e pinado pelos testes sapl/painel/tests/test_broadcasts.py e
// test_consumers.py, então essa função nunca deve mudar de formato; toda
// adaptação de shape vive aqui, não em build_dados_painel().
export const DEFAULT_STATE = Object.freeze({
sessao_aberta: false,
painel_aberto: false,
mostrar_voto: false,
message: '',
sessao: {
sessao_plenaria: '',
sessao_plenaria_data: '',
sessao_plenaria_hora_inicio: '',
sessao_solene: false,
tema_solene: '',
brasao: ''
},
cronometro_discurso: '',
cronometro_aparte: '',
cronometro_ordem: '',
cronometro_consideracoes: '',
parlamentares: [],
oradores: [],
materia: {},
resultado: {
numero_votos: {}
},
// Populado uma vez, a partir do contexto inicial renderizado pelo Django
// (não vem no payload do WebSocket) — ver GAP 3 do plano de merge.
// applyData() preserva o valor atual quando o payload não traz a lista.
tipos_resultado: []
})
function asObject (v) {
return v && typeof v === 'object' ? v : {}
}
function asArray (v) {
return Array.isArray(v) ? v : []
}
function asString (v, fallback) {
return v != null ? v : fallback
}
export function normalizePainelData (raw) {
const d = asObject(raw)
const parlamentares = asArray(d.presentes)
.filter((p) => p && typeof p === 'object')
.map((p) => ({
id: p.id,
parlamentar_id: p.parlamentar_id,
nome_parlamentar: asString(p.nome, ''),
filiacao: asString(p.partido, ''),
fotografia: p.fotografia != null ? p.fotografia : false,
voto: p.voto != null ? p.voto : ''
}))
const oradores = asArray(d.oradores)
.filter((o) => o && typeof o === 'object')
.map((o) => ({
ordem_pronunciamento: o.numero,
nome_parlamentar: asString(o.nome, '')
}))
console.log(d.sessao_iniciada);
return {
// sessao_iniciada vem de sessao.iniciada is not False (True ou None
// contam como "iniciada" — sessões legadas ficaram com None, mesma
// convenção de restringe_sessoes_visiveis() no backend).
sessao_aberta: !!d.sessao_iniciada && !d.sessao_finalizada,
painel_aberto: d.status_painel != null ? !!d.status_painel : DEFAULT_STATE.painel_aberto,
mostrar_voto: d.mostrar_voto != null ? !!d.mostrar_voto : DEFAULT_STATE.mostrar_voto,
message: asString(d.msg_painel, DEFAULT_STATE.message),
sessao: {
sessao_plenaria: asString(d.sessao_plenaria, DEFAULT_STATE.sessao.sessao_plenaria),
sessao_plenaria_data: asString(d.sessao_plenaria_data, DEFAULT_STATE.sessao.sessao_plenaria_data),
sessao_plenaria_hora_inicio: asString(d.sessao_plenaria_hora_inicio, DEFAULT_STATE.sessao.sessao_plenaria_hora_inicio),
sessao_solene: d.sessao_solene != null ? !!d.sessao_solene : DEFAULT_STATE.sessao.sessao_solene,
tema_solene: asString(d.tema_solene, DEFAULT_STATE.sessao.tema_solene),
brasao: asString(d.brasao, DEFAULT_STATE.sessao.brasao)
},
cronometro_discurso: asString(d.cronometro_discurso, DEFAULT_STATE.cronometro_discurso),
cronometro_aparte: asString(d.cronometro_aparte, DEFAULT_STATE.cronometro_aparte),
cronometro_ordem: asString(d.cronometro_ordem, DEFAULT_STATE.cronometro_ordem),
cronometro_consideracoes: asString(d.cronometro_consideracoes, DEFAULT_STATE.cronometro_consideracoes),
parlamentares,
oradores,
materia: {
texto: asString(d.materia_legislativa_texto, ''),
ementa: asString(d.materia_legislativa_ementa, ''),
observacao: asString(d.observacao_materia, ''),
resultado_votacao: asString(d.tipo_resultado, '')
},
resultado: {
numero_votos: {
num_presentes: d.num_presentes != null ? d.num_presentes : parlamentares.length,
votos_sim: d.numero_votos_sim != null ? d.numero_votos_sim : 0,
votos_nao: d.numero_votos_nao != null ? d.numero_votos_nao : 0,
abstencoes: d.numero_abstencoes != null ? d.numero_abstencoes : 0,
total_votos: d.total_votos != null ? d.total_votos : 0
}
},
// Nunca vem no payload do WebSocket — applyData() só sobrescreve o
// valor atual do store quando esta lista não está vazia.
tipos_resultado: asArray(d.tipos_resultado)
}
}