mirror of https://github.com/interlegis/sapl.git
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
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)
|
|
}
|
|
}
|
|
|