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.
 
 
 
 
 

490 lines
15 KiB

{% extends "crud/form.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block extra_css %}
<style>
/* =====================================================
Componente de co-autores com busca + checkboxes
===================================================== */
#coautores-search-box {
width: 100%;
padding: 8px 12px;
border: 1px solid #ced4da;
border-radius: 6px;
font-size: 0.95em;
margin-bottom: 8px;
box-sizing: border-box;
}
#coautores-search-box:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 2px rgba(0,123,255,0.2);
}
#coautores-list-container {
max-height: 220px;
overflow-y: auto;
border: 1px solid #ced4da;
border-radius: 6px;
background: #fff;
padding: 6px 0;
}
#coautores-list-container .coautores-item {
display: flex;
align-items: center;
padding: 6px 12px;
cursor: pointer;
transition: background 0.15s;
}
#coautores-list-container .coautores-item:hover {
background: #f0f7ff;
}
#coautores-list-container .coautores-item input[type="checkbox"] {
margin-right: 10px;
width: 16px;
height: 16px;
accent-color: #007bff;
cursor: pointer;
flex-shrink: 0;
}
#coautores-list-container .coautores-item label {
margin: 0;
cursor: pointer;
font-weight: normal;
color: #343a40;
font-size: 0.95em;
}
#coautores-no-results {
padding: 10px 12px;
color: #6c757d;
font-style: italic;
font-size: 0.9em;
display: none;
}
#coautores-counter {
font-size: 0.85em;
color: #6c757d;
margin-top: 5px;
}
#div_id_coautores {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #e9ecef;
margin-bottom: 15px;
}
#div_id_coautores > label {
font-weight: 600;
color: #495057;
margin-bottom: 8px;
display: block;
}
#div_id_coautores .form-text {
color: #6c757d;
font-size: 0.875em;
margin-top: 5px;
}
/* =====================================================
Estilo para o container do tipo de proposição
===================================================== */
#div_id_tipo {
position: relative;
}
#div_id_tipo .tipo-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
#div_id_tipo .btn-novo-tipo {
white-space: nowrap;
padding: 6px 12px;
font-size: 13px;
}
/* =====================================================
Estilo para os radio buttons de tipo de texto
===================================================== */
#div_id_tipo_texto {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
border: 1px solid #e9ecef;
margin-bottom: 15px;
}
#div_id_tipo_texto > label.col-form-label,
#div_id_tipo_texto > label:first-child {
font-weight: 600;
color: #495057;
margin-bottom: 15px;
display: block;
font-size: 1em;
}
#div_id_tipo_texto .form-check {
display: flex;
gap: 15px;
flex-wrap: wrap;
padding: 0;
}
#div_id_tipo_texto .form-check label,
#div_id_tipo_texto .form-check-inline {
display: flex;
align-items: center;
padding: 14px 20px;
background: white;
border: 2px solid #dee2e6;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
margin: 0 !important;
font-weight: 500;
color: #495057;
}
#div_id_tipo_texto .form-check label:hover,
#div_id_tipo_texto .form-check-inline:hover {
border-color: #007bff;
background: #f0f7ff;
}
#div_id_tipo_texto .form-check label.checked,
#div_id_tipo_texto .form-check-inline.checked {
border-color: #007bff;
background: #e7f1ff;
box-shadow: 0 0 0 1px #007bff;
color: #0056b3;
}
#div_id_tipo_texto input[type="radio"] {
margin-right: 10px;
width: 18px;
height: 18px;
accent-color: #007bff;
}
/* =====================================================
Estilo para o alerta do OnlyOffice
===================================================== */
#onlyoffice-info {
border-left: 4px solid #17a2b8;
background: linear-gradient(135deg, #e8f4f8 0%, #f8f9fa 100%);
border-radius: 8px;
padding: 20px;
margin-top: 15px;
}
#onlyoffice-info h5 {
color: #0c5460;
margin-bottom: 12px;
font-size: 1.1em;
}
#onlyoffice-info .fa-file-word-o {
margin-right: 8px;
color: #2b579a;
}
#onlyoffice-info p {
color: #495057;
margin-bottom: 8px;
}
/* =====================================================
Estilo para o campo de upload
===================================================== */
#div_id_texto_original {
background: #fff;
padding: 20px;
border-radius: 8px;
border: 2px dashed #dee2e6;
transition: all 0.2s ease;
}
#div_id_texto_original:hover {
border-color: #007bff;
background: #f8f9ff;
}
#div_id_texto_original label {
font-weight: 600;
color: #495057;
}
/* =====================================================
Fieldset de vinculação
===================================================== */
fieldset.card {
margin-top: 25px;
border: 1px solid #e9ecef;
border-radius: 8px;
}
fieldset.card legend {
padding: 0 10px;
font-size: 1em;
}
/* =====================================================
Alerta de ementa da matéria
===================================================== */
.ementa_materia {
margin-top: 15px;
font-size: 0.95em;
border-radius: 6px;
}
/* =====================================================
Botões do formulário (Cancelar / Salvar)
===================================================== */
.form-group.row.justify-content-between {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 0;
margin-top: 20px;
border-top: 1px solid #e9ecef;
}
.form-group.row.justify-content-between .btn {
min-width: 120px;
}
.form-group.row.justify-content-between .btn-dark {
background-color: #6c757d;
border-color: #6c757d;
}
.form-group.row.justify-content-between .btn-dark:hover {
background-color: #5a6268;
border-color: #545b62;
}
.form-group.row.justify-content-between .btn-primary {
padding: 8px 25px;
}
</style>
{% endblock %}
{% block extra_js %}
<script type="text/javascript">
$(document).ready(function(){
// =====================================================
// Componente checkbox + busca para co-autores
// =====================================================
(function() {
var $fieldDiv = $('#div_id_coautores');
// O Django renderiza os checkboxes nativos dentro de um <ul> — vamos substituí-los
var $originalWidget = $fieldDiv.find('ul, .checkbox-select, select');
// Coletar todos os checkboxes originais gerados pelo CheckboxSelectMultiple
var checkboxes = [];
$fieldDiv.find('input[type="checkbox"]').each(function() {
checkboxes.push({
value: $(this).val(),
label: $(this).closest('label').text().trim() ||
$fieldDiv.find('label[for="' + $(this).attr('id') + '"]').text().trim(),
checked: $(this).prop('checked'),
id: $(this).attr('id'),
name: $(this).attr('name')
});
});
if (checkboxes.length === 0) return; // Sem autores cadastrados, não renderizar
// Esconder widget original (manter checkboxes no DOM para submit)
$fieldDiv.find('ul').css('display', 'none');
// Inserir campo de busca e container customizado após a label
var $label = $fieldDiv.find('label').first();
var $helpText = $fieldDiv.find('.form-text, small.text-muted');
var $searchInput = $('<input>', {
type: 'text',
id: 'coautores-search-box',
placeholder: '{% trans "Buscar co-autor por nome..." %}',
autocomplete: 'off'
});
var $listContainer = $('<div>', { id: 'coautores-list-container' });
var $noResults = $('<div>', { id: 'coautores-no-results', text: '{% trans "Nenhum autor encontrado." %}' });
var $counter = $('<div>', { id: 'coautores-counter' });
$listContainer.append($noResults);
// Renderizar itens
function renderItem(cb) {
var $item = $('<div>', { 'class': 'coautores-item' });
var $chk = $('<input>', {
type: 'checkbox',
id: cb.id + '_custom',
value: cb.value,
checked: cb.checked
});
var $lbl = $('<label>', {
'for': cb.id + '_custom',
text: cb.label
});
$item.append($chk).append($lbl);
// Sincronizar com checkbox original (para submit)
$chk.on('change', function() {
$('#' + cb.id).prop('checked', $(this).prop('checked'));
updateCounter();
});
return $item;
}
checkboxes.forEach(function(cb) {
$listContainer.append(renderItem(cb));
});
function updateCounter() {
var total = $listContainer.find('input[type="checkbox"]:checked').length;
if (total === 0) {
$counter.text('');
} else if (total === 1) {
$counter.text('1 {% trans "co-autor selecionado" %}');
} else {
$counter.text(total + ' {% trans "co-autores selecionados" %}');
}
}
// Busca em tempo real
$searchInput.on('input', function() {
var term = $(this).val().toLowerCase().trim();
var visible = 0;
$listContainer.find('.coautores-item').each(function() {
var name = $(this).find('label').text().toLowerCase();
if (!term || name.indexOf(term) !== -1) {
$(this).show();
visible++;
} else {
$(this).hide();
}
});
$noResults.toggle(visible === 0);
});
// Inserir no DOM
$label.after($searchInput, $listContainer, $counter);
if ($helpText.length) {
$counter.after($helpText.detach());
}
updateCounter();
})();
// =====================================================
// Configuração do botão "Novo Tipo"
// =====================================================
var $tipoDiv = $('#div_id_tipo');
var $tipoLabel = $tipoDiv.find('label').first();
var $tipoSelect = $("select[name=tipo]");
if ($tipoLabel.length > 0 && $tipoSelect.length > 0) {
var $header = $('<div class="tipo-header"></div>');
var $btnNovoTipo = $(`
<a href="/sistema/proposicao/tipo/create"
class="btn btn-success btn-sm btn-novo-tipo"
title="Cadastrar novo tipo de proposição"
target="_blank">
<i class="fa fa-plus"></i> Novo Tipo
</a>
`);
$tipoLabel.wrap($header);
$tipoLabel.after($btnNovoTipo);
}
// =====================================================
// Gerenciamento do tipo de texto
// =====================================================
function updateTipoTextoDisplay() {
var tipoTextoValue = $("input[name=tipo_texto]:checked").val();
if (tipoTextoValue === 'D') {
$("#div_id_texto_original").slideDown(200);
$("#onlyoffice-info").slideUp(200);
} else if (tipoTextoValue === 'T') {
$("#div_id_texto_original").slideUp(200);
$("#onlyoffice-info").slideUp(200);
} else if (tipoTextoValue === 'O') {
$("#div_id_texto_original").slideUp(200);
$("#onlyoffice-info").slideDown(200);
}
$("#div_id_tipo_texto .form-check label, #div_id_tipo_texto .form-check-inline").removeClass('checked');
$("input[name=tipo_texto]:checked").closest('label').addClass('checked');
}
$("input[name=tipo_texto]").change(function() {
updateTipoTextoDisplay();
});
function showTipoTextoOptions() {
var $tipoTextoContainer = $("input[name=tipo_texto]").closest('.form-group').parent();
$tipoTextoContainer.removeClass('hidden');
$("input[name=tipo_texto]").prop('disabled', false);
$("input[name=tipo_texto]").closest('label').removeClass('disabled');
if ($("input[name=tipo_texto]:checked").length === 0) {
$("input[name=tipo_texto]").first().prop('checked', true);
}
updateTipoTextoDisplay();
}
showTipoTextoOptions();
$("select[name=tipo]").change(function() { showTipoTextoOptions(); });
// =====================================================
// Busca de matéria legislativa para vinculação
// =====================================================
function buscarMateria() {
var formData = {
'tipo': $("select[name=tipo_materia]").val(),
'ano': $("input[name=ano_materia]").val(),
'numero': $("input[name=numero_materia]").val(),
};
if (!formData.tipo || !formData.ano || !formData.numero) {
$(".ementa_materia").html('').addClass('hidden');
return;
}
var url = '{% url "sapl.api:materialegislativa-list" %}';
$.get(url, formData).done(function(data) {
if (data.pagination.total_entries === 1) {
$(".ementa_materia")
.html('<strong><i class="fa fa-check-circle text-success"></i> Matéria encontrada:</strong> ' + data.results[0].ementa)
.removeClass('hidden alert-warning')
.addClass('alert-info');
} else if (data.pagination.total_entries === 0) {
$(".ementa_materia")
.html('<i class="fa fa-exclamation-triangle"></i> <em>Matéria não encontrada</em>')
.removeClass('hidden alert-info')
.addClass('alert-warning');
} else {
$(".ementa_materia").html('').addClass('hidden');
}
}).fail(function() {
$(".ementa_materia").html('').addClass('hidden');
});
}
$("select[name=tipo_materia], input[name=numero_materia], input[name=ano_materia]")
.on('change keyup', function() { buscarMateria(); });
// =====================================================
// Inicialização
// =====================================================
$("select[name=tipo]").trigger('change');
buscarMateria();
$("#onlyoffice-info").hide();
setTimeout(updateTipoTextoDisplay, 100);
});
</script>
{% endblock %}