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.
 
 
 
 
 

125 lines
4.2 KiB

import './scss/leitura-materia.scss'
import Vue from 'vue'
import VueCompositionApi from '@vue/composition-api'
import { PiniaVuePlugin, createPinia } from 'pinia'
import axios from 'axios'
import { usePainelStore } from '../painel/store/painelStore'
import { isPermanentCloseCode, permanentCloseMessage, nextBackoffDelay, INITIAL_BACKOFF_MS, DISCONNECTED_MESSAGE } from '../painel/ws/painelSocket'
import LeituraMateria from '../../components/leitura-materia/LeituraMateria.vue'
import WsStatusBanner from '../../components/painel/WsStatusBanner.vue'
Vue.component('leitura-materia', LeituraMateria)
Vue.component('ws-status-banner', WsStatusBanner)
axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = 'X-CSRFToken'
Vue.use(VueCompositionApi)
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
new Vue({ // eslint-disable-line
pinia,
delimiters: ['[[', ']]'],
el: '#leitura-materia',
data () {
return {
sessaoId: null,
oid: null,
mid: null,
fase: 'ordem',
initialObservacao: '',
initialMateriaTexto: '',
initialMateriaEmenta: '',
cancelUrl: '#',
ws: null,
reconnectTimer: null,
reconnectDelay: INITIAL_BACKOFF_MS,
wsStatus: 'connecting',
wsErrorMessage: 'Conectando ao servidor de tempo real…',
error_message: ''
}
},
mounted () {
const el = this.$el
this.sessaoId = el.dataset.sessaoId
this.oid = el.dataset.oid
this.mid = el.dataset.mid
this.fase = el.dataset.fase || 'ordem'
this.initialObservacao = el.dataset.observacao || ''
this.initialMateriaTexto = el.dataset.materiaTexto || ''
this.initialMateriaEmenta = el.dataset.materiaEmenta || ''
// Mesma URL da tela legada (AbstractLeituraView.cancel_url) —
// iso=1 identifica o fluxo de OrdemDia, iso=0 Expediente.
const iso = this.fase === 'expediente' ? 0 : 1
this.cancelUrl = `/sessao/${this.sessaoId}/${iso}/${this.oid}/retirar-leitura`
if (this.sessaoId) {
this.connectWS()
}
},
methods: {
painelStore () {
return usePainelStore()
},
actionUrl () {
const etapa = this.fase === 'expediente' ? 'expediente' : 'ordemdia'
return `/sessao/${this.sessaoId}/materia/${etapa}/leitura/v2/${this.oid}/${this.mid}/salvar`
},
wsURL () {
const proto = location.protocol === 'https:' ? 'wss' : 'ws'
return `${proto}://${location.host}/ws/painel/${this.sessaoId}/`
},
connectWS () {
this.ws = new WebSocket(this.wsURL())
this.ws.addEventListener('open', () => {
this.wsStatus = 'open'
this.wsErrorMessage = ''
this.reconnectDelay = INITIAL_BACKOFF_MS
})
this.ws.addEventListener('message', (message) => {
try {
const data = JSON.parse(message.data)
if (data.type === 'data') {
this.painelStore().applyData(data.payload)
}
} catch (e) {
console.error('Leitura materia WS parse error:', e)
}
})
this.ws.addEventListener('close', (e) => {
if (isPermanentCloseCode(e.code)) {
this.wsStatus = 'error'
this.wsErrorMessage = permanentCloseMessage(e.code)
return
}
this.wsStatus = 'reconnecting'
this.wsErrorMessage = DISCONNECTED_MESSAGE
this.reconnectTimer = setTimeout(() => this.connectWS(), this.reconnectDelay)
this.reconnectDelay = nextBackoffDelay(this.reconnectDelay)
})
},
onSalvar (data) {
axios.post(this.actionUrl(), data, {
headers: { 'Content-Type': 'application/json' }
})
.then(response => {
if (response.data.redirect_url) {
window.location.href = response.data.redirect_url
}
})
.catch(error => {
const respData = error.response && error.response.data
this.error_message = (respData && respData.message) || 'Erro ao registrar a leitura. Tente novamente.'
})
},
onCancelar () {
// O próprio <a :href> do componente já navega — nada a fazer aqui.
},
beforeDestroy () {
if (this.reconnectTimer) clearTimeout(this.reconnectTimer)
if (this.ws) this.ws.close()
}
}
})