+
@@ -76,7 +77,7 @@
{% trans 'Mac on OLT' %}: {{ onu_details.mac }}
-
+
{% trans 'Fix it' %}
diff --git a/devapp/templates/devapp/custom_dev_page/onu_for_zte.html b/devapp/templates/devapp/custom_dev_page/onu_for_zte.html
new file mode 100644
index 0000000..49317c6
--- /dev/null
+++ b/devapp/templates/devapp/custom_dev_page/onu_for_zte.html
@@ -0,0 +1,91 @@
+{% extends request.is_ajax|yesno:'nullcont.htm,devapp/ext.htm' %}
+{% load i18n %}
+{% block content %}
+
+{% with uptime=dev_manager.uptime onu_details=dev_manager.get_details %}
+
+
+
+
+
{{ dev.get_devtype_display|default:_('Title of the type of switch') }}.
+ {% if uptime %}
+ {% trans 'Uptime' %} {{ uptime }}
+ {% endif %}
+
+
+
+
+ - {% trans 'Ip address' %}: {{ dev.ip_address|default:'-' }}
+ - {% trans 'Mac' %}: {{ dev.mac_addr }}
+ - {% trans 'Description' %}: {{ dev.comment }}
+ {% for da in dev_accs %}
+ - {% trans 'Attached user' %}:
+ {% if da.group %}
+ {{ da.get_full_name }}
+ {% else %}
+ {{ da.get_full_name }}
+ {% endif %}
+
+ {% endfor %}
+ {% if dev.parent_dev %}
+ -
+ {% with pdev=dev.parent_dev pdgrp=dev.parent_dev.group %}
+ {% trans 'Parent device' %}:
+
+ {{ pdev.ip_address|default:'-' }} {{ pdev.comment }}
+
+ {% endwith %}
+
+ {% endif %}
+
+
+
+
+
+
+
+
{% trans 'ONU Status' %}
+
+
+
+ {% if onu_details %}
+ {% if onu_details.err %}
+
+
+ {% trans 'ONU error' %}: {{ onu_details.err }}
+
+ {% else %}
+
+ {% endif %}
+ {% else %}
+
{% trans 'Info does not fetch' %}
+ {% endif %}
+
+
+
+
+
+{% endwith %}
+{% endblock %}
diff --git a/devapp/templates/devapp/dev.html b/devapp/templates/devapp/dev.html
index 3910334..31f2f9d 100644
--- a/devapp/templates/devapp/dev.html
+++ b/devapp/templates/devapp/dev.html
@@ -52,7 +52,7 @@
{% bootstrap_icon 'list-alt' as ic %}
- {% bootstrap_field form.snmp_item_num addon_before=ic %}
+ {% bootstrap_field form.snmp_extra addon_before=ic %}
{% bootstrap_field form.is_noticeable %}
diff --git a/devapp/views.py b/devapp/views.py
index 44afebb..5417e75 100644
--- a/devapp/views.py
+++ b/devapp/views.py
@@ -14,7 +14,7 @@ from easysnmp import EasySNMPTimeoutError, EasySNMPError
from django.views.generic import DetailView
from devapp.base_intr import DeviceImplementationError
-from mydefs import res_success, res_error, only_admins, safe_int
+from djing.lib import res_success, res_error, only_admins, safe_int
from abonapp.models import Abon
from group_app.models import Group
from accounts_app.models import UserProfile
@@ -137,7 +137,7 @@ def dev(request, group_id, device_id=0):
'comment': request.GET.get('c'),
'ip_address': request.GET.get('ip'),
'man_passw': getattr(settings, 'DEFAULT_SNMP_PASSWORD', ''),
- 'snmp_item_num': request.GET.get('n') or 0
+ 'snmp_extra': request.GET.get('n') or ''
})
else:
frm = DeviceForm(instance=devinst)
@@ -505,8 +505,8 @@ def fix_onu(request):
# convert bytes mac address to str presentation mac address
real_mac = ':'.join('%x' % ord(i) for i in srcmac)
if mac == real_mac:
- onu.snmp_item_num = snmpnum
- onu.save(update_fields=('snmp_item_num',))
+ onu.snmp_extra = str(snmpnum)
+ onu.save(update_fields=('snmp_extra',))
status = 0
text = '
%s' % _('Fixed')
break
@@ -619,11 +619,11 @@ class NagiosObjectsConfView(global_base_views.AuthenticatedOrHashAuthView):
if device.devtype == 'On':
if device.parent_dev:
host_addr = device.parent_dev.ip_address
- conf = self.templ_onu(host_name, host_addr, mac=mac_addr, snmp_item=device.snmp_item_num or None)
+ conf = self.templ_onu(host_name, host_addr, mac=mac_addr, snmp_item=device.snmp_extra or None)
else:
if device.ip_address:
host_addr = device.ip_address
- conf = self.templ_onu(host_name, host_addr, mac=mac_addr, snmp_item=device.snmp_item_num or None)
+ conf = self.templ_onu(host_name, host_addr, mac=mac_addr, snmp_item=device.snmp_extra or None)
else:
parent_host_name = norm_name("%d%s" % (
device.parent_dev.pk, translit(device.parent_dev.comment, language_code='ru', reversed=True)
@@ -651,7 +651,7 @@ class NagiosObjectsConfView(global_base_views.AuthenticatedOrHashAuthView):
return '\n'.join(i for i in r if i)
@staticmethod
- def templ_onu(host_name: str, host_addr: str, mac: Optional[str], snmp_item: int):
+ def templ_onu(host_name: str, host_addr: str, mac: Optional[str], snmp_item: str):
if not host_addr:
return
r = (
@@ -659,7 +659,7 @@ class NagiosObjectsConfView(global_base_views.AuthenticatedOrHashAuthView):
"\tuse device-onu",
"\thost_name %s" % host_name,
"\taddress %s" % host_addr,
- "\t_snmp_item %d" % snmp_item if snmp_item is not None else '',
+ "\t_snmp_item %s" % snmp_item if snmp_item is not None else '',
"\t_mac_addr %s" % mac if mac is not None else '',
"}\n"
)
diff --git a/djing/auth_backends.py b/djing/lib/auth_backends.py
similarity index 100%
rename from djing/auth_backends.py
rename to djing/lib/auth_backends.py
diff --git a/migrate_to_0.2.py b/migrate_to_0.2.py
deleted file mode 100755
index a2edee8..0000000
--- a/migrate_to_0.2.py
+++ /dev/null
@@ -1,359 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-import os
-import sys
-import shutil
-from json import dump
-import django
-
-'''
-Some permissions is not migrates, all admins is superuser
-after migrate.
-'''
-
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djing.settings")
-from django.db.models import fields as django_fields
-
-
-def get_fixture_from_unchanget_model(model_name: str, model_class):
- """
- Создаёт фикстуру если модели между версиями не изменились
- :param model_name: str 'app_label.model_name'
- :param model_class: Model модель для которой надо сделать фикстуру
- :return: список словарей
- """
- print(model_name)
-
- def get_fields(obj):
- fields = dict()
- for field in obj._meta.get_fields():
- if isinstance(field,
- (django_fields.reverse_related.ManyToOneRel, django_fields.reverse_related.ManyToManyRel)):
- continue
- field_val = getattr(obj, field.name)
- if field_val is None:
- continue
- if isinstance(field, django_fields.related.ManyToManyField):
- fields[field.name] = [f.pk for f in field_val.all()]
- elif isinstance(field,
- (django_fields.related.ForeignKey, django.contrib.contenttypes.fields.GenericForeignKey)):
- fields[field.name] = field_val.pk
- elif isinstance(field, django_fields.FloatField):
- fields[field.name] = float(field_val)
- elif isinstance(field, django_fields.DateTimeField):
- fields[field.name] = str(field_val)
- elif isinstance(field, django_fields.AutoField):
- continue
- else:
- fields[field.name] = field_val
- return fields
-
- res = [{
- 'model': model_name,
- 'pk': obj.pk,
- 'fields': get_fields(obj)
- } for obj in model_class.objects.all()]
- return res
-
-
-def dump_groups():
- from abonapp import models
- print('group_app.group')
- res = [{
- 'model': 'group_app.group',
- 'pk': abon_group.pk,
- 'fields': {
- 'title': abon_group.title
- }
- } for abon_group in models.AbonGroup.objects.all()]
- return res
-
-
-def dump_abonapp():
- from abonapp import models
-
- res = get_fixture_from_unchanget_model('abonapp.abontariff', models.AbonTariff)
-
- res += get_fixture_from_unchanget_model('abonapp.abonstreet', models.AbonStreet)
-
- res += get_fixture_from_unchanget_model('abonapp.extrafieldsmodel', models.ExtraFieldsModel)
-
- # res += get_fixture_from_unchanget_model('abonapp.abonlog', models.AbonLog)
-
- print('abonapp.abon')
- res += [{
- 'model': 'abonapp.abon',
- 'pk': abon.pk,
- 'fields': {
- 'current_tariff': abon.current_tariff.pk if abon.current_tariff else None,
- 'group': abon.group.pk if abon.group else None,
- 'ballance': abon.ballance,
- 'ip_address': abon.ip_address,
- 'description': abon.description,
- 'street': abon.street.pk if abon.street else None,
- 'house': abon.house,
- 'extra_fields': [a.pk for a in abon.extra_fields.all()],
- 'device': abon.device.pk if abon.device else None,
- 'dev_port': abon.dev_port if abon.dev_port else None,
- 'is_dynamic_ip': abon.is_dynamic_ip,
- 'markers': abon.markers
- }
- } for abon in models.Abon.objects.filter(is_admin=False)]
-
- res += get_fixture_from_unchanget_model('abonapp.passportinfo', models.PassportInfo)
-
- res += get_fixture_from_unchanget_model('abonapp.invoiceforpayment', models.InvoiceForPayment)
-
- res += get_fixture_from_unchanget_model('abonapp.alltimepaylog', models.AllTimePayLog)
-
- res += get_fixture_from_unchanget_model('abonapp.abonrawpassword', models.AbonRawPassword)
-
- res += get_fixture_from_unchanget_model('abonapp.additionaltelephone', models.AdditionalTelephone)
-
- res += get_fixture_from_unchanget_model('abonapp.periodicpayforid', models.PeriodicPayForId)
-
- return res
-
-
-def dump_tariffs():
- from tariff_app import models
- from abonapp.models import AbonGroup
- print('tariff_app.tariff')
- res = [{
- 'model': 'tariff_app.tariff',
- 'pk': trf.pk,
- 'fields': {
- 'title': trf.title,
- 'descr': trf.descr,
- 'speedIn': trf.speedIn,
- 'speedOut': trf.speedOut,
- 'amount': trf.amount,
- 'calc_type': trf.calc_type,
- 'is_admin': trf.is_admin,
- 'groups': [ag.pk for ag in AbonGroup.objects.filter(tariffs__in=[trf])]
- }
- } for trf in models.Tariff.objects.all()]
-
- res += get_fixture_from_unchanget_model('tariff_app.periodicpay', models.PeriodicPay)
-
- return res
-
-
-def dump_devs():
- from devapp import models
- print('devapp.device')
- res = [{
- 'model': 'devapp.device',
- 'pk': dv.pk,
- 'fields': {
- 'ip_address': dv.ip_address,
- 'mac_addr': str(dv.mac_addr) if dv.mac_addr else None,
- 'comment': dv.comment,
- 'devtype': dv.devtype,
- 'man_passw': dv.man_passw,
- 'group': dv.user_group.pk if dv.user_group else None,
- 'parent_dev': dv.parent_dev.pk if dv.parent_dev else None,
- 'snmp_item_num': dv.snmp_item_num,
- 'status': dv.status,
- 'is_noticeable': dv.is_noticeable
- }
- } for dv in models.Device.objects.all()]
-
- res += get_fixture_from_unchanget_model('devapp.port', models.Port)
- return res
-
-
-def dump_accounts():
- from accounts_app import models
- from abonapp.models import AbonGroup
-
- def get_responsibility_groups(account):
- responsibility_groups = AbonGroup.objects.filter(profiles__in=[account])
- ids = [ag.pk for ag in responsibility_groups]
- return ids
-
- print('accounts_app.baseaccount')
- res = [{
- 'model': 'accounts_app.baseaccount',
- 'pk': up.pk,
- 'fields': {
- 'username': up.username,
- 'fio': up.fio,
- 'birth_day': up.birth_day,
- 'is_active': up.is_active,
- 'is_admin': up.is_admin,
- 'telephone': up.telephone,
- 'password': up.password,
- 'last_login': up.last_login,
- 'is_superuser': up.is_admin
- }
- } for up in models.UserProfile.objects.all()]
-
- print('accounts_app.userprofile')
- res += [{
- 'model': 'accounts_app.userprofile',
- 'pk': up.pk,
- 'fields': {
- 'avatar': up.avatar.pk if up.avatar else None,
- 'email': up.email,
- 'responsibility_groups': get_responsibility_groups(up)
- }
- } for up in models.UserProfile.objects.filter(is_admin=True)]
-
- return res
-
-
-def dump_photos():
- from photo_app.models import Photo
- print('photo_app.photo')
- res = [{
- 'model': 'photo_app.photo',
- 'pk': p.pk,
- 'fields': {
- 'image': "%s" % p.image,
- 'wdth': p.wdth,
- 'heigt': p.heigt
- }
- } for p in Photo.objects.all()]
- return res
-
-
-def dump_chatbot():
- from chatbot import models
- res = get_fixture_from_unchanget_model('chatbot.telegrambot', models.TelegramBot)
- res += get_fixture_from_unchanget_model('chatbot.messagehistory', models.MessageHistory)
- res += get_fixture_from_unchanget_model('chatbot.messagequeue', models.MessageQueue)
- return res
-
-
-def dump_map():
- from mapapp import models
- res = get_fixture_from_unchanget_model('mapapp.dot', models.Dot)
- return res
-
-
-def dump_task_app():
- from taskapp import models
- res = get_fixture_from_unchanget_model('taskapp.changelog', models.ChangeLog)
- res += get_fixture_from_unchanget_model('taskapp.task', models.Task)
- res += get_fixture_from_unchanget_model('taskapp.ExtraComment', models.ExtraComment)
- return res
-
-
-def dump_auth():
- from django.contrib.auth import models
- from django.contrib.contenttypes.models import ContentType
- res = get_fixture_from_unchanget_model('contenttypes.contenttype', ContentType)
- res += get_fixture_from_unchanget_model('auth.group', models.Group)
- res += get_fixture_from_unchanget_model('auth.permission', models.Permission)
- return res
-
-
-def dump_guardian():
- from guardian import models
- print('guardian.groupobjectpermission')
- res = [{
- 'model': 'guardian.groupobjectpermission',
- 'pk': gp.pk,
- 'fields': {
- 'group': gp.group.pk,
- 'permission': gp.permission.pk,
- 'content_type': gp.content_type.pk,
- 'object_pk': str(gp.object_pk),
- 'content_object': gp.content_object.pk
- }
- } for gp in models.GroupObjectPermission.objects.all()]
- print('guardian.userobjectpermission')
- res += [{
- 'model': 'guardian.userobjectpermission',
- 'pk': up.pk,
- 'fields': {
- 'permission': up.permission.pk,
- 'content_type': up.content_type.pk,
- 'object_pk': str(up.object_pk),
- 'user': up.user.pk
- }
- } for up in models.UserObjectPermission.objects.all()]
- return res
-
-
-def make_migration():
- from datetime import datetime, date
-
- def my_date_converter(o):
- if isinstance(o, datetime) or isinstance(o, date):
- return "%s" % o
-
- def appdump(path, func):
- fname = os.path.join(*path)
- path_dir = os.path.join(*path[:-1])
- if not os.path.isdir(path_dir):
- os.mkdir(path_dir)
- with open(fname, 'w') as f:
- dump(func(), f, default=my_date_converter, ensure_ascii=False)
-
- if not os.path.isdir('fixtures'):
- os.mkdir('fixtures')
- appdump(['fixtures', 'group_app', 'groups_fixture.json'], dump_groups)
- appdump(['fixtures', 'tariff_app', 'tariffs_fixture.json'], dump_tariffs)
- appdump(['fixtures', 'photo_app', 'photos_fixture.json'], dump_photos)
- appdump(['fixtures', 'devapp', 'devs_fixture.json'], dump_devs)
- appdump(['fixtures', 'accounts_app', 'accounts_fixture.json'], dump_accounts)
- appdump(['fixtures', 'abonapp', 'abon_fixture.json'], dump_abonapp)
- appdump(['fixtures', 'chatbot', 'chatbot_fixture.json'], dump_chatbot)
- appdump(['fixtures', 'mapapp', 'map_fixture.json'], dump_map)
- appdump(['fixtures', 'taskapp', 'task_fixture.json'], dump_task_app)
- # appdump(['fixtures', 'accounts_app', 'auth_fixture.json'], dump_auth)
- # appdump(['fixtures', 'accounts_app', 'guardian_fixture.json'], dump_guardian)
-
-
-def move_to_fixtures_dirs():
- fixdir = 'fixtures'
- for dr in os.listdir(fixdir):
- fixture_dir = os.path.join(fixdir, dr)
- for fixture_file in os.listdir(fixture_dir):
- from_file = os.path.join(fixture_dir, fixture_file)
- dst_dir = os.path.join(dr, fixdir)
- to_file = os.path.join(dst_dir, fixture_file)
- if not os.path.isdir(dst_dir):
- os.mkdir(dst_dir)
- shutil.copyfile(from_file, to_file)
- print('cp %s -> %s' % (from_file, to_file))
-
-
-def apply_fixtures():
- from django.core.management import execute_from_command_line
- from accounts_app.models import UserProfile
- # from django.contrib.auth import models
-
- UserProfile.objects.filter(username='AnonymousUser').delete()
- # print('clearing auth.group')
- # models.Group.objects.all().delete()
- # print('clearing auth.permission')
- # models.Permission.objects.all().delete()
-
- fixtures_names = [
- 'groups_fixture.json', 'tariffs_fixture.json', 'photos_fixture.json',
- 'devs_fixture.json', 'accounts_fixture.json', 'abon_fixture.json',
- 'chatbot_fixture.json', 'map_fixture.json', 'task_fixture.json'
- ]
- # 'auth_fixture.json', 'guardian_fixture.json'
- print('./manage.py loaddata ' + ', '.join(fixtures_names))
- execute_from_command_line([sys.argv[0], 'loaddata'] + fixtures_names)
-
-
-if __name__ == '__main__':
- if len(sys.argv) < 2:
- print('Usage: ./migrate_to_0.2.py [makedump OR applydump]')
- exit(1)
- choice = sys.argv[1]
- if choice == 'applydump':
- django.setup()
- move_to_fixtures_dirs()
- apply_fixtures()
- shutil.rmtree('fixtures')
- elif choice == 'makedump':
- django.setup()
- make_migration()
- else:
- print('Unexpected choice')
diff --git a/mydefs.py b/mydefs.py
deleted file mode 100644
index d885fa0..0000000
--- a/mydefs.py
+++ /dev/null
@@ -1,187 +0,0 @@
-# -*- coding: utf-8 -*-
-from datetime import timedelta
-from json import dumps
-import socket
-import struct
-from collections import Iterator
-from functools import wraps
-from django.http import HttpResponse, Http404, HttpResponseRedirect
-from django.shortcuts import redirect
-from django.db import models
-from django.conf import settings
-
-DEBUG = getattr(settings, 'DEBUG', False)
-
-
-def ip2int(addr):
- try:
- return struct.unpack("!I", socket.inet_aton(addr))[0]
- except:
- return 0
-
-
-def int2ip(addr):
- try:
- return socket.inet_ntoa(struct.pack("!I", addr))
- except:
- return ''
-
-
-def safe_float(fl):
- try:
- return 0.0 if fl is None or fl == '' else float(fl)
- except ValueError:
- return 0.0
-
-
-def safe_int(i):
- try:
- return 0 if i is None or i == '' else int(i)
- except ValueError:
- return 0
-
-
-def res_success(request, redirect_to='/'):
- if request.is_ajax():
- return HttpResponse(dumps({'errnum': 0}))
- else:
- return redirect(redirect_to)
-
-
-def res_error(request, text):
- if request.is_ajax():
- return HttpResponse(dumps({'errnum': 1, 'errtext': text}))
- else:
- raise Http404(text)
-
-
-class MyGenericIPAddressField(models.GenericIPAddressField):
- description = "Int32 notation ip address"
-
- def __init__(self, protocol='ipv4', *args, **kwargs):
- super(MyGenericIPAddressField, self).__init__(protocol=protocol, *args, **kwargs)
- self.max_length = 8
-
- def get_prep_value(self, value):
- # strIp to Int
- value = super(MyGenericIPAddressField, self).get_prep_value(value)
- return ip2int(value)
-
- def to_python(self, value):
- return value
-
- def get_internal_type(self):
- return 'PositiveIntegerField'
-
- @staticmethod
- def from_db_value(value, expression, connection, context):
- return int2ip(value) if value != 0 else None
-
- def int_ip(self):
- return ip2int(self)
-
-
-# Предназначен для Django CHOICES чтоб можно было передавать классы вместо просто описания поля,
-# классы передавать для того чтоб по значению кода из базы понять какой класс нужно взять для нужной функциональности.
-# Например по коду в базе вам нужно определять как считать тариф абонента, что реализовано в возвращаемом классе.
-class MyChoicesAdapter(Iterator):
- chs = tuple()
- current_index = 0
- _max_index = 0
-
- # На вход принимает кортеж кортежей, вложенный из 2х элементов: кода и класса, как: TARIFF_CHOICES
- def __init__(self, choices):
- self._max_index = len(choices)
- self.chs = choices
-
- def __next__(self):
- if self.current_index >= self._max_index:
- raise StopIteration
- else:
- e = self.chs
- ci = self.current_index
- res = e[ci][0], e[ci][1].description()
- self.current_index += 1
- return res
-
-
-# Декоратор проверяет аккаунт, чтоб не пускать клиентов в страницы администрации
-def only_admins(fn):
- @wraps(fn)
- def wrapped(request, *args, **kwargs):
- if request.user.is_admin:
- return fn(request, *args, **kwargs)
- else:
- return redirect('client_side:home')
-
- return wrapped
-
-
-# Русифицированный вывод timedelta
-class RuTimedelta(timedelta):
- def __new__(cls, tm):
- if isinstance(tm, timedelta):
- return timedelta.__new__(
- cls,
- days=tm.days,
- seconds=tm.seconds,
- microseconds=tm.microseconds
- )
-
- def __str__(self):
- # hours, remainder = divmod(self.seconds, 3600)
- # minutes, seconds = divmod(remainder, 60)
- # text_date = "%d:%d" % (
- # hours,
- # minutes
- # )
- if self.days > 1:
- ru_days = 'дней'
- if 5 > self.days > 1:
- ru_days = 'дня'
- elif self.days == 1:
- ru_days = 'день'
- # text_date = '%d %s %s' % (self.days, ru_days, text_date)
- text_date = '%d %s' % (self.days, ru_days)
- else:
- text_date = ''
- return text_date
-
-
-def require_ssl(view):
- """
- Decorator that requires an SSL connection. If the current connection is not SSL, we redirect to the SSL version of
- the page.
- from: https://gist.github.com/ckinsey/9709984
- """
-
- @wraps(view)
- def wrapper(request, *args, **kwargs):
- if not DEBUG and not request.is_secure():
- target_url = "https://" + request.META['HTTP_HOST'] + request.path_info
- return HttpResponseRedirect(target_url)
- return view(request, *args, **kwargs)
-
- return wrapper
-
-
-class MultipleException(Exception):
- def __init__(self, err_list):
- if not isinstance(err_list, (list, tuple)):
- raise TypeError
- self.err_list = err_list
-
-
-class LogicError(Exception):
- pass
-
-
-def singleton(class_):
- instances = {}
-
- def getinstance(*args, **kwargs):
- if class_ not in instances:
- instances[class_] = class_(*args, **kwargs)
- return instances[class_]
-
- return getinstance
diff --git a/static/css/custom.css b/static/css/custom.css
index 4e12389..3903f00 100644
--- a/static/css/custom.css
+++ b/static/css/custom.css
@@ -110,7 +110,7 @@ td.btn-group {
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
border-bottom: 1px solid #ddd;
- border-radius: 0px 0px 5px 5px;
+ border-radius: 0 0 5px 5px;
padding: 10px;
}
@@ -209,8 +209,7 @@ a.port-img{
left: 0;
}
- .row-offcanvas-left
- .sidebar-offcanvas {
+ .row-offcanvas-left .sidebar-offcanvas {
left: -50%; /* 6 columns */
}
@@ -299,3 +298,16 @@ pre {
.m-icon_dollar{background-position: 0 -52px;}
.m-icon_service{background-position: -26px -52px;}
.m-icon_mrk{background-position: -52px -52px;}
+
+
+@media (max-width: 991px) and (min-width: 768px){
+ .container {
+ width: 874px;
+ }
+}
+
+
+/* Icon near to device info */
+.font-extra-large{
+ font-size: 75px;
+}