Browse Source

New feauture: User flags. You may mark each user for multiple flags.

devel
bashmak 8 years ago
parent
commit
bb57557997
  1. 11
      abonapp/forms.py
  2. 23
      abonapp/migrations/0006_abon_markers.py
  3. 38
      abonapp/models.py
  4. 17
      abonapp/templates/abonapp/editAbon.html
  5. 2
      abonapp/templates/abonapp/group_list.html
  6. 31
      abonapp/templates/abonapp/modal_user_markers.html
  7. 2
      abonapp/templates/abonapp/peoples.html
  8. 2
      abonapp/urls_abon.py
  9. 30
      abonapp/views.py
  10. 1
      requirements.txt
  11. 19
      static/css/custom.css
  12. BIN
      static/img/user_markers.png

11
abonapp/forms.py

@ -7,6 +7,7 @@ from random import choice
from string import digits, ascii_lowercase from string import digits, ascii_lowercase
from . import models from . import models
from django.conf import settings from django.conf import settings
from bitfield.forms import BitFieldCheckboxSelectMultiple
TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$') TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$')
@ -179,3 +180,13 @@ class ExportUsersForm(forms.Form):
fields = forms.MultipleChoiceField(choices=FIELDS_CHOICES, fields = forms.MultipleChoiceField(choices=FIELDS_CHOICES,
widget=forms.CheckboxSelectMultiple(attrs={"checked": ""}), widget=forms.CheckboxSelectMultiple(attrs={"checked": ""}),
label=_('Fields')) label=_('Fields'))
class MarkersForm(forms.ModelForm):
class Meta:
model = models.Abon
fields = ['markers']
def save(self, commit=True):
instance = super(MarkersForm, self).save(commit=False)
return instance.save(update_fields=['markers'])

23
abonapp/migrations/0006_abon_markers.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-02-13 14:06
from __future__ import unicode_literals
import bitfield.models
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('abonapp', '0005_auto_20180123_1353'),
]
operations = [
migrations.AddField(
model_name='abon',
name='markers',
field=bitfield.models.BitField((('icon_donkey', 'Donkey'), ('icon_fire', 'Fire'), ('icon_ok', 'Ok'),
('icon_king', 'King'), ('icon_tv', 'TV'), ('icon_smile', 'Smile'),
('icon_dollar', 'Dollar'), ('icon_service', 'Service'),
('icon_mrk', 'Marker')), default=None),
),
]

38
abonapp/models.py

@ -1,17 +1,20 @@
from datetime import datetime from datetime import datetime
from django.conf import settings
from django.core import validators
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.db import models, connection, transaction
from django.db.models.signals import post_save, post_delete, pre_delete, post_init from django.db.models.signals import post_save, post_delete, pre_delete, post_init
from django.dispatch import receiver from django.dispatch import receiver
from django.utils import timezone from django.utils import timezone
from django.db import models, connection, transaction
from django.core import validators
from django.utils.translation import ugettext as _
from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult, NasNetworkError
from tariff_app.models import Tariff, PeriodicPay
from django.utils.translation import ugettext_lazy as _
from accounts_app.models import UserProfile, MyUserManager from accounts_app.models import UserProfile, MyUserManager
from agent import Transmitter, AbonStruct, TariffStruct, NasFailedResult, NasNetworkError
from mydefs import MyGenericIPAddressField, ip2int, LogicError, ip_addr_regex from mydefs import MyGenericIPAddressField, ip2int, LogicError, ip_addr_regex
from django.conf import settings
from tariff_app.models import Tariff, PeriodicPay
from bitfield import BitField
TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$') TELEPHONE_REGEXP = getattr(settings, 'TELEPHONE_REGEXP', r'^\+[7,8,9,3]\d{10,11}$')
@ -159,6 +162,29 @@ class Abon(UserProfile):
dev_port = models.ForeignKey('devapp.Port', null=True, blank=True, on_delete=models.SET_NULL) dev_port = models.ForeignKey('devapp.Port', null=True, blank=True, on_delete=models.SET_NULL)
is_dynamic_ip = models.BooleanField(default=False) is_dynamic_ip = models.BooleanField(default=False)
MARKER_FLAGS = (
('icon_donkey', _('Donkey')),
('icon_fire', _('Fire')),
('icon_ok', _('Ok')),
('icon_king', _('King')),
('icon_tv', _('TV')),
('icon_smile', _('Smile')),
('icon_dollar', _('Dollar')),
('icon_service', _('Service')),
('icon_mrk', _('Marker'))
)
markers = BitField(flags=MARKER_FLAGS, default=0)
def get_flag_icons(self):
"""
Return icon list of set flags from self.markers
:return: ['m-icon-donkey', 'm-icon-tv', ...]
"""
return ["m-%s" % name for name, state in self.markers if state]
def is_markers_empty(self):
return int(self.markers) == 0
def active_tariff(self): def active_tariff(self):
return self.current_tariff return self.current_tariff

17
abonapp/templates/abonapp/editAbon.html

@ -216,6 +216,23 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{% trans 'User flags' %}</h3>
</div>
<div class="panel-body">
{% for user_icon in abon.get_flag_icons %}
<span class="m-icon {{ user_icon }}"></span>
{% endfor %}
</div>
<div class="panel-footer">
<div class="btn-group">
<a href="{% url 'abonapp:markers_edit' abon_group.pk abon.pk %}" class="btn btn-default btn-modal">
<span class="glyphicon glyphicon-edit"></span> {% trans 'Edit' %}
</a>
</div>
</div>
</div>
</div> </div>
</div> </div>

2
abonapp/templates/abonapp/group_list.html

