-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Melhoria da Usabilidade na Seleção de Grupos: Atualização da Interface para Seleção Intuitiva e Eficiente #5
base: main
Are you sure you want to change the base?
Changes from all commits
19419d3
903b4ac
4e8248d
9cdb02d
ba33382
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
.related-widget-wrapper { | ||
display: flex; | ||
flex-direction: column; | ||
width: 100%; | ||
height: auto; | ||
} | ||
|
||
|
||
.duallistbox { | ||
width: 100%; | ||
height: 100px; | ||
} | ||
|
||
.duallistbox option { | ||
border: 1px solid #ccc; | ||
padding: 5px; | ||
border-radius: 4px; | ||
margin: 2px 0; | ||
} | ||
|
||
.duallistbox option.selected { | ||
border-color: #007bff; | ||
background-color: #e7f0ff; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{% extends "admin/base_site.html" %} | ||
{% load i18n %} | ||
|
||
{% block title %}{% translate 'Page not found' %}{% endblock %} | ||
|
||
{% block content %} | ||
|
||
<h2>{% translate 'Page not found' %}</h2> | ||
|
||
<p>{% translate 'We’re sorry, but the requested page could not be found.' %}</p> | ||
|
||
{% endblock %} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. O que esse template tem a ver com o DualListBox???? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ele é um dos templates utilizados pelo próprio admin então achei interessante ter o .html deles ali. Ele não tem nada haver com o DualListBox. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{% extends "admin/base_site.html" %} | ||
{% load i18n %} | ||
|
||
{% block breadcrumbs %} | ||
<div class="breadcrumbs"> | ||
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a> | ||
› {% translate 'Server error' %} | ||
</div> | ||
{% endblock %} | ||
|
||
{% block title %}{% translate 'Server error (500)' %}{% endblock %} | ||
|
||
{% block content %} | ||
<h1>{% translate 'Server Error <em>(500)</em>' %}</h1> | ||
<p>{% translate 'There’s been an error. It’s been reported to the site administrators via email and should be fixed shortly. Thanks for your patience.' %}</p> | ||
|
||
{% endblock %} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. O que esse template tem a ver com o DualListBox???? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{% load i18n %} | ||
<button class="theme-toggle"> | ||
<span class="visually-hidden theme-label-when-auto">{% translate 'Toggle theme (current theme: auto)' %}</span> | ||
<span class="visually-hidden theme-label-when-light">{% translate 'Toggle theme (current theme: light)' %}</span> | ||
<span class="visually-hidden theme-label-when-dark">{% translate 'Toggle theme (current theme: dark)' %}</span> | ||
<svg aria-hidden="true" class="theme-icon-when-auto"> | ||
<use xlink:href="#icon-auto" /> | ||
</svg> | ||
<svg aria-hidden="true" class="theme-icon-when-dark"> | ||
<use xlink:href="#icon-moon" /> | ||
</svg> | ||
<svg aria-hidden="true" class="theme-icon-when-light"> | ||
<use xlink:href="#icon-sun" /> | ||
</svg> | ||
</button> |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. O que esse template tem a ver com o DualListBox???? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{% load i18n %} | ||
<button class="sticky toggle-nav-sidebar" id="toggle-nav-sidebar" aria-label="{% translate 'Toggle navigation' %}"></button> | ||
<nav class="sticky" id="nav-sidebar" aria-label="{% translate 'Sidebar' %}"> | ||
<input type="search" id="nav-filter" | ||
placeholder="{% translate 'Start typing to filter…' %}" | ||
aria-label="{% translate 'Filter navigation items' %}"> | ||
{% include 'admin/app_list.html' with app_list=available_apps show_changelinks=False %} | ||
</nav> |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. O que esse template tem a ver com o DualListBox???? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{% load i18n static %}<!DOCTYPE html> | ||
<html> | ||
<head><title>{% translate 'Popup closing…' %}</title></head> | ||
<body> | ||
<script id="django-admin-popup-response-constants" | ||
src="{% static "admin/js/popup_response.js" %}" | ||
data-popup-response="{{ popup_response_data }}"> | ||
</script> | ||
</body> | ||
</html> |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Onde isso é usado? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{% load static %} | ||
<script id="django-admin-prepopulated-fields-constants" | ||
src="{% static "admin/js/prepopulate_init.js" %}" | ||
data-prepopulated-fields="{{ prepopulated_fields_json }}"> | ||
</script> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,16 @@ | ||
{% load i18n static %} | ||
<div class="related-widget-wrapper" {% if not model_has_limit_choices_to %}data-model-ref="{{ model_name }}"{% endif %}> | ||
{{ rendered_widget }} | ||
<link rel="stylesheet" href="{% static 'css/related_widget_wrapper.css' %}"> | ||
<div class="related-widget-wrapper" style="height: 100%;" {% if not model_has_limit_choices_to %}data-model-ref="{{ model_name }}"{% endif %}> | ||
<!-- Renderiza o widget original, mas oculto --> | ||
<div id="original-widget" style="display: none;"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. id hardcoded é errado. Cada elemento no HTML final tem que ter um id único |
||
{{ rendered_widget }} | ||
</div> | ||
|
||
<!-- Duallistbox Visível --> | ||
<select multiple="multiple" name="duallistbox_demo1[]" id="duallistbox_demo1" class="duallistbox"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tá certo isso? O name e id do select estão hardcoded. Se num form tiver dois ou mais campos com esse widget, todos terão o mesmo id/nome, que certamente trará problemas. |
||
<!-- As opções serão preenchidas aqui via JavaScript --> | ||
</select> | ||
|
||
{% block links %} | ||
{% spaceless %} | ||
{% if not is_hidden %} | ||
|
@@ -39,3 +49,72 @@ | |
{% endspaceless %} | ||
{% endblock %} | ||
</div> | ||
|
||
<script> | ||
$(document).ready(function() { | ||
// Função para sincronizar o DualListBox com o rendered_widget | ||
function updateDualListbox() { | ||
// Extrair as opções do select oculto do rendered_widget | ||
const renderedOptions = $('#original-widget select[name="{{ name }}"] option'); | ||
|
||
// Limpar o DualListBox | ||
$('#duallistbox_demo1').empty(); | ||
|
||
// Adicionar as novas opções ao DualListBox | ||
renderedOptions.each(function() { | ||
$('#duallistbox_demo1').append($(this).clone()); | ||
}); | ||
|
||
// Atualizar visualmente o DualListBox sem reinicializar | ||
$('#duallistbox_demo1').bootstrapDualListbox('refresh'); | ||
} | ||
|
||
// Sincronizar as seleções do DualListBox com o select oculto | ||
function syncDualListboxToRenderedWidget() { | ||
const selectedValues = $('#duallistbox_demo1').val() || []; | ||
|
||
// Limpar o select original oculto | ||
$('#original-widget select[name="{{ name }}"]').empty(); | ||
|
||
// Adicionar as opções selecionadas no DualListBox ao rendered_widget | ||
selectedValues.forEach(function(value) { | ||
const optionText = $('#duallistbox_demo1 option[value="' + value + '"]').text(); | ||
$('#original-widget select[name="{{ name }}"]').append(new Option(optionText, value, true, true)); | ||
}); | ||
} | ||
|
||
// Inicializa o DualListBox | ||
$('#duallistbox_demo1').bootstrapDualListbox({ | ||
nonSelectedListLabel: '', | ||
selectedListLabel: '', | ||
moveOnSelect: false, | ||
infoText: false, | ||
filterPlaceHolder: 'Pesquisar', | ||
selectorMinimalHeight: 400, // Ajuste conforme necessário | ||
}); | ||
|
||
// Adicionar ícones manuais para o Bootstrap 5 | ||
$('.moveall').html('<i class="bi bi-chevron-double-right"></i>'); | ||
$('.removeall').html('<i class="bi bi-chevron-double-left"></i>'); | ||
$('.move').html('<i class="bi bi-chevron-right"></i>'); | ||
$('.remove').html('<i class="bi bi-chevron-left"></i>'); | ||
|
||
// Monitorar mudanças no select do rendered_widget e atualizar o DualListBox | ||
$('#original-widget select[name="{{ name }}"]').on('DOMSubtreeModified', function() { | ||
updateDualListbox(); | ||
}); | ||
|
||
// Atualizar o select oculto antes de salvar o formulário | ||
$('form').on('submit', function() { | ||
syncDualListboxToRenderedWidget(); // Sincroniza os valores antes do envio | ||
}); | ||
|
||
// Trigger para sincronizar as seleções iniciais | ||
updateDualListbox(); | ||
}); | ||
</script> | ||
|
||
|
||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,8 @@ | |
<title>{% block title %}{% endblock %}</title> | ||
<meta charset="utf-8"> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> | ||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-duallistbox/dist/bootstrap-duallistbox.min.css" rel="stylesheet"> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css"> | ||
<link rel="stylesheet" href="{{ djbs.ICON_SOURCE|safe }}"> | ||
<link rel="stylesheet" href="{% block stylesheet %}{% static 'css/base.css' %}{% endblock %}"> | ||
<script src="{% static 'js/sidenav_menu.js' %}"></script> | ||
|
@@ -13,6 +15,7 @@ | |
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-duallistbox/dist/jquery.bootstrap-duallistbox.min.js"></script> | ||
{% block dark-mode-vars %}{% endblock %} | ||
{% block extrastyle %}{% endblock %} | ||
{% if LANGUAGE_BIDI %} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,5 @@ | ||
{% with id=widget.attrs.id %} | ||
<div {% if id %} id="{{ id }}"{% endif %} | ||
{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% else %} class="form-control"{% endif %}> | ||
|
||
{% for group, options, index in widget.optgroups %} | ||
{% if group %} | ||
<div><label>{{ group }}</label></div> | ||
{% endif %} | ||
|
||
{% for option in options %} | ||
<div> | ||
{% include option.template_name with widget=option %} | ||
</div> | ||
{% endfor %} | ||
{% endfor %} | ||
|
||
</div> | ||
{% endwith %} | ||
{% with id=widget.attrs.id %}<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %} | ||
<div><label>{{ group }}</label>{% endif %}{% for option in options %}<div> | ||
{% include option.template_name with widget=option %}</div>{% endfor %}{% if group %} | ||
</div>{% endif %}{% endfor %} | ||
</div>{% endwith %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
O que esse template tem a ver com o DualListBox????