Skip to content

Commit

Permalink
Merge pull request #159 from jonatasrs/super-sei
Browse files Browse the repository at this point in the history
Versão 5.0 - Torna a extensão compatível com o SEI/SUPER 4.0
  • Loading branch information
jonatasrs authored Sep 5, 2022
2 parents 98f117a + d0a0eef commit 3a6863b
Show file tree
Hide file tree
Showing 127 changed files with 3,600 additions and 2,898 deletions.
45 changes: 0 additions & 45 deletions background.js

This file was deleted.

71 changes: 71 additions & 0 deletions background/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { getLocalStorage } from '../lib/core/tools.js'
import { fetchRoot, fetchSei, getActionUrl } from './fetchSei.js'

async function fetchListaDetalhada (newUrl = null) {
const url = newUrl || await getActionUrl('procedimento_controlar')

const formData = new URLSearchParams()
formData.append('hdnTipoVisualizacao', 'D')
const options = {
method: 'POST',
body: formData
}

const html = await fetchSei(url, options)
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
const form = doc.querySelector('#frmProcedimentoControlar')
const tipoVisualizacao = form.querySelector('#hdnTipoVisualizacao').value
if (tipoVisualizacao === 'D') {
return doc
} else if (tipoVisualizacao === 'R' && newUrl === null) {
const storage = await getLocalStorage()

const formUrl = storage.baseUrl + form.getAttribute('action')
return fetchListaDetalhada(formUrl)
} else {
throw Error('Erro ao obter a lista detalhada')
}
}

export async function listarProcessos () {
const doc = await fetchListaDetalhada()
const table = doc.querySelector('#tblProcessosDetalhado')

if (!table) return []

const rows = table.querySelectorAll('tbody > tr[id]')

const json = [...rows].map(row => {
// const linkAnotacao = row.querySelector('td:nth-child(2) > a[href*="acao=anotacao_registrar"]')
// const anotacao = linkAnotacao ? linkAnotacao.attributes.onmouseover.value : '\'\',\'\''
// const [dscAnotacao, usrAnotacao] = anotacao.replaceAll('\'', '')

const result = {
id: row.id,
numProcesso: row.querySelector('td:nth-child(3) > a').innerText,
processoVisualizado: row.querySelector('td:nth-child(3) > a').classList.contains('processoVisualizado'),
processoVisitado: row.querySelector('td:nth-child(3) > a').classList.contains('processoVisitado'),
atribuido: row.querySelector('td:nth-child(4) > a')?.innerText || '',
tipoProcesso: row.querySelector('td:nth-child(5)').innerText,
interessados: [...row.querySelectorAll('td:nth-child(6) .spanItemCelula')].map(e => e.innerText),
anotacao: {
descricao: '',
usuario: ''
},
marcador: {
titulo: '',
descricao: ''
},
especificacao: ''
}
return result
})
return json
}

export async function isAuthenticated (baseUrl) {
const doc = await fetchRoot(baseUrl)
const frmLogin = doc.querySelector('#frmLogin')
return !frmLogin
}
32 changes: 32 additions & 0 deletions background/fetchSei.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { getLocalStorage } from '../lib/core/tools.js'

export async function fetchSei (url, options = { method: 'GET' }) {
const resp = await fetch(url, options)
if (resp.ok) {
// const contentType = resp.headers.get('content-type')
const buffer = await resp.arrayBuffer()
const body = new TextDecoder('ISO-8859-1').decode(buffer)
return body
}
}

/**
*
* @param {String} baseUrl URL base do SEI (Default: storage.baseUrl)
* @returns {Document} DOM document
*/
export async function fetchRoot (baseUrl = null) {
const storage = await getLocalStorage()
baseUrl = baseUrl || storage.baseUrl
const parser = new DOMParser()
const html = await fetchSei(baseUrl)
return parser.parseFromString(html, 'text/html')
}

export async function getActionUrl (actionName) {
const storage = await getLocalStorage()
const doc = await fetchRoot()
const menu = doc.querySelector('#main-menu, #infraMenu')
const link = menu.querySelector(`li > a[href*="acao=${actionName}"]`)
return `${storage.baseUrl}${link.getAttribute('href')}`
}
12 changes: 12 additions & 0 deletions background/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
</head>

<body>
<script type="module" src="main.js"></script>
</body>

</html>
18 changes: 18 additions & 0 deletions background/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import '../lib/core/core.js'
import { handleInstalled } from '../lib/core/tools.js'
import { initServices } from './services.js'

/******************************************************************************
SEI ++: Script que adiciona novas funcionalidades ao SEI
Autor: Jonatas Evaristo
*******************************************************************************/

browser.runtime.onInstalled.addListener(handleInstalled)

if (!window.isChrome) {
browser.runtime.getBrowserInfo().then(function (info) {
browser.storage.local.set({ version: info.version }).then(null, null)
})
}

initServices()
115 changes: 115 additions & 0 deletions background/notifyProcessos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { browserActionGetBadgeText, clearAlarm, getAlarms, getLocalStorage } from '../lib/core/tools.js'
import { isAuthenticated, listarProcessos } from './api.js'

const periodInMinutes = 5
const alarmName = 'notifyProcessos'
const browserAction = {
enabled: false,
status: 'Desativado',
qtdNaoVisualizado: null
}

