diff --git a/devapp/templates/devapp/manage_ports/fix_abon_device.html b/devapp/templates/devapp/manage_ports/fix_abon_device.html
index 84c78ad..1887812 100644
--- a/devapp/templates/devapp/manage_ports/fix_abon_device.html
+++ b/devapp/templates/devapp/manage_ports/fix_abon_device.html
@@ -1,7 +1,7 @@
{% extends request.is_ajax|yesno:'nullcont.htm,devapp/ext.htm' %}
{% load i18n %}
-{% block main %}
+{% block breadcrumb %}
+{% endblock %}
- {% include 'message_block.html' %}
-
-
+{% block page-header %}
+
-
{% endblock %}
diff --git a/devapp/views.py b/devapp/views.py
index 289c3e0..73a5c87 100644
--- a/devapp/views.py
+++ b/devapp/views.py
@@ -131,9 +131,6 @@ class DeviceUpdate(UpdateView):
messages.success(self.request, _('Device info has been saved'))
return r
- def get_success_url(self):
- return resolve_url('devapp:edit', self.device_group.pk, self.object.pk)
-
def dispatch(self, request, *args, **kwargs):
group_id = self.kwargs.get('group_id')
device_group = get_object_or_404(Group, pk=group_id)
@@ -188,9 +185,6 @@ class DeviceCreateView(CreateView):
messages.success(self.request, _('Device info has been saved'))
return r
- def get_success_url(self):
- return resolve_url('devapp:edit', self.device_group.pk, self.object.pk)
-
def dispatch(self, request, *args, **kwargs):
group_id = self.kwargs.get('group_id')
device_group = get_object_or_404(Group, pk=group_id)
@@ -238,11 +232,6 @@ class DeviceUpdateExtra(UpdateView):
messages.success(self.request, _('Device extra data has successfully updated'))
return r
- def get_success_url(self):
- return resolve_url('devapp:edit',
- self.kwargs.get('group_id'),
- self.kwargs.get('device_id'))
-
@login_required
@permission_required('devapp.change_device')
diff --git a/dialing_app/templates/ext.html b/dialing_app/templates/ext.html
index b9fd956..3282f5d 100644
--- a/dialing_app/templates/ext.html
+++ b/dialing_app/templates/ext.html
@@ -1,17 +1,21 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
-{% block main %}
+
+{% block breadcrumb %}
+{% endblock %}
- {% include 'message_block.html' %}
-
+{% block page-header %}
+
diff --git a/djing/global_base_views.py b/djing/global_base_views.py
index 6896bf9..958fa36 100644
--- a/djing/global_base_views.py
+++ b/djing/global_base_views.py
@@ -147,3 +147,7 @@ class BaseListWithFiltering(RedirectWhenErrorMixin, ListView):
'page_number': page_number,
'message': str(e)
})
+
+
+class BaseOrderedFilteringList(OrderingMixin, BaseListWithFiltering):
+ paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
diff --git a/djing/settings.py b/djing/settings.py
index d8bbed9..898fc8a 100644
--- a/djing/settings.py
+++ b/djing/settings.py
@@ -33,12 +33,12 @@ AUTHENTICATION_BACKENDS = (
# Application definition
INSTALLED_APPS = [
- # 'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'ip_pool',
'accounts_app',
'abonapp',
'tariff_app',
@@ -58,6 +58,10 @@ INSTALLED_APPS = [
'bootstrap3'
]
+if DEBUG:
+ INSTALLED_APPS.insert(0, 'django.contrib.admin')
+
+
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
diff --git a/djing/templatetags/globaltags.py b/djing/templatetags/globaltags.py
index 9b36fd9..66b31f2 100644
--- a/djing/templatetags/globaltags.py
+++ b/djing/templatetags/globaltags.py
@@ -1,5 +1,8 @@
+from urllib.parse import unquote
+
from django import template
from django.conf import settings
+from django.utils.http import is_safe_url
register = template.Library()
@@ -7,3 +10,13 @@ register = template.Library()
@register.simple_tag
def global_var(var_name):
return getattr(settings, var_name, '')
+
+
+@register.simple_tag
+def back_url(request):
+ url = request.META.get('HTTP_REFERER')
+ if url:
+ url = unquote(url) # HTTP_REFERER may be encoded.
+ if not is_safe_url(url=url, allowed_hosts={request.get_host()}, require_https=request.is_secure()):
+ url = '/'
+ return url
diff --git a/djing/urls.py b/djing/urls.py
index 1ea66bf..9c65f70 100644
--- a/djing/urls.py
+++ b/djing/urls.py
@@ -1,6 +1,5 @@
from django.conf.urls import url, include
from django.conf import settings
-# from django.contrib import admin
from .views import home
@@ -18,17 +17,18 @@ urlpatterns = [
url(r'^msg/', include('msg_app.urls', namespace='msg_app')),
url(r'^dialing/', include('dialing_app.urls', namespace='dialapp')),
url(r'^groups/', include('group_app.urls', namespace='group_app')),
+ url(r'^ip_pool/', include('ip_pool.urls', namespace='ip_pool'))
# Switch language
#url(r'^i18n/', include('django.conf.urls.i18n')),
- # url(r'^admin/', admin.site.urls)
-
]
if settings.DEBUG:
from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
+ from django.contrib import admin
- urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
- urlpatterns += staticfiles_urlpatterns()
+ urlpatterns.extend(static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT))
+ urlpatterns.extend(staticfiles_urlpatterns())
+ urlpatterns.append(url(r'^admin/', admin.site.urls))
diff --git a/group_app/templates/group_app/ext.html b/group_app/templates/group_app/ext.html
index 09ab095..5e2aa50 100644
--- a/group_app/templates/group_app/ext.html
+++ b/group_app/templates/group_app/ext.html
@@ -1,23 +1,25 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
-{% block main %}
+
+{% block breadcrumb %}
- {% trans 'Groups' %}
- {% block active_text %}{% trans 'Groups' %}{% endblock %}
+{% endblock %}
- {% include 'message_block.html' %}
-
+{% block page-header %}
+
{% trans 'Groups' %}
+{% endblock %}
+
+{% block main %}
{% block content %}{% endblock %}
-
{% endblock %}
\ No newline at end of file
diff --git a/group_app/templates/group_app/group_list.html b/group_app/templates/group_app/group_list.html
index cc86158..bce8572 100644
--- a/group_app/templates/group_app/group_list.html
+++ b/group_app/templates/group_app/group_list.html
@@ -1,16 +1,20 @@
{% extends 'base.html' %}
{% load i18n %}
-{% block main %}
+{% block breadcrumb %}
- {% trans 'Groups' %}
+{% endblock %}
+
+{% block page-header %}
{% trans 'Groups' %}
+{% endblock %}
- {% include 'message_block.html' %}
+{% block main %}
-
- {% include 'pagination.html' %}
-
{% endblock %}
diff --git a/ip_pool/__init__.py b/ip_pool/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ip_pool/admin.py b/ip_pool/admin.py
new file mode 100644
index 0000000..a85b3c6
--- /dev/null
+++ b/ip_pool/admin.py
@@ -0,0 +1,5 @@
+from django.contrib import admin
+from ip_pool import models
+
+admin.site.register(models.NetworkModel)
+admin.site.register(models.EmployedIpModel)
diff --git a/ip_pool/apps.py b/ip_pool/apps.py
new file mode 100644
index 0000000..551cca3
--- /dev/null
+++ b/ip_pool/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class IpPoolConfig(AppConfig):
+ name = 'ip_pool'
diff --git a/ip_pool/forms.py b/ip_pool/forms.py
new file mode 100644
index 0000000..0b20f94
--- /dev/null
+++ b/ip_pool/forms.py
@@ -0,0 +1,30 @@
+from netaddr import IPNetwork, AddrFormatError, IPAddress
+from django import forms
+from django.core.exceptions import ValidationError
+from ip_pool import models
+
+
+class NetworkForm(forms.ModelForm):
+
+ def clean_network(self):
+ network = self.cleaned_data.get('network')
+ try:
+ return IPAddress(network)
+ except AddrFormatError as e:
+ raise ValidationError(e, code='invalid')
+
+ class Meta:
+ model = models.NetworkModel
+ fields = '__all__'
+
+
+class EmployedIpForm(forms.ModelForm):
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ if self.instance is None:
+ self.fields['ip'].initial = '127.0.0.1'
+
+ class Meta:
+ model = models.EmployedIpModel
+ fields = '__all__'
diff --git a/ip_pool/migrations/0001_initial.py b/ip_pool/migrations/0001_initial.py
new file mode 100644
index 0000000..56d30df
--- /dev/null
+++ b/ip_pool/migrations/0001_initial.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2018-06-12 13:24
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='EmployedIpModel',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('ip', models.GenericIPAddressField(unique=True, verbose_name='Ip address')),
+ ],
+ options={
+ 'verbose_name': 'Employed ip',
+ 'verbose_name_plural': 'Employed ip addresses',
+ 'db_table': 'ip_pool_employed_ip',
+ 'ordering': ('-id',),
+ },
+ ),
+ migrations.CreateModel(
+ name='NetworkModel',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('network', models.GenericIPAddressField(help_text='Dot separated ip address. For example: 192.168.1.100', unique=True, verbose_name='IP network')),
+ ('mask', models.PositiveSmallIntegerField(default=24, help_text='For example: 24, if network is 192.168.1.0/24', verbose_name='Mask')),
+ ('work_range_start_ip', models.GenericIPAddressField(default=2, help_text='Ip from 192.168.1.2 may be used', verbose_name='Work range start ip')),
+ ('work_range_end_ip', models.GenericIPAddressField(default=254, help_text='Ip may be used until 192.168.1.254', verbose_name='Work range end ip')),
+ ('description', models.CharField(max_length=64, verbose_name='Description')),
+ ],
+ options={
+ 'verbose_name': 'Network',
+ 'verbose_name_plural': 'Networks',
+ 'db_table': 'ip_pool_network',
+ 'ordering': ('description',),
+ },
+ ),
+ migrations.AddField(
+ model_name='employedipmodel',
+ name='network',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ip_pool.NetworkModel', verbose_name='Parent network'),
+ ),
+ migrations.AlterUniqueTogether(
+ name='employedipmodel',
+ unique_together=set([('ip', 'network')]),
+ ),
+ ]
diff --git a/ip_pool/migrations/__init__.py b/ip_pool/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ip_pool/models.py b/ip_pool/models.py
new file mode 100644
index 0000000..e4db696
--- /dev/null
+++ b/ip_pool/models.py
@@ -0,0 +1,91 @@
+from typing import Optional
+
+from django.shortcuts import resolve_url
+from netaddr import IPNetwork, IPAddress
+from django.core.exceptions import ValidationError
+from django.db import models
+from django.utils.translation import gettext_lazy as _
+
+
+class NetworkModel(models.Model):
+ _netw_cache = None
+
+ network = models.GenericIPAddressField(
+ verbose_name=_('IP network'),
+ help_text=_('Dot separated ip address of network. For example: 192.168.1.0'),
+ unique=True
+ )
+ mask = models.PositiveSmallIntegerField(
+ _('Mask'),
+ help_text=_('For example: 24, if network is 192.168.1.0/24'),
+ default=24
+ )
+ work_range_start_ip = models.GenericIPAddressField(
+ verbose_name=_('Work range start ip'),
+ help_text=_('For example 192.168.1.2, this is first ip that may be used')
+ )
+ work_range_end_ip = models.GenericIPAddressField(
+ verbose_name=_('Work range end ip'),
+ help_text=_('Ip may be used until 192.168.1.254')
+ )
+ description = models.CharField(_('Description'), max_length=64)
+
+ def __str__(self):
+ return "%s: %s/%d" % (self.description, self.network, self.mask)
+
+ def get_network(self) -> IPNetwork:
+ if self._netw_cache is None:
+ self._netw_cache = IPNetwork("%s/%s" % (self.network, self.mask or 32))
+ return self._netw_cache
+
+ def get_absolute_url(self):
+ return resolve_url('ip_pool:net_edit', self.pk)
+
+ class Meta:
+ db_table = 'ip_pool_network'
+ verbose_name = _('Network')
+ verbose_name_plural = _('Networks')
+ ordering = ('description',)
+
+
+class EmployedIpManager(models.Manager):
+
+ def get_free_ip(self, network: NetworkModel) -> Optional[IPAddress]:
+ netw = IPNetwork(network)
+ employed_ip_queryset = self.filter(network=network)
+ free_ip = next(IPAddress(net) for ip, net in zip(
+ employed_ip_queryset, netw
+ ) if ip != net)
+ return free_ip
+
+
+class EmployedIpModel(models.Model):
+ ip = models.GenericIPAddressField(verbose_name=_('Ip address'), unique=True)
+ network = models.ForeignKey(NetworkModel, on_delete=models.CASCADE, verbose_name=_('Parent network'))
+
+ objects = EmployedIpManager()
+
+ def __str__(self):
+ return self.ip
+
+ def clean(self):
+ ip = IPAddress(self.ip)
+ network = self.network.get_network()
+
+ if ip not in network:
+ raise ValidationError(_('Ip address %(ip)s not in %(net)s network') % {
+ 'ip': ip,
+ 'net': network
+ }, code='invalid')
+
+ start_allowed_ip = IPAddress(self.network.work_range_start_ip)
+ end_allowed_ip = IPAddress(self.network.work_range_end_ip)
+ if not start_allowed_ip <= ip <= end_allowed_ip:
+ raise ValidationError(_('Ip address that you entered is not in work range'), code='invalid')
+
+ class Meta:
+ db_table = 'ip_pool_employed_ip'
+ verbose_name = _('Employed ip')
+ verbose_name_plural = _('Employed ip addresses')
+ ordering = ('-id',)
+ unique_together = ('ip', 'network')
diff --git a/ip_pool/templates/ip_pool/employed_ip_list.html b/ip_pool/templates/ip_pool/employed_ip_list.html
new file mode 100644
index 0000000..f86dc66
--- /dev/null
+++ b/ip_pool/templates/ip_pool/employed_ip_list.html
@@ -0,0 +1,39 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% load bootstrap3 %}
+
+{% block breadcrumb %}
+
+
+ - {% trans 'Ip pool' %}
+ - {{ net }}
+ - {% trans 'Ip list' %}
+
+{% endblock %}
+
+{% block page-header %}{% trans 'Ip list' %}{% endblock %}
+
+{% block main %}
+
+
+
+
+ | {% trans 'Ip' %} |
+ {% trans 'Network' %} |
+
+
+
+ {% for ip in object_list %}
+
+ | {{ ip.ip }} |
+ {{ ip.network }} |
+
+ {% empty %}
+
+ | {% trans 'You have not any available dedicated ips in this network' %} |
+
+ {% endfor %}
+
+
+
+{% endblock %}
diff --git a/ip_pool/templates/ip_pool/ext.html b/ip_pool/templates/ip_pool/ext.html
new file mode 100644
index 0000000..eee4f83
--- /dev/null
+++ b/ip_pool/templates/ip_pool/ext.html
@@ -0,0 +1,30 @@
+{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
+{% load i18n %}
+
+
+{% block breadcrumb %}
+
+
+ - {% trans 'Ip pool' %}
+
+{% endblock %}
+
+
+{% block main %}
+
+
+
+
+
+ {% block content %}{% endblock %}
+
+
+
+{% endblock %}
diff --git a/ip_pool/templates/ip_pool/net_add.html b/ip_pool/templates/ip_pool/net_add.html
new file mode 100644
index 0000000..3dbb6cd
--- /dev/null
+++ b/ip_pool/templates/ip_pool/net_add.html
@@ -0,0 +1,35 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% load bootstrap3 %}
+{% load globaltags %}
+
+{% block breadcrumb %}
+
+
+ - {% trans 'Ip pool' %}
+ - {% trans 'Add network' %}
+
+{% endblock %}
+
+{% block main %}
+
+{% endblock %}
diff --git a/ip_pool/templates/ip_pool/net_edit.html b/ip_pool/templates/ip_pool/net_edit.html
new file mode 100644
index 0000000..7ab999e
--- /dev/null
+++ b/ip_pool/templates/ip_pool/net_edit.html
@@ -0,0 +1,41 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% load bootstrap3 %}
+{% load globaltags %}
+
+{% block breadcrumb %}
+
+
+ - {% trans 'Ip pool' %}
+ - {{ object }}
+
+{% endblock %}
+
+{% block page-header %}{{ object }}{% endblock %}
+
+{% block main %}
+
+{% endblock %}
diff --git a/ip_pool/templates/ip_pool/network_list.html b/ip_pool/templates/ip_pool/network_list.html
new file mode 100644
index 0000000..75378da
--- /dev/null
+++ b/ip_pool/templates/ip_pool/network_list.html
@@ -0,0 +1,70 @@
+{% extends 'base.html' %}
+{% load i18n %}
+
+{% block breadcrumb %}
+
+
+ - {% trans 'Ip pool' %}
+
+{% endblock %}
+
+{% block page-header %}
+ {% trans 'Networks' %}
+{% endblock %}
+
+{% block main %}
+
+{% endblock %}
diff --git a/ip_pool/tests.py b/ip_pool/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/ip_pool/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/ip_pool/urls.py b/ip_pool/urls.py
new file mode 100644
index 0000000..6640980
--- /dev/null
+++ b/ip_pool/urls.py
@@ -0,0 +1,11 @@
+from django.conf.urls import url
+from ip_pool import views
+
+app_name = 'ip_pool'
+
+urlpatterns = [
+ url('^$', views.NetworksListView.as_view(), name='networks'),
+ url('^network_add/$', views.NetworkCreateView.as_view(), name='net_add'),
+ url('^(?P
\d{1,6})/$', views.IpEmployedListView.as_view(), name='ip_list'),
+ url('^(?P\d{1,6})/edit$', views.NetworkUpdateView.as_view(), name='net_edit'),
+]
diff --git a/ip_pool/views.py b/ip_pool/views.py
new file mode 100644
index 0000000..e36bcdc
--- /dev/null
+++ b/ip_pool/views.py
@@ -0,0 +1,60 @@
+from django.contrib.auth.decorators import login_required
+from django.contrib import messages
+from django.shortcuts import resolve_url, get_object_or_404
+from django.utils.decorators import method_decorator
+from django.utils.translation import gettext_lazy as _
+from django.views.generic import UpdateView, CreateView
+
+from guardian.decorators import permission_required_or_403 as permission_required
+from djing.global_base_views import BaseOrderedFilteringList
+from ip_pool import models, forms
+
+
+@method_decorator(login_required, name='dispatch')
+class NetworksListView(BaseOrderedFilteringList):
+ template_name = 'ip_pool/network_list.html'
+ context_object_name = 'networks'
+ model = models.NetworkModel
+
+
+@method_decorator(login_required, name='dispatch')
+@method_decorator(permission_required('ip_pool.change_networkmodel'), name='dispatch')
+class NetworkUpdateView(UpdateView):
+ model = models.NetworkModel
+ template_name = 'ip_pool/net_edit.html'
+ form_class = forms.NetworkForm
+ pk_url_kwarg = 'net_id'
+
+ def form_valid(self, form):
+ r = super().form_valid(form)
+ messages.success(self.request, _('Network successfully updated'))
+ return r
+
+
+@method_decorator(login_required, name='dispatch')
+class IpEmployedListView(BaseOrderedFilteringList):
+ template_name = 'ip_pool/employed_ip_list.html'
+ model = models.EmployedIpModel
+
+ def get_context_data(self, **kwargs):
+ net_id = self.kwargs.get('net_id')
+ context = super().get_context_data(**kwargs)
+ context['net'] = get_object_or_404(models.NetworkModel, pk=net_id)
+ return context
+
+ def get_queryset(self):
+ net_id = self.kwargs.get('net_id')
+ return self.model.objects.filter(network__id=net_id)
+
+
+@method_decorator(login_required, name='dispatch')
+@method_decorator(permission_required('ip_pool.add_networkmodel'), name='dispatch')
+class NetworkCreateView(CreateView):
+ model = models.NetworkModel
+ template_name = 'ip_pool/net_add.html'
+ form_class = forms.NetworkForm
+
+ def form_valid(self, form):
+ r = super().form_valid(form)
+ messages.success(self.request, _('Network has been created'))
+ return r
diff --git a/locale/ru/LC_MESSAGES/django.po b/locale/ru/LC_MESSAGES/django.po
index f9f8301..fcb7b78 100644
--- a/locale/ru/LC_MESSAGES/django.po
+++ b/locale/ru/LC_MESSAGES/django.po
@@ -108,5 +108,8 @@ msgstr "Звонки"
msgid "Devices"
msgstr "Устройства"
-msgid "Language"
-msgstr "Язык"
+# msgid "Language"
+# msgstr "Язык"
+
+msgid "Ip pool"
+msgstr "IP пул"
diff --git a/mapapp/templates/maps/add_device.html b/mapapp/templates/maps/add_device.html
index 537e1c0..4f4fa11 100644
--- a/mapapp/templates/maps/add_device.html
+++ b/mapapp/templates/maps/add_device.html
@@ -1,22 +1,18 @@
{% extends 'base.html' %}
{% load i18n %}
{% load bootstrap3 %}
-{% block main %}
-
-
-
- - {% trans 'Map settings' %}
- - {{ dot.title }}
- - {% trans 'Add devices' %}
-
-
-{% include 'message_block.html' %}
-
-
+{% block breadcrumb %}
+
+
+ - {% trans 'Map settings' %}
+ - {{ dot.title }}
+ - {% trans 'Add devices' %}
+
+{% endblock %}
+{% block main %}
@@ -45,7 +41,6 @@
});
});
-
-
{% endblock %}
diff --git a/mapapp/templates/maps/dot.html b/mapapp/templates/maps/dot.html
index 8822423..5779e81 100644
--- a/mapapp/templates/maps/dot.html
+++ b/mapapp/templates/maps/dot.html
@@ -2,22 +2,29 @@
{% load i18n %}
{% load bootstrap3 %}
{% load globaltags %}
-{% block main %}
-
-
- - {% trans 'Map settings' %}
- {% if dot.id %}
- - {{ dot.title }}
- {% url 'mapapp:edit_dot' dot.id as form_url %}
- {% else %}
- - {% trans 'Add new point' %}
- {% url 'mapapp:add_dot' as form_url %}
- {% endif %}
-
-{% include 'message_block.html' %}
+{% block breadcrumb %}
+
+
+ - {% trans 'Map settings' %}
+ {% if dot.id %}
+ - {{ dot.title }}
+ {% url 'mapapp:edit_dot' dot.id as form_url %}
+ {% else %}
+ - {% trans 'Add new point' %}
+ {% url 'mapapp:add_dot' as form_url %}
+ {% endif %}
+
+{% endblock %}
+
+{% block page-header %}
+
{% trans 'Map point' %}
+{% endblock %}
+
+
+{% block main %}
-
{% endblock %}
diff --git a/tariff_app/templates/tariff_app/periodic_pays/add_edit.html b/tariff_app/templates/tariff_app/periodic_pays/add_edit.html
index 930fccd..8be7124 100644
--- a/tariff_app/templates/tariff_app/periodic_pays/add_edit.html
+++ b/tariff_app/templates/tariff_app/periodic_pays/add_edit.html
@@ -1,8 +1,8 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
{% load bootstrap3 %}
-{% block main %}
+{% block breadcrumb %}
- {% trans 'Services' %}
@@ -12,18 +12,21 @@
- {% trans 'Add new periodic pay' %}
{% endif %}
+{% endblock %}
- {% include 'message_block.html' %}
- {% if pay_instance %}
-
- {% url 'tarifs:periodic_pay_edit' pay_instance.id as form_url %}
- {% else %}
- {% url 'tarifs:periodic_pay_add' as form_url %}
- {% endif %}
+{% if pay_instance %}
+ {% block page-header %}
+
{{ pay_instance.name }}
+ {% endblock %}
+ {% url 'tarifs:periodic_pay_edit' pay_instance.id as form_url %}
+{% else %}
+ {% url 'tarifs:periodic_pay_add' as form_url %}
+{% endif %}
+
+
+{% block main %}
{% trans 'Pay details' %}
@@ -47,5 +50,4 @@
-
{% endblock %}
diff --git a/taskapp/templates/taskapp/add_edit_task.html b/taskapp/templates/taskapp/add_edit_task.html
index a72f806..c5f0abd 100644
--- a/taskapp/templates/taskapp/add_edit_task.html
+++ b/taskapp/templates/taskapp/add_edit_task.html
@@ -2,16 +2,18 @@
{% load i18n %}
{% load bootstrap3 %}
{% load globaltags %}
-{% block main %}
+
+{% block breadcrumb %}
- {% trans 'Tasks' %}
- {% if task.id %}{% trans 'Edit' %}{% else %}{% trans 'Create' %}{% endif %}
+{% endblock %}
- {% include 'message_block.html' %}
+{% block main %}
diff --git a/taskapp/templates/taskapp/ext.htm b/taskapp/templates/taskapp/ext.htm
index 4df5e41..1105e95 100644
--- a/taskapp/templates/taskapp/ext.htm
+++ b/taskapp/templates/taskapp/ext.htm
@@ -1,20 +1,20 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
-{% block main %}
+
+{% block breadcrumb %}
- {% trans 'Tasks' %}
+{% endblock %}
- {% include 'message_block.html' %}
+{% block page-header %}
+
{% trans 'Tasks to be performed' %}
+{% endblock %}
-
+
+{% block main %}
diff --git a/taskapp/templates/taskapp/tasklist_all.html b/taskapp/templates/taskapp/tasklist_all.html
index 78cfdef..654b30b 100644
--- a/taskapp/templates/taskapp/tasklist_all.html
+++ b/taskapp/templates/taskapp/tasklist_all.html
@@ -1,19 +1,23 @@
{% extends request.is_ajax|yesno:'bajax.html,base.html' %}
{% load i18n %}
{% load tasktags %}
-{% block main %}
+
+{% block breadcrumb %}
- {% trans 'Tasks' %}
- {% trans 'All tasks' %}
+{% endblock %}
- {% include 'message_block.html' %}
-
+{% block page-header %}
+ {% trans 'Records of all the tasks in the system' %}
+{% endblock %}
+
+
+{% block main %}
- {% include 'pagination.html' %}
-
{% endblock %}
diff --git a/taskapp/templates/taskapp/tasklist_empty.html b/taskapp/templates/taskapp/tasklist_empty.html
index f5632e7..5a69382 100644
--- a/taskapp/templates/taskapp/tasklist_empty.html
+++ b/taskapp/templates/taskapp/tasklist_empty.html
@@ -1,8 +1,8 @@
{% extends request.is_ajax|yesno:'nullcont.htm,taskapp/ext.htm' %}
{% load i18n %}
-{% block pagetitle %}
- {% trans 'Tasks in which no recipients' %}
+{% block page-header %}
+ {% trans 'Tasks in which no recipients' %}
{% endblock %}
{% block content %}
diff --git a/taskapp/templates/taskapp/tasklist_failed.html b/taskapp/templates/taskapp/tasklist_failed.html
index 75b8431..adcb752 100644
--- a/taskapp/templates/taskapp/tasklist_failed.html
+++ b/taskapp/templates/taskapp/tasklist_failed.html
@@ -1,8 +1,8 @@
{% extends request.is_ajax|yesno:'nullcont.htm,taskapp/ext.htm' %}
{% load i18n %}
-{% block pagetitle %}
- {% trans 'Tasks in which was trouble while at runtime' %}
+{% block page-header %}
+ {% trans 'Tasks in which was trouble while at runtime' %}
{% endblock %}
{% block content %}
diff --git a/taskapp/views.py b/taskapp/views.py
index 83bd8d3..2816936 100644
--- a/taskapp/views.py
+++ b/taskapp/views.py
@@ -271,11 +271,8 @@ def check_news(request):
@method_decorator(permission_required('taskapp.add_extracomment'), name='dispatch')
class NewCommentView(CreateView):
form_class = ExtraCommentForm
- http_method_names = ['get', 'post']
-
- def get_success_url(self):
- task_id = self.kwargs.get('task_id')
- return resolve_url('taskapp:edit', task_id)
+ model = ExtraComment
+ http_method_names = ('get', 'post')
def form_valid(self, form):
self.task = get_object_or_404(Task, pk=self.kwargs.get('task_id'))
diff --git a/templates/base.html b/templates/base.html
index 1ab7b31..23a8ad6 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -33,33 +33,45 @@
-
{% trans 'Subscribers' %}
-
+
+
{% url 'taskapp:home' as task_home %}
-
{% trans 'Tasks' %}
{% if tasks_count > 0 %}{{ tasks_count }}{% endif %}
-
+
+
{% url 'group_app:group_list' as group_list_link %}
-
{% trans 'Groups' %}
-
+
+
{% url 'tarifs:home' as tarifs_home %}
-
{% trans 'Services' %}
-
+
+
+
+ {% url 'ip_pool:networks' as ippool_home %}
+ -
+
+ {% trans 'Ip pool' %}
+
+
{% if request.user.is_superuser %}
{% url 'mapapp:options' as mapapp_ops %}
-
{% trans 'Map settings' %}
-
+
+
{% endif %}
{% url 'msg_app:home' as privmsg_home %}
@@ -69,21 +81,24 @@
{% if new_messages_count > 0 %}
{{ new_messages_count }}
{% endif %}
-
+
+
{% if perms.dialing_app.change_asteriskcdr %}
{% url 'dialapp:home' as dialhome %}
-
{% trans 'Dialing' %}
-
+
+
{% endif %}
{% url 'devapp:group_list' as devapp_groups %}
-
{% trans 'Devices' %}
-
+
+
@@ -96,8 +111,22 @@
+ {% block breadcrumb %}
+
+
+
+ {% endblock %}
+
+ {% include 'message_block.html' %}
+
+
+
{% block main %}{% endblock %}
+ {% include 'pagination.html' %}
+
{% endblock %}