use Django's Admin FilteredSelectMultiple for Group Membership
This commit is contained in:
parent
5f861189e4
commit
2b8c2b2346
|
@ -2,10 +2,20 @@
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load utils %}
|
{% load utils %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
{% block head %}
|
{% block head %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
{{ form.media.css }}
|
{{ form.media.css }}
|
||||||
|
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/core.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/actions.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/urlify.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/prepopulate.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/SelectBox.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'admin/js/SelectFilter2.js' %}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from passbook.core.models import Group, User
|
from passbook.core.models import Group, User
|
||||||
|
from django.contrib.admin.widgets import FilteredSelectMultiple
|
||||||
|
|
||||||
|
|
||||||
class GroupForm(forms.ModelForm):
|
class GroupForm(forms.ModelForm):
|
||||||
"""Group Form"""
|
"""Group Form"""
|
||||||
|
|
||||||
members = forms.ModelMultipleChoiceField(User.objects.all(), required=False)
|
members = forms.ModelMultipleChoiceField(
|
||||||
|
User.objects.all(), required=False, widget=FilteredSelectMultiple('users', False))
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
@ -18,7 +20,7 @@ class GroupForm(forms.ModelForm):
|
||||||
instance = super().save(*args, **kwargs)
|
instance = super().save(*args, **kwargs)
|
||||||
if instance.pk:
|
if instance.pk:
|
||||||
instance.user_set.clear()
|
instance.user_set.clear()
|
||||||
instance.user_set.add(*self.cleaned_data['users'])
|
instance.user_set.add(*self.cleaned_data['members'])
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 2.1.7 on 2019-03-08 14:17
|
# Generated by Django 2.1.7 on 2019-03-10 16:15
|
||||||
|
|
||||||
import django.contrib.postgres.fields.hstore
|
import django.contrib.postgres.fields.hstore
|
||||||
from django.contrib.postgres.operations import HStoreExtension
|
from django.contrib.postgres.operations import HStoreExtension
|
||||||
|
@ -8,7 +8,7 @@ from django.db import migrations
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('passbook_core', '0016_auto_20190227_1355'),
|
('passbook_core', '0018_provider_property_mappings'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
|
@ -21,3 +21,177 @@
|
||||||
.dynamic-array-widget .remove:hover {
|
.dynamic-array-widget .remove:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Selector */
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 45vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-filter {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-filter label {
|
||||||
|
margin: 0 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector .selector-filter input {
|
||||||
|
width: auto;
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-available, .selector-chosen {
|
||||||
|
width: auto;
|
||||||
|
flex: 1 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector select {
|
||||||
|
width: 100%;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector ul.selector-chooser {
|
||||||
|
width: 26px;
|
||||||
|
height: 52px;
|
||||||
|
padding: 2px 0;
|
||||||
|
margin: auto 15px;
|
||||||
|
border-radius: 20px;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-add, .selector-remove {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background-size: 20px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-add {
|
||||||
|
background-position: 0 -120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-remove {
|
||||||
|
background-position: 0 -80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.selector-chooseall, a.selector-clearall {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked {
|
||||||
|
flex-direction: column;
|
||||||
|
max-width: 480px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked > * {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked select {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-available, .stacked .selector-chosen {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked ul.selector-chooser {
|
||||||
|
width: 52px;
|
||||||
|
height: 26px;
|
||||||
|
padding: 0 2px;
|
||||||
|
margin: 15px auto;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-chooser li {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-add, .stacked .selector-remove {
|
||||||
|
background-size: 20px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-add {
|
||||||
|
background-position: 0 -40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .active.selector-add {
|
||||||
|
background-position: 0 -60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .selector-remove {
|
||||||
|
background-position: 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stacked .active.selector-remove {
|
||||||
|
background-position: 0 -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-tooltip, .selector .help-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-row p.datetime {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetime input {
|
||||||
|
width: 50%;
|
||||||
|
max-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetime span {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetime .timezonewarning {
|
||||||
|
display: block;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.datetimeshortcuts {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-group {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-add, .selector-remove {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
display: block;
|
||||||
|
text-indent: -3000px;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: default;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active.selector-add, .active.selector-remove {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active.selector-add:hover, .active.selector-remove:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-add {
|
||||||
|
background: url(../admin/img/selector-icons.svg) 0 -96px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active.selector-add:focus, .active.selector-add:hover {
|
||||||
|
background-position: 0 -112px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-remove {
|
||||||
|
background: url(../admin/img/selector-icons.svg) 0 -64px no-repeat;
|
||||||
|
}
|
||||||
|
|
Reference in a new issue