/**
* Envia notificações ao sistema
* @param {Object} message Mensagem {title: '', description: ''}
*/
function notify (message) {
browser.notifications.create(
'notifyProcessos',
{
type: 'basic',
iconUrl: browser.runtime.getURL('icons/seipp.png'),
title: message.title,
message: message.description
}
)
}

async function notifyProcessos () {
const lista = await listarProcessos()
browserAction.qtdNaoVisualizado = lista.filter(e => !e.processoVisualizado).length
browserAction.enabled = true
browserAction.status = 'Ativado'
if (browserAction.qtdNaoVisualizado) {
const count = Number(await browserActionGetBadgeText({}))
if (!count) {
notify({ title: 'Processos', description: 'Novo processo' })
browser.browserAction.setBadgeText({ text: '1' })
}
}
browser.storage.local.set({ browserAction })
}

async function alarmNotifyProcessos (alarmInfo) {
try {
await notifyProcessos()
} catch (error) {
const authenticated = await isAuthenticated()
if (!authenticated) {
browserAction.enabled = true
browserAction.status = 'Não autenticado'
browserAction.qtdNaoVisualizado = null
browser.storage.local.set({ browserAction })
const badgeText = await browserActionGetBadgeText({})
if (badgeText !== 'login') {
notify({
title: 'Erro ao checar processos',
description: 'Usuário não está autenticado no SEI/SUPER'
})
browser.browserAction.setBadgeText({ text: 'login' })
}
} else {
const result = await disableNotifyProcessos()
console.error(alarmInfo.name, result, error)
notify({
title: 'Erro ao checar processos',
description: `Erro ao carregar dados: ${error}`
})
}
}
}

async function enableNotifyProcessos () {
browser.alarms.onAlarm.addListener(alarmNotifyProcessos)
browser.alarms.create(alarmName, { periodInMinutes })
await alarmNotifyProcessos({ name: alarmName })
}

async function disableNotifyProcessos () {
browserAction.enabled = false
browserAction.status = 'Desativado'
browserAction.qtdNaoVisualizado = 0
browser.storage.local.set({ browserAction })
browser.browserAction.setBadgeText({ text: '' })
await clearAlarm(alarmName)
}

export async function notifyReceivedMenssage (message) {
if (message.from === 'browserAction') {
browser.browserAction.setBadgeText({ text: '' })
} else if (message.from === 'seippOptionsSave') {
const storage = await getLocalStorage()
if (storage.CheckTypes?.includes('notificacoes')) {
const alarm = await getAlarms(alarmName)
if (!alarm) enableNotifyProcessos()
} else {
disableNotifyProcessos()
}
}
}

export async function serviceNotify () {
const storage = await getLocalStorage()
if (storage.CheckTypes?.includes('notificacoes') && storage.baseUrl) {
const alarm = await getAlarms(alarmName)
if (alarm) await clearAlarm(alarmName)
enableNotifyProcessos()
} else {
disableNotifyProcessos()
}
}

export async function notifyOnClicked () {
const storage = await getLocalStorage()
browser.tabs.create({ url: storage.baseUrl })
}
21 changes: 21 additions & 0 deletions background/services.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { notifyOnClicked, notifyReceivedMenssage, serviceNotify } from './notifyProcessos.js'

export async function initServices () {
serviceNotify()
}

/** Handle de mensagens recebidas */
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.from === 'browserAction') {
notifyReceivedMenssage(message)
} else if (message.from === 'seippOptionsSave') {
notifyReceivedMenssage(message)
}
})

/** Handle de click nas notificações */
browser.notifications.onClicked.addListener(function (notificationId) {
if (notificationId === 'notifyProcessos') {
notifyOnClicked()
}
})
22 changes: 22 additions & 0 deletions browser_action/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css"/>
<script type="module" src="main.js"></script>
</head>

<body>
<h3 id="title">SEI++</h3>
<div id="popup-content">
<div class="field"><label>Notificações:</label><span id="status-notify" class="red">Desativadas</span></div>

<div id="processo-novo" class="field"><label>Processos novos:</label><span>0</span></div>

<button id="btn-processos">Abrir controle de processos</button>
</div>
<div id="hostname"></div>
</body>

</html>
30 changes: 30 additions & 0 deletions browser_action/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import '../lib/core/core.js'
import { getLocalStorage } from '../lib/core/tools.js'

export async function checkEnable () {
const storage = await getLocalStorage()
const { qtdNaoVisualizado, enabled, status } = storage.browserAction
const statusNotify = document.querySelector('#status-notify')
statusNotify.textContent = status
statusNotify.className = status === 'Ativado' ? 'green' : 'red'
document.querySelector('#processo-novo').style.display = enabled ? null : 'none'
if (enabled) {
document.querySelector('#processo-novo > span').textContent = qtdNaoVisualizado
document.querySelector('#hostname').textContent = storage.baseUrl
document.querySelector('#btn-processos').style.display = null
document.querySelector('#btn-processos').addEventListener('click', () => openControleProcesso(storage.baseUrl))
} else {
document.querySelector('#btn-processos').style.display = 'none'
}
}

function openControleProcesso (baseUrl) {
browser.tabs.create({ url: baseUrl })
}

checkEnable()

browser.runtime.sendMessage({
from: 'browserAction',
text: 'Action Clicked'
})
Loading

0 comments on commit 3a6863b

Please sign in to comment.