Skip to content
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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions static/css/related_widget_wrapper.css
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;
}
12 changes: 12 additions & 0 deletions templates/admin/404.html
Copy link
Member

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????

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 %}
17 changes: 17 additions & 0 deletions templates/admin/500.html
Copy link
Member

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????

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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>
&rsaquo; {% 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 %}
15 changes: 15 additions & 0 deletions templates/admin/color_theme_toggle.html
Copy link
Member

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????

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>
8 changes: 8 additions & 0 deletions templates/admin/nav_sidebar.html
Copy link
Member

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????

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>
10 changes: 10 additions & 0 deletions templates/admin/popup_response.html
Copy link
Member

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????

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>
5 changes: 5 additions & 0 deletions templates/admin/prepopulated_fields_js.html
Copy link
Member

Choose a reason for hiding this comment

The 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>
83 changes: 81 additions & 2 deletions templates/admin/widgets/related_widget_wrapper.html
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;">
Copy link
Member

Choose a reason for hiding this comment

The 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">
Copy link
Member

Choose a reason for hiding this comment

The 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 %}
Expand Down Expand Up @@ -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>





3 changes: 3 additions & 0 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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 %}
Expand Down
23 changes: 5 additions & 18 deletions templates/django/forms/widgets/multiple_input.html
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 %}