mirror of https://github.com/interlegis/sapl.git
Browse Source
* config inicial * impl channels tutorial 1 e 2 * corrige versão do redis * impl tutorial 3 * impl time-refresh websocket * add view para apps frontend * corrige teste de app do sapl * renomeia view para entry_point_view * add redis no docker compose e no travis * configura ativação para channels * add comunicação websocket ao nginx * change frontend * corrige porta do postgres * descomenta código de configuração do logging * rename view and urls from app frontend * corrige teste e url para app online * adequa leitura de query_string para asgirequest * nova versão do frontend * inclui teste de https no wspull/2601/head
Leandro Roberto Silva
6 years ago
committed by
Edward
56 changed files with 929 additions and 355 deletions
@ -0,0 +1,46 @@ |
|||
#!/bin/bash |
|||
|
|||
# As seen in http://tutos.readthedocs.org/en/latest/source/ndg.html |
|||
|
|||
SAPL_DIR="/var/interlegis/sapl" |
|||
|
|||
# Seta um novo diretório foi passado como raiz para o SAPL |
|||
# caso esse tenha sido passado como parâmetro |
|||
if [ "$1" ] |
|||
then |
|||
SAPL_DIR="$1" |
|||
fi |
|||
|
|||
NAME="SAPL" # Name of the application (*) |
|||
DJANGODIR=/var/interlegis/sapl/ # Django project directory (*) |
|||
SOCKFILE=/var/interlegis/sapl/run/daphne.sock # we will communicate using this unix socket (*) |
|||
USER=`whoami` # the user to run as (*) |
|||
GROUP=`whoami` # the group to run as (*) |
|||
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn (*) |
|||
# NUM_WORKERS = 2 * CPUS + 1 |
|||
TIMEOUT=60 |
|||
MAX_REQUESTS=100 # number of requests before restarting worker |
|||
DJANGO_SETTINGS_MODULE=sapl.settings # which settings file should Django use (*) |
|||
DJANGO_ASGI_MODULE=sapl.asgi # WSGI module name (*) |
|||
|
|||
echo "Starting $NAME as `whoami` on base dir $SAPL_DIR" |
|||
|
|||
# parameter can be passed to run without virtualenv |
|||
if [[ "$@" != "no-venv" ]]; then |
|||
# Activate the virtual environment |
|||
cd $DJANGODIR |
|||
source /var/interlegis/.virtualenvs/sapl/bin/activate |
|||
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE |
|||
export PYTHONPATH=$DJANGODIR:$PYTHONPATH |
|||
fi |
|||
|
|||
# Create the run directory if it doesn't exist |
|||
RUNDIR=$(dirname $SOCKFILE) |
|||
test -d $RUNDIR || mkdir -p $RUNDIR |
|||
|
|||
# Start your Django Unicorn |
|||
exec daphne \ |
|||
-u $SOCKFILE ${DJANGO_ASGI_MODULE}:application \ |
|||
--access-log /var/log/sapl/daphne_access.log \ |
|||
-v2 |
|||
|
@ -0,0 +1,14 @@ |
|||
""" |
|||
ASGI entrypoint. Configures Django and then runs the application |
|||
defined in the ASGI_APPLICATION setting. |
|||
""" |
|||
|
|||
import os |
|||
|
|||
from channels.routing import get_default_application |
|||
import django |
|||
|
|||
|
|||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sapl.settings") |
|||
django.setup() |
|||
application = get_default_application() |
@ -0,0 +1,139 @@ |
|||
import json |
|||
|
|||
from asgiref.sync import async_to_sync |
|||
from channels.generic.websocket import AsyncWebsocketConsumer, WebsocketConsumer |
|||
from channels.layers import get_channel_layer |
|||
from django.db.models.signals import post_save, post_delete, pre_delete |
|||
from django.dispatch.dispatcher import receiver |
|||
|
|||
|
|||
class TimeRefreshConsumer(AsyncWebsocketConsumer): |
|||
|
|||
async def connect(self): |
|||
self.room_name = 'time_refresh_channel' |
|||
self.room_group_name = 'group_%s' % self.room_name |
|||
|
|||
# Join room group |
|||
await self.channel_layer.group_add( |
|||
self.room_group_name, |
|||
self.channel_name |
|||
) |
|||
|
|||
await self.accept() |
|||
|
|||
async def disconnect(self, close_code): |
|||
await self.channel_layer.group_discard( |
|||
self.room_group_name, |
|||
self.channel_name |
|||
) |
|||
|
|||
# Receive message from WebSocket |
|||
async def receive(self, text_data): |
|||
text_data_json = json.loads(text_data) |
|||
message = text_data_json['message'] |
|||
|
|||
# Send message to room group |
|||
await self.channel_layer.group_send( |
|||
self.room_group_name, |
|||
{ |
|||
'type': 'time_refresh_message', |
|||
'message': message |
|||
} |
|||
) |
|||
|
|||
# Receive message from room group |
|||
async def time_refresh_message(self, event): |
|||
message = event['message'] |
|||
|
|||
# Send message to WebSocket |
|||
await self.send(text_data=json.dumps({ |
|||
'message': message |
|||
})) |
|||
|
|||
|
|||
class ChatConsumer(AsyncWebsocketConsumer): |
|||
async def connect(self): |
|||
self.room_name = self.scope['url_route']['kwargs']['room_name'] |
|||
self.room_group_name = 'chat_%s' % self.room_name |
|||
|
|||
# Join room group |
|||
await self.channel_layer.group_add( |
|||
self.room_group_name, |
|||
self.channel_name |
|||
) |
|||
|
|||
await self.accept() |
|||
|
|||
async def disconnect(self, close_code): |
|||
# Leave room group |
|||
await self.channel_layer.group_discard( |
|||
self.room_group_name, |
|||
self.channel_name |
|||
) |
|||
|
|||
# Receive message from WebSocket |
|||
async def receive(self, text_data): |
|||
text_data_json = json.loads(text_data) |
|||
message = text_data_json['message'] |
|||
|
|||
# Send message to room group |
|||
await self.channel_layer.group_send( |
|||
self.room_group_name, |
|||
{ |
|||
'type': 'chat_message', |
|||
'message': message |
|||
} |
|||
) |
|||
|
|||
# Receive message from room group |
|||
async def chat_message(self, event): |
|||
message = event['message'] |
|||
|
|||
# Send message to WebSocket |
|||
await self.send(text_data=json.dumps({ |
|||
'message': message |
|||
})) |
|||
|
|||
|
|||
class ChatConsumer__tutorial2(WebsocketConsumer): |
|||
def connect(self): |
|||
self.room_name = self.scope['url_route']['kwargs']['room_name'] |
|||
self.room_group_name = 'chat_%s' % self.room_name |
|||
|
|||
# Join room group |
|||
async_to_sync(self.channel_layer.group_add)( |
|||
self.room_group_name, |
|||
self.channel_name |
|||
) |
|||
|
|||
self.accept() |
|||
|
|||
def disconnect(self, close_code): |
|||
# Leave room group |
|||
async_to_sync(self.channel_layer.group_discard)( |
|||
self.room_group_name, |
|||
self.channel_name |
|||
) |
|||
|
|||
# Receive message from WebSocket |
|||
def receive(self, text_data): |
|||
text_data_json = json.loads(text_data) |
|||
message = text_data_json['message'] |
|||
|
|||
# Send message to room group |
|||
async_to_sync(self.channel_layer.group_send)( |
|||
self.room_group_name, |
|||
{ |
|||
'type': 'chat_message', |
|||
'message': message |
|||
} |
|||
) |
|||
|
|||
# Receive message from room group |
|||
def chat_message(self, event): |
|||
message = event['message'] |
|||
|
|||
# Send message to WebSocket |
|||
self.send(text_data=json.dumps({ |
|||
'message': message |
|||
})) |
@ -0,0 +1,9 @@ |
|||
from django.conf.urls import url |
|||
|
|||
from . import consumers |
|||
|
|||
websocket_urlpatterns = [ |
|||
url(r'^ws/chat/(?P<room_name>[^/]+)/$', consumers.ChatConsumer), |
|||
|
|||
url(r'^ws/time-refresh/$', consumers.TimeRefreshConsumer), |
|||
] |
@ -0,0 +1,12 @@ |
|||
from channels.auth import AuthMiddlewareStack |
|||
from channels.routing import ProtocolTypeRouter, URLRouter |
|||
import sapl.base.routing |
|||
|
|||
|
|||
application = ProtocolTypeRouter({ |
|||
'websocket': AuthMiddlewareStack( |
|||
URLRouter( |
|||
sapl.base.routing.websocket_urlpatterns |
|||
) |
|||
), |
|||
}) |
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@ |
|||
.container-messages[data-v-26b3e554]{position:fixed;bottom:0;right:1rem;z-index:10001} |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 4.3 KiB |
@ -0,0 +1 @@ |
|||
(window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-2d0c4a82"],{"3c84":function(e,n,s){"use strict";s.r(n);var a={name:"sessao-plenaria-module"},t=s("0c7c"),c=Object(t.a)(a,function(){var e=this.$createElement,n=this._self._c||e;return n("div",{staticClass:"online-sessaolenaria"},[n("router-view")],1)},[],!1,null,null,null);n.default=c.exports}}]); |
Binary file not shown.
@ -0,0 +1 @@ |
|||
(window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-2d0e8be2"],{"8b24":function(n,e,t){"use strict";t.r(e);var a={name:"index",data:function(){return{}}},i=t("0c7c"),c=Object(i.a)(a,function(){var n=this.$createElement;return(this._self._c||n)("div",[this._v("\n teste de página para dentro do main - INDEX INDEX\n")])},[],!1,null,null,null);e.default=c.exports}}]); |
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -0,0 +1 @@ |
|||
(window.webpackJsonp=window.webpackJsonp||[]).push([["chunk-4cf2dae1"],{3713:function(t,s,a){"use strict";(function(t){var e=a("975e");s.a={name:"sessao-plenaria-item-list",props:["sessao"],data:function(){return{utils:e.a.Utils,app:["sessao","parlamentares"],model:["sessaoplenaria","sessaolegislativa","tiposessaoplenaria","legislatura"],data_inicio:new Date,sessao_legislativa:{numero:""},tipo:{nome:""},legislatura:{numero:""},metadata:{sessao_legislativa:{app:"parlamentares",model:"sessaolegislativa",id:this.sessao.sessao_legislativa},legislatura:{app:"parlamentares",model:"legislatura",id:this.sessao.legislatura},tipo:{app:"sessao",model:"tiposessaoplenaria",id:this.sessao.tipo}}}},watch:{sessao:function(t){this.updateSessao(),this.fetch()}},computed:{titulo:function(){var t=this.sessao,s=this.tipo,a=this.data_inicio;return"".concat(t.numero,"ª ").concat(s.nome," da \n ").concat(a.getDate()>15?2:1,"ª Quizena do Mês de \n ").concat(this.month_text(a.getMonth())," de \n ").concat(a.getFullYear(),"\n ")},subtitulo:function(){return"".concat(this.sessao_legislativa.numero,"ª Sessão Legislativa da \n ").concat(this.legislatura.numero,"ª Legislatura")},date_text:function(){return"".concat(this.data_inicio.getDate()," de \n ").concat(this.month_text(this.data_inicio.getMonth())," de\n ").concat(this.data_inicio.getFullYear()," – ").concat(this.sessao.hora_inicio)}},methods:{sendStore:function(){this.insertInState({app:"sessao",model:"sessaoplenaria",id:this.sessao.id,value:this.sessao})},month_text:function(t){return["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"][t]},fetch:function(){var s=this;t.mapKeys(s.metadata,function(t,a){var e=s.metadata[a];e.component=s;var i=s.getModel(e);null===i?s.insertInState(e).then(function(t){s[a]=s.getModel(e)[e.id]}):void 0===i[e.id]?s.$nextTick().then(function(){setTimeout(function(){s.fetch()},100)}):s[a]=i[e.id]})},updateSessao:function(){this.data_inicio=this.stringToDate(this.sessao.data_inicio,"yyyy-mm-dd","-"),this.metadata.sessao_legislativa.id=this.sessao.sessao_legislativa,this.metadata.tipo.id=this.sessao.tipo,this.metadata.legislatura.id=this.sessao.legislatura}},mounted:function(){this.updateSessao(),this.fetch()}}}).call(this,a("2ef0"))},4358:function(t,s,a){"use strict";var e=a("3713").a,i=(a("e94f"),a("0c7c")),n=Object(i.a)(e,function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("router-link",{class:"sessao-plenaria-item-list",attrs:{to:{name:"sessao_plenaria_online_link",params:{id:t.sessao.id}}},nativeOn:{click:function(s){return t.sendStore(s)}}},[a("h5",{staticClass:"tit"},[t._v("\n "+t._s(t.titulo)+"\n ")]),a("div",{staticClass:"subtitulo"},[a("span",[t._v(t._s(t.subtitulo))]),a("span",{staticClass:"separator"},[t._v(" – ")]),a("span",[t._v(t._s(t.date_text))])])])},[],!1,null,null,null);s.a=n.exports},"4a7e":function(t,s,a){"use strict";a.r(s);var e=a("4358"),i=a("975e"),n={name:"sessao-plenaria-online",components:{SessaoPlenariaItemList:e.a},data:function(){return{utils:i.a.Utils,sessao:null,app:["sessao"],model:["sessaoplenaria"]}},mounted:function(){this.fetchSessao()},methods:{fetchSessao:function(){var t=this,s=t.$route.params.id,a={app:t.app[0],model:t.model[0],id:s},e=t.getModel(a);null!==e&&e.hasOwnProperty(s)?t.sessao=e[s]:t.$nextTick().then(function(){t.insertInState(a).then(function(){e=t.getModel(a),t.sessao=e[s]})})},fetch:function(){this.fetchSessao()}}},o=(a("8e03"),a("0c7c")),l=Object(o.a)(n,function(){var t=this.$createElement,s=this._self._c||t;return s("div",{staticClass:"sessao-plenaria-online"},[this.sessao?s("div",[s("sessao-plenaria-item-list",{attrs:{sessao:this.sessao}}),this._v("\nteste\n ")],1):this._e()])},[],!1,null,null,null);s.default=l.exports},"8e03":function(t,s,a){"use strict";var e=a("e8c9");a.n(e).a},e8c9:function(t,s,a){},e94f:function(t,s,a){"use strict";var e=a("f16d");a.n(e).a},f16d:function(t,s,a){}}]); |
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -0,0 +1,27 @@ |
|||
<!-- chat/templates/chat/index.html --> |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"/> |
|||
<title>Chat Rooms</title> |
|||
</head> |
|||
<body> |
|||
What chat room would you like to enter?<br/> |
|||
<input id="room-name-input" type="text" size="100"/><br/> |
|||
<input id="room-name-submit" type="button" value="Enter"/> |
|||
|
|||
<script> |
|||
document.querySelector('#room-name-input').focus(); |
|||
document.querySelector('#room-name-input').onkeyup = function(e) { |
|||
if (e.keyCode === 13) { // enter, return |
|||
document.querySelector('#room-name-submit').click(); |
|||
} |
|||
}; |
|||
|
|||
document.querySelector('#room-name-submit').onclick = function(e) { |
|||
var roomName = document.querySelector('#room-name-input').value; |
|||
window.location.pathname = '/channel/' + roomName + '/'; |
|||
}; |
|||
</script> |
|||
</body> |
|||
</html> |
@ -0,0 +1,47 @@ |
|||
<!-- chat/templates/chat/room.html --> |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"/> |
|||
<title>Chat Room</title> |
|||
</head> |
|||
<body> |
|||
<textarea id="chat-log" cols="100" rows="20"></textarea><br/> |
|||
<input id="chat-message-input" type="text" size="100"/><br/> |
|||
<input id="chat-message-submit" type="button" value="Send"/> |
|||
</body> |
|||
<script> |
|||
var roomName = {{ room_name_json }}; |
|||
|
|||
var chatSocket = new WebSocket( |
|||
'ws://' + window.location.host + |
|||
'/ws/chat/' + roomName + '/'); |
|||
|
|||
chatSocket.onmessage = function(e) { |
|||
var data = JSON.parse(e.data); |
|||
var message = data['message']; |
|||
document.querySelector('#chat-log').value += (message + '\n'); |
|||
}; |
|||
|
|||
chatSocket.onclose = function(e) { |
|||
console.error('Chat socket closed unexpectedly'); |
|||
}; |
|||
|
|||
document.querySelector('#chat-message-input').focus(); |
|||
document.querySelector('#chat-message-input').onkeyup = function(e) { |
|||
if (e.keyCode === 13) { // enter, return |
|||
document.querySelector('#chat-message-submit').click(); |
|||
} |
|||
}; |
|||
|
|||
document.querySelector('#chat-message-submit').onclick = function(e) { |
|||
var messageInputDom = document.querySelector('#chat-message-input'); |
|||
var message = messageInputDom.value; |
|||
chatSocket.send(JSON.stringify({ |
|||
'message': message |
|||
})); |
|||
|
|||
messageInputDom.value = ''; |
|||
}; |
|||
</script> |
|||
</html> |
@ -0,0 +1,34 @@ |
|||
<!-- chat/templates/chat/room.html --> |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"/> |
|||
<title>Chat Room</title> |
|||
</head> |
|||
<body> |
|||
<textarea id="chat-log" cols="100" rows="20"></textarea><br/> |
|||
<input id="chat-message-submit" type="button" value="Pull"/> |
|||
</body> |
|||
<script> |
|||
|
|||
var chatSocket = new WebSocket( |
|||
(window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host + |
|||
'/ws/time-refresh/'); |
|||
|
|||
chatSocket.onmessage = function(e) { |
|||
var data = JSON.parse(e.data); |
|||
var message = data['message']; |
|||
document.querySelector('#chat-log').value += (e.data + '\n'); |
|||
}; |
|||
|
|||
chatSocket.onclose = function(e) { |
|||
console.error('Chat socket closed unexpectedly'); |
|||
}; |
|||
|
|||
document.querySelector('#chat-message-submit').onclick = function(e) { |
|||
chatSocket.send(JSON.stringify({ |
|||
'message': 'OK' |
|||
})); |
|||
}; |
|||
</script> |
|||
</html> |
@ -1 +1 @@ |
|||
{"status":"done","publicPath":"/static/sapl/","chunks":{"chunk-vendors":[{"name":"css/chunk-vendors.3c9fe6b4.css","publicPath":"/static/sapl/css/chunk-vendors.3c9fe6b4.css","path":"../sapl/sapl/static/sapl/css/chunk-vendors.3c9fe6b4.css"},{"name":"js/chunk-vendors.0003dc37.js","publicPath":"/static/sapl/js/chunk-vendors.0003dc37.js","path":"../sapl/sapl/static/sapl/js/chunk-vendors.0003dc37.js"},{"name":"css/chunk-vendors.3c9fe6b4.css.map","publicPath":"/static/sapl/css/chunk-vendors.3c9fe6b4.css.map","path":"../sapl/sapl/static/sapl/css/chunk-vendors.3c9fe6b4.css.map"}],"compilacao":[{"name":"css/compilacao.3372b760.css","publicPath":"/static/sapl/css/compilacao.3372b760.css","path":"../sapl/sapl/static/sapl/css/compilacao.3372b760.css"},{"name":"js/compilacao.9853b958.js","publicPath":"/static/sapl/js/compilacao.9853b958.js","path":"../sapl/sapl/static/sapl/js/compilacao.9853b958.js"},{"name":"css/compilacao.3372b760.css.map","publicPath":"/static/sapl/css/compilacao.3372b760.css.map","path":"../sapl/sapl/static/sapl/css/compilacao.3372b760.css.map"}],"global":[{"name":"css/global.f7113e2c.css","publicPath":"/static/sapl/css/global.f7113e2c.css","path":"../sapl/sapl/static/sapl/css/global.f7113e2c.css"},{"name":"js/global.081db1b5.js","publicPath":"/static/sapl/js/global.081db1b5.js","path":"../sapl/sapl/static/sapl/js/global.081db1b5.js"},{"name":"css/global.f7113e2c.css.map","publicPath":"/static/sapl/css/global.f7113e2c.css.map","path":"../sapl/sapl/static/sapl/css/global.f7113e2c.css.map"}],"painel":[{"name":"css/painel.baa845ab.css","publicPath":"/static/sapl/css/painel.baa845ab.css","path":"../sapl/sapl/static/sapl/css/painel.baa845ab.css"},{"name":"js/painel.f4adb91b.js","publicPath":"/static/sapl/js/painel.f4adb91b.js","path":"../sapl/sapl/static/sapl/js/painel.f4adb91b.js"},{"name":"css/painel.baa845ab.css.map","publicPath":"/static/sapl/css/painel.baa845ab.css.map","path":"../sapl/sapl/static/sapl/css/painel.baa845ab.css.map"}]}} |
|||
{"status":"done","publicPath":"/static/sapl/","chunks":{"null":[{"name":"css/chunk-4cf2dae1.c632bec6.css","publicPath":"/static/sapl/css/chunk-4cf2dae1.c632bec6.css","path":"../sapl/sapl/static/sapl/css/chunk-4cf2dae1.c632bec6.css"},{"name":"js/chunk-4cf2dae1.89120e74.js","publicPath":"/static/sapl/js/chunk-4cf2dae1.89120e74.js","path":"../sapl/sapl/static/sapl/js/chunk-4cf2dae1.89120e74.js"},{"name":"css/chunk-4cf2dae1.c632bec6.css.map","publicPath":"/static/sapl/css/chunk-4cf2dae1.c632bec6.css.map","path":"../sapl/sapl/static/sapl/css/chunk-4cf2dae1.c632bec6.css.map"}],"chunk-vendors":[{"name":"css/chunk-vendors.2ce8185b.css","publicPath":"/static/sapl/css/chunk-vendors.2ce8185b.css","path":"../sapl/sapl/static/sapl/css/chunk-vendors.2ce8185b.css"},{"name":"js/chunk-vendors.0b0a5dbb.js","publicPath":"/static/sapl/js/chunk-vendors.0b0a5dbb.js","path":"../sapl/sapl/static/sapl/js/chunk-vendors.0b0a5dbb.js"},{"name":"css/chunk-vendors.2ce8185b.css.map","publicPath":"/static/sapl/css/chunk-vendors.2ce8185b.css.map","path":"../sapl/sapl/static/sapl/css/chunk-vendors.2ce8185b.css.map"}],"compilacao":[{"name":"css/compilacao.3372b760.css","publicPath":"/static/sapl/css/compilacao.3372b760.css","path":"../sapl/sapl/static/sapl/css/compilacao.3372b760.css"},{"name":"js/compilacao.7b04bca9.js","publicPath":"/static/sapl/js/compilacao.7b04bca9.js","path":"../sapl/sapl/static/sapl/js/compilacao.7b04bca9.js"},{"name":"css/compilacao.3372b760.css.map","publicPath":"/static/sapl/css/compilacao.3372b760.css.map","path":"../sapl/sapl/static/sapl/css/compilacao.3372b760.css.map"}],"global":[{"name":"css/global.e4ae5421.css","publicPath":"/static/sapl/css/global.e4ae5421.css","path":"../sapl/sapl/static/sapl/css/global.e4ae5421.css"},{"name":"js/global.742e068f.js","publicPath":"/static/sapl/js/global.742e068f.js","path":"../sapl/sapl/static/sapl/js/global.742e068f.js"},{"name":"css/global.e4ae5421.css.map","publicPath":"/static/sapl/css/global.e4ae5421.css.map","path":"../sapl/sapl/static/sapl/css/global.e4ae5421.css.map"}],"online":[{"name":"css/online.3d6220ca.css","publicPath":"/static/sapl/css/online.3d6220ca.css","path":"../sapl/sapl/static/sapl/css/online.3d6220ca.css"},{"name":"js/online.50eb7f8e.js","publicPath":"/static/sapl/js/online.50eb7f8e.js","path":"../sapl/sapl/static/sapl/js/online.50eb7f8e.js"},{"name":"css/online.3d6220ca.css.map","publicPath":"/static/sapl/css/online.3d6220ca.css.map","path":"../sapl/sapl/static/sapl/css/online.3d6220ca.css.map"}],"painel":[{"name":"css/painel.baa845ab.css","publicPath":"/static/sapl/css/painel.baa845ab.css","path":"../sapl/sapl/static/sapl/css/painel.baa845ab.css"},{"name":"js/painel.f4adb91b.js","publicPath":"/static/sapl/js/painel.f4adb91b.js","path":"../sapl/sapl/static/sapl/js/painel.f4adb91b.js"},{"name":"css/painel.baa845ab.css.map","publicPath":"/static/sapl/css/painel.baa845ab.css.map","path":"../sapl/sapl/static/sapl/css/painel.baa845ab.css.map"}]}} |
|||
|
Loading…
Reference in new issue