@ -83,6 +83,6 @@
</table> </table>
</div> </div>
{% include 'toolbar_page_cbv.html' %}
{% include 'pagination.html' %}
{% endblock %} {% endblock %}

31
abonapp/templates/abonapp/modal_user_markers.html

@ -0,0 +1,31 @@
{% load i18n %}
<form action="{% url 'abonapp:markers_edit' gid uid %}" method="post"> {% csrf_token %}
<div class="modal-header primary">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title"><span class="glyphicon glyphicon-bookmark"></span>{% trans 'Markers' %}</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label class="control-label">{% trans 'Markers' %}</label>
{% for ch in form.markers %}
<div class="checkbox">
<label for="{{ ch.id_for_label }}">
<input type="checkbox" name="{{ ch.data.name }}" value="{{ ch.data.value }}" id="{{ ch.id_for_label }}" {% if ch.selected %}checked {% endif %}/>
<span class="m-icon m-{{ ch.data.value }}"></span>
{{ ch.choice_label }}
</label>
</div>
{% endfor %}
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-ok-circle"></span> {% trans 'Save' %}
</button>
</div>
</form>

2
abonapp/templates/abonapp/peoples.html

@ -167,6 +167,6 @@
</div> </div>
</div> </div>
{% include 'toolbar_page_cbv.html' %}
{% include 'pagination.html' %}
{% endblock %} {% endblock %}

2
abonapp/urls_abon.py

@ -41,6 +41,8 @@ urlpatterns = [
url(r'^(?P<uid>\d+)/tel/add$', views.tel_add, name='telephone_new'), url(r'^(?P<uid>\d+)/tel/add$', views.tel_add, name='telephone_new'),
url(r'^(?P<uid>\d+)/tel/del$', views.tel_del, name='telephone_del'), url(r'^(?P<uid>\d+)/tel/del$', views.tel_del, name='telephone_del'),
url(r'^(?P<uid>\d+)/markers$', views.EditSibscriberMarkers.as_view(), name='markers_edit'),
url(r'^(?P<uid>\d+)/periodic_pay$', views.add_edit_periodic_pay, name='add_periodic_pay'), url(r'^(?P<uid>\d+)/periodic_pay$', views.add_edit_periodic_pay, name='add_periodic_pay'),
url(r'^(?P<uid>\d+)/periodic_pay(?P<periodic_pay_id>\d+)$', views.add_edit_periodic_pay, name='add_periodic_pay'), url(r'^(?P<uid>\d+)/periodic_pay(?P<periodic_pay_id>\d+)$', views.add_edit_periodic_pay, name='add_periodic_pay'),
url(r'^(?P<uid>\d+)/periodic_pay(?P<periodic_pay_id>\d+)/del$', views.del_periodic_pay, name='del_periodic_pay') url(r'^(?P<uid>\d+)/periodic_pay(?P<periodic_pay_id>\d+)/del$', views.del_periodic_pay, name='del_periodic_pay')

30
abonapp/views.py

@ -10,7 +10,7 @@ from django.http import HttpResponse, HttpResponseBadRequest
from django.contrib import messages from django.contrib import messages
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.generic import ListView
from django.views.generic import ListView, UpdateView
from django.conf import settings from django.conf import settings
from statistics.models import StatCache from statistics.models import StatCache
@ -1036,6 +1036,34 @@ def del_periodic_pay(request, gid, uid, periodic_pay_id):
return redirect('abonapp:abon_services', gid, uid) return redirect('abonapp:abon_services', gid, uid)
@method_decorator([login_required, mydefs.only_admins], name='dispatch')
class EditSibscriberMarkers(UpdateView):
http_method_names = ['get', 'post']
template_name = 'abonapp/modal_user_markers.html'
form_class = forms.MarkersForm
def get_object(self, queryset=None):
obj = models.Abon.objects.get(pk=self.kwargs.get('uid'))
return obj
def get_success_url(self):
return resolve_url('abonapp:abon_home', self.kwargs.get('gid'), self.kwargs.get('uid'))
def get_context_data(self, **kwargs):
context = super(EditSibscriberMarkers, self).get_context_data(**kwargs)
context['gid'] = self.kwargs.get('gid')
context['uid'] = self.kwargs.get('uid')
return context
def form_invalid(self, form):
messages.add_message(self.request, messages.ERROR, _('fix form errors'))
return super(EditSibscriberMarkers, self).form_invalid(form)
def form_valid(self, form):
v = super(EditSibscriberMarkers, self).form_valid(form)
messages.add_message(self.request, messages.SUCCESS, _('User flags has changed successfully'))
return v
# API's # API's

1
requirements.txt

@ -21,3 +21,4 @@ requests
webdavclient webdavclient
pyst2 pyst2
django-jsonview django-jsonview
django-bitfield

19
static/css/custom.css

@ -280,3 +280,22 @@ pre {
word-wrap: break-word; word-wrap: break-word;
} }
/*
* Markers icons
*/
.m-icon{
background-image: url(../img/user_markers.png);
width: 26px;
height: 26px;
display: inline-block;
margin-bottom: -9px;
}
.m-icon_donkey{background-position: 0 0;}
.m-icon_fire{background-position: -26px 0;}
.m-icon_ok{background-position: -52px 0;}
.m-icon_king{background-position: 0 -26px;}
.m-icon_tv{background-position: -26px -26px;}
.m-icon_smile{background-position: -52px -26px;}
.m-icon_dollar{background-position: 0 -52px;}
.m-icon_service{background-position: -26px -52px;}
.m-icon_mrk{background-position: -52px -52px;}

BIN
static/img/user_markers.png

After

Width: 78  |  Height: 78  |  Size: 11 KiB

Loading…
Cancel
Save