Miroca_Server
This commit is contained in:
0
api/__init__.py
Normal file
0
api/__init__.py
Normal file
3
api/admin.py
Normal file
3
api/admin.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
6
api/apps.py
Normal file
6
api/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ApiConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'api'
|
||||||
5
api/mikrotik/api.py
Normal file
5
api/mikrotik/api.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import ros_api
|
||||||
|
|
||||||
|
router = ros_api.Api('192.168.10.1', user='server', password='Cbvgcjy0V', port='8728')
|
||||||
|
r = router.talk('/interface/wireless/cap/print')
|
||||||
|
print(r[0]['enabled'])
|
||||||
15
api/mikrotik/total.py
Normal file
15
api/mikrotik/total.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import netmiko
|
||||||
|
from netmiko import ConnectHandler
|
||||||
|
|
||||||
|
mikrotik_router_1 = {
|
||||||
|
'device_type': 'mikrotik_routeros',
|
||||||
|
'host': '192.168.10.1',
|
||||||
|
'port': '2202',
|
||||||
|
'username': 'server',
|
||||||
|
'password': 'Cbvgcjy0V'
|
||||||
|
}
|
||||||
|
|
||||||
|
sshCli = ConnectHandler(**mikrotik_router_1)
|
||||||
|
print(sshCli.find_prompt())
|
||||||
|
output = sshCli.send_command("/interface ethernet print")
|
||||||
|
print(output)
|
||||||
3
api/models.py
Normal file
3
api/models.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
15
api/serializers.py
Normal file
15
api/serializers.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
User = get_user_model()
|
||||||
|
from upanel.models import Device,Hostname
|
||||||
|
|
||||||
|
class DeviceSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Device
|
||||||
|
fields = ('id','name', 'device_id','device_ip','local_key','device_version','customuser_id')
|
||||||
|
|
||||||
|
|
||||||
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = ('id','username','email','ipaddress')
|
||||||
3
api/tests.py
Normal file
3
api/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
0
api/tuya/__init__.py
Normal file
0
api/tuya/__init__.py
Normal file
32
api/tuya/connect.py
Normal file
32
api/tuya/connect.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import psycopg2
|
||||||
|
import tinytuya
|
||||||
|
import json
|
||||||
|
from tuya_connector import TuyaOpenAPI
|
||||||
|
|
||||||
|
tuya_file='tuya_con.json'
|
||||||
|
|
||||||
|
def connect_base():
|
||||||
|
conn = psycopg2.connect(host='172.17.0.1',
|
||||||
|
port='54322',
|
||||||
|
user='miroca',
|
||||||
|
password='cbvgcjy0',
|
||||||
|
database='miroca')
|
||||||
|
return conn
|
||||||
|
|
||||||
|
|
||||||
|
def connect_local():
|
||||||
|
device=tinytuya.deviceScan()
|
||||||
|
return device
|
||||||
|
|
||||||
|
def connect_tuya():
|
||||||
|
ACCESS_ID = "pardyqsmdjetwdxjcaxa"
|
||||||
|
ACCESS_KEY = "4f81a40a36f349dc9ad11d53d74cb34b"
|
||||||
|
API_ENDPOINT = "https://openapi.tuyaeu.com"
|
||||||
|
|
||||||
|
try:
|
||||||
|
openapi = TuyaOpenAPI(API_ENDPOINT, ACCESS_ID, ACCESS_KEY)
|
||||||
|
openapi.connect()
|
||||||
|
return openapi
|
||||||
|
except Exception as e:
|
||||||
|
with open(tuya_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump([{'error': str(e)}], f,ensure_ascii=False, indent=4)
|
||||||
85
api/tuya/device.py
Normal file
85
api/tuya/device.py
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
from itertools import chain
|
||||||
|
from psycopg2.extras import execute_values
|
||||||
|
from connect import *
|
||||||
|
import json
|
||||||
|
|
||||||
|
file_psycopd = 'psycopd_con.json'
|
||||||
|
file_local = 'local_device.json'
|
||||||
|
file_tuya = 'tuya_con.json'
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def update_base():
|
||||||
|
conn = connect_base()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
count = 0
|
||||||
|
try:
|
||||||
|
with open(file_tuya, 'r', encoding='utf-8') as f:
|
||||||
|
tuya_devices = json.load(f)
|
||||||
|
if tuya_devices['error']:
|
||||||
|
raise DeviceError(tuya_devices['error'])
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Ошибка update_base: {e}')
|
||||||
|
with open(file_local, 'r', encoding='utf-8') as f:
|
||||||
|
local_devices = json.load(f)
|
||||||
|
for device in tuya_devices:
|
||||||
|
if device['result']['id'] == [v for v in local_devices.values()][count]['gwId']:
|
||||||
|
cursor.execute("UPDATE upanel_device SET local_key = %s, name = %s "
|
||||||
|
"WHERE device_id= %s",
|
||||||
|
(device['result']['local_key'],
|
||||||
|
device['result']['name'],
|
||||||
|
device['result']['id']))
|
||||||
|
conn.commit()
|
||||||
|
count += 1
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
|
||||||
|
def add_base():
|
||||||
|
conn = connect_base()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
try:
|
||||||
|
with open(file_local, 'r', encoding='utf-8') as f:
|
||||||
|
local_devices_dict = json.load(f)
|
||||||
|
local_devices = {i + 1: v for i, v in enumerate(local_devices_dict.values())}
|
||||||
|
cursor.execute("SELECT * FROM upanel_device")
|
||||||
|
devices = list(chain.from_iterable(cursor.fetchall()))
|
||||||
|
execute_values(cursor, "INSERT INTO upanel_device "
|
||||||
|
"(device_ip, device_id,device_version) "
|
||||||
|
"VALUES %s",
|
||||||
|
[(local_devices_dict[local_devices[device]['ip']]['ip'],
|
||||||
|
local_devices_dict[local_devices[device]['ip']]['gwId'],
|
||||||
|
local_devices_dict[local_devices[device]['ip']]['version'],)
|
||||||
|
for device in local_devices if local_devices[device]['ip'] not in devices])
|
||||||
|
conn.commit()
|
||||||
|
cursor.close()
|
||||||
|
except Exception as e:
|
||||||
|
print(f'ошибка add_base: {e}')
|
||||||
|
with open('error_add.json', 'w', encoding='utf-8') as f:
|
||||||
|
json.dump({'Error_add':e}, f)
|
||||||
|
|
||||||
|
def delete_base():
|
||||||
|
conn = connect_base()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
try:
|
||||||
|
with open(file_local, 'r', encoding='utf-8') as f:
|
||||||
|
local_devices_dict = json.load(f)
|
||||||
|
ip_file=sorted([v for k,v in enumerate(local_devices_dict)])
|
||||||
|
cursor.execute('SELECT * FROM upanel_device')
|
||||||
|
cursor.executemany("DELETE FROM upanel_device WHERE device_ip=%s",
|
||||||
|
[tuple(str(item) for item in ip[2].split())
|
||||||
|
for ip in cursor.fetchall()
|
||||||
|
if ip[2] not in ip_file])
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Ошибка delete_base: {e}')
|
||||||
|
with open('error_delete.json', 'w', encoding='utf-8') as f:
|
||||||
|
json.dump({'Error_delete':e}, f)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
add_base()
|
||||||
|
update_base()
|
||||||
|
delete_base()
|
||||||
44
api/tuya/input_file.py
Normal file
44
api/tuya/input_file.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
from connect import *
|
||||||
|
|
||||||
|
psycopd_file = 'psycopd_con.json'
|
||||||
|
local_file = 'local_device.json'
|
||||||
|
tuya_file='tuya_con.json'
|
||||||
|
|
||||||
|
def file_base():
|
||||||
|
try:
|
||||||
|
cursor=connect_base().cursor()
|
||||||
|
cursor.execute('SELECT * FROM upanel_device')
|
||||||
|
except Exception as e:
|
||||||
|
with open(psycopd_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump({'error': str(e)}, f)
|
||||||
|
else:
|
||||||
|
with open(psycopd_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump({v[0]:v[1:] for k,v in enumerate(cursor.fetchall())}, f,
|
||||||
|
ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def file_local():
|
||||||
|
try:
|
||||||
|
with open(local_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(connect_local(), f, ensure_ascii=False, indent=4)
|
||||||
|
except Exception as e:
|
||||||
|
with open(local_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump({'error': str(e)}, f)
|
||||||
|
|
||||||
|
|
||||||
|
def file_tuya():
|
||||||
|
try:
|
||||||
|
with open(local_file, 'r', encoding='utf-8') as f:
|
||||||
|
local_device = json.load(f)
|
||||||
|
with open(tuya_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump([connect_tuya().get(f"/v1.0/iot-03/devices/{local_device[dev]['id']}")
|
||||||
|
for dev in local_device],f,ensure_ascii=False, indent=4)
|
||||||
|
except Exception as e:
|
||||||
|
with open(tuya_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump({'error': str(e)}, f)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
file_base()
|
||||||
|
file_local()
|
||||||
|
file_tuya()
|
||||||
12
api/urls.py
Normal file
12
api/urls.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from django.urls import path,include
|
||||||
|
from rest_framework.routers import DefaultRouter
|
||||||
|
from api import views
|
||||||
|
|
||||||
|
router = DefaultRouter()
|
||||||
|
router.register(r'devices', views.DeviceViewSet)
|
||||||
|
router.register(r'user', views.UserViewSet)
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', include((router.urls, 'app_name'), namespace='api/device')),
|
||||||
|
path('', include((router.urls, 'app_name'), namespace='api/user')),
|
||||||
|
]
|
||||||
24
api/views.py
Normal file
24
api/views.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
User = get_user_model()
|
||||||
|
from rest_framework import viewsets
|
||||||
|
from api.serializers import DeviceSerializer,UserSerializer
|
||||||
|
from upanel.models import *
|
||||||
|
|
||||||
|
from rest_framework.authentication import BasicAuthentication
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceViewSet(viewsets.ModelViewSet):
|
||||||
|
authentication_classes = (BasicAuthentication,)
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
queryset = Device.objects.values().order_by('id')
|
||||||
|
serializer_class = DeviceSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class UserViewSet(viewsets.ModelViewSet):
|
||||||
|
authentication_classes = (BasicAuthentication,)
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
queryset = User.objects.values().order_by('id')
|
||||||
|
serializer_class = UserSerializer
|
||||||
0
auth_miroca/__init__.py
Normal file
0
auth_miroca/__init__.py
Normal file
26
auth_miroca/admin.py
Normal file
26
auth_miroca/admin.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from django.contrib.auth.admin import UserAdmin
|
||||||
|
from .forms import CustomUserCreationForm, CustomUserChangeForm
|
||||||
|
from .models import CustomUser
|
||||||
|
|
||||||
|
class CustomUserAdmin(UserAdmin):
|
||||||
|
add_form = CustomUserCreationForm
|
||||||
|
form = CustomUserChangeForm
|
||||||
|
model = CustomUser
|
||||||
|
list_display = ('email', 'is_superuser','is_staff', 'is_active',)
|
||||||
|
list_filter = ('email','is_superuser','is_staff', 'is_active',)
|
||||||
|
fieldsets = (
|
||||||
|
(None, {'fields': ('email', 'password')}),
|
||||||
|
('Разрешения', {'fields': ('is_superuser','is_staff','is_active','groups',)}),
|
||||||
|
('Пользователь',{'fields':('username','last_name','first_name','phone','org','address')}),
|
||||||
|
('Регистрация и вход', {'fields': ('date_joined','last_login')}),
|
||||||
|
)
|
||||||
|
add_fieldsets = (
|
||||||
|
(None, {
|
||||||
|
'classes': ('wide',),
|
||||||
|
'fields': ('email','is_superuser', 'password1', 'password2', 'is_staff', 'is_active')}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
search_fields = ('email',)
|
||||||
|
ordering = ('email',)
|
||||||
|
admin.site.register(CustomUser, CustomUserAdmin)
|
||||||
6
auth_miroca/apps.py
Normal file
6
auth_miroca/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class AuthMirocaConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'auth_miroca'
|
||||||
10
auth_miroca/forms.py
Normal file
10
auth_miroca/forms.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
|
||||||
|
from .models import CustomUser
|
||||||
|
class CustomUserCreationForm(UserCreationForm):
|
||||||
|
class Meta(UserCreationForm):
|
||||||
|
model = CustomUser
|
||||||
|
fields = ('email',)
|
||||||
|
class CustomUserChangeForm(UserChangeForm):
|
||||||
|
class Meta:
|
||||||
|
model = CustomUser
|
||||||
|
fields = ('email',)
|
||||||
9
auth_miroca/logout.py
Normal file
9
auth_miroca/logout.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from django.shortcuts import render, redirect
|
||||||
|
|
||||||
|
def logout_view(func):
|
||||||
|
def wrapper(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
request.session.clear()
|
||||||
|
return redirect ('login')
|
||||||
|
return func(request)
|
||||||
|
return wrapper
|
||||||
34
auth_miroca/managers.py
Normal file
34
auth_miroca/managers.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from django.contrib.auth.base_user import BaseUserManager
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class CustomUserManager(BaseUserManager):
|
||||||
|
"""
|
||||||
|
Custom user model manager where email is the unique identifiers
|
||||||
|
for authentication instead of usernames.
|
||||||
|
"""
|
||||||
|
def create_user(self, email, password, **extra_fields):
|
||||||
|
"""
|
||||||
|
Create and save a user with the given email and password.
|
||||||
|
"""
|
||||||
|
if not email:
|
||||||
|
raise ValueError(_("The Email must be set"))
|
||||||
|
email = self.normalize_email(email)
|
||||||
|
user = self.model(email=email, **extra_fields)
|
||||||
|
user.set_password(password)
|
||||||
|
user.save()
|
||||||
|
return user
|
||||||
|
|
||||||
|
def create_superuser(self, email, password, **extra_fields):
|
||||||
|
"""
|
||||||
|
Create and save a SuperUser with the given email and password.
|
||||||
|
"""
|
||||||
|
extra_fields.setdefault("is_staff", True)
|
||||||
|
extra_fields.setdefault("is_superuser", True)
|
||||||
|
extra_fields.setdefault("is_active", True)
|
||||||
|
|
||||||
|
if extra_fields.get("is_staff") is not True:
|
||||||
|
raise ValueError(_("Superuser must have is_staff=True."))
|
||||||
|
if extra_fields.get("is_superuser") is not True:
|
||||||
|
raise ValueError(_("Superuser must have is_superuser=True."))
|
||||||
|
return self.create_user(email, password, **extra_fields)
|
||||||
37
auth_miroca/migrations/0001_initial.py
Normal file
37
auth_miroca/migrations/0001_initial.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-29 06:19
|
||||||
|
|
||||||
|
import django.utils.timezone
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth', '0012_alter_user_first_name_max_length'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CustomUser',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||||
|
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||||
|
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||||
|
('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')),
|
||||||
|
('is_staff', models.BooleanField(default=False, verbose_name='Персонал')),
|
||||||
|
('is_active', models.BooleanField(default=True, verbose_name='Активный')),
|
||||||
|
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||||
|
('username', models.CharField(max_length=255, null=True, verbose_name='username')),
|
||||||
|
('image', models.ImageField(blank=True, null=True, upload_to='user/%Y/%m/%d', verbose_name='Изображение')),
|
||||||
|
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
|
||||||
|
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': ('user',),
|
||||||
|
'verbose_name_plural': 'Пользователь',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
18
auth_miroca/migrations/0002_customuser_ipaddress.py
Normal file
18
auth_miroca/migrations/0002_customuser_ipaddress.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-29 12:46
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth_miroca', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='customuser',
|
||||||
|
name='ipaddress',
|
||||||
|
field=models.GenericIPAddressField(null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-29 12:53
|
||||||
|
|
||||||
|
import phone_field.models
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth_miroca', '0002_customuser_ipaddress'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='customuser',
|
||||||
|
name='last_name',
|
||||||
|
field=models.CharField(max_length=255, null=True, verbose_name='Фамилия'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='customuser',
|
||||||
|
name='phone',
|
||||||
|
field=phone_field.models.PhoneField(blank=True, help_text='Контактный номер', max_length=31, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-29 13:00
|
||||||
|
|
||||||
|
import address.models
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('address', '0003_auto_20200830_1851'),
|
||||||
|
('auth_miroca', '0003_customuser_last_name_customuser_phone'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='customuser',
|
||||||
|
name='address',
|
||||||
|
field=address.models.AddressField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='address.address', verbose_name='Адрес'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='customuser',
|
||||||
|
name='first_name',
|
||||||
|
field=models.CharField(max_length=255, null=True, verbose_name='Имя'),
|
||||||
|
),
|
||||||
|
]
|
||||||
21
auth_miroca/migrations/0005_alter_customuser_address.py
Normal file
21
auth_miroca/migrations/0005_alter_customuser_address.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-29 13:02
|
||||||
|
|
||||||
|
import address.models
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('address', '0003_auto_20200830_1851'),
|
||||||
|
('auth_miroca', '0004_customuser_address_customuser_first_name'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='customuser',
|
||||||
|
name='address',
|
||||||
|
field=address.models.AddressField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='address.address', verbose_name='Адрес'),
|
||||||
|
),
|
||||||
|
]
|
||||||
17
auth_miroca/migrations/0006_remove_customuser_address.py
Normal file
17
auth_miroca/migrations/0006_remove_customuser_address.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-29 13:05
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth_miroca', '0005_alter_customuser_address'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='customuser',
|
||||||
|
name='address',
|
||||||
|
),
|
||||||
|
]
|
||||||
18
auth_miroca/migrations/0007_customuser_ipaddress_mikrotik.py
Normal file
18
auth_miroca/migrations/0007_customuser_ipaddress_mikrotik.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-29 16:51
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth_miroca', '0006_remove_customuser_address'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='customuser',
|
||||||
|
name='ipaddress_mikrotik',
|
||||||
|
field=models.GenericIPAddressField(null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-29 17:28
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth_miroca', '0007_customuser_ipaddress_mikrotik'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='customuser',
|
||||||
|
name='ipaddress_mikrotik',
|
||||||
|
),
|
||||||
|
]
|
||||||
0
auth_miroca/migrations/__init__.py
Normal file
0
auth_miroca/migrations/__init__.py
Normal file
33
auth_miroca/models.py
Normal file
33
auth_miroca/models.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
|
||||||
|
from django.db import models
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from phone_field import PhoneField
|
||||||
|
from address.models import AddressField
|
||||||
|
|
||||||
|
from .managers import CustomUserManager
|
||||||
|
|
||||||
|
|
||||||
|
class CustomUser(AbstractBaseUser, PermissionsMixin):
|
||||||
|
email = models.EmailField(_("email address"), unique=True)
|
||||||
|
is_staff = models.BooleanField(default=False, verbose_name='Персонал')
|
||||||
|
is_active = models.BooleanField(default=True, verbose_name='Активный')
|
||||||
|
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
|
||||||
|
username = models.CharField(max_length=255, null=True, verbose_name='username')
|
||||||
|
image = models.ImageField(upload_to='user/%Y/%m/%d', blank=True, null=True, verbose_name='Изображение')
|
||||||
|
ipaddress=models.GenericIPAddressField(null=True)
|
||||||
|
last_name=models.CharField(max_length=255, null=True,verbose_name='Фамилия')
|
||||||
|
first_name=models.CharField(max_length=255,null=True,verbose_name='Имя')
|
||||||
|
phone = PhoneField(blank=True,null=True, help_text='Контактный номер')
|
||||||
|
|
||||||
|
USERNAME_FIELD = 'email'
|
||||||
|
REQUIRED_FIELDS = []
|
||||||
|
|
||||||
|
objects = CustomUserManager()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.email
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'user',
|
||||||
|
verbose_name_plural = 'Пользователь'
|
||||||
3
auth_miroca/tests.py
Normal file
3
auth_miroca/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
3
auth_miroca/views.py
Normal file
3
auth_miroca/views.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
0
home/__init__.py
Normal file
0
home/__init__.py
Normal file
3
home/admin.py
Normal file
3
home/admin.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
6
home/apps.py
Normal file
6
home/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class HomeConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'home'
|
||||||
3
home/models.py
Normal file
3
home/models.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
3
home/tests.py
Normal file
3
home/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
3
home/views.py
Normal file
3
home/views.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
0
kiosk/__init__.py
Normal file
0
kiosk/__init__.py
Normal file
3
kiosk/admin.py
Normal file
3
kiosk/admin.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
3
kiosk/models.py
Normal file
3
kiosk/models.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
69
kiosk/templates/kiosk/base/base.html
Normal file
69
kiosk/templates/kiosk/base/base.html
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
{% load static %}
|
||||||
|
<html lang="ru"
|
||||||
|
class="light-style layout-menu-fixed layout-compact"
|
||||||
|
dir="ltr"
|
||||||
|
data-theme="theme-default"
|
||||||
|
data-assets-path="{% static 'kiosk' %}"
|
||||||
|
data-template="vertical-menu-template-free">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"/>
|
||||||
|
|
||||||
|
<title>Панель управления Умный дом Мирока</title>
|
||||||
|
|
||||||
|
<meta name="description" content=""/>
|
||||||
|
|
||||||
|
<!-- Favicon -->
|
||||||
|
<link rel="icon" type="image/x-icon" href="{% static 'file/kiosk/img/favicon.ico' %}"/>
|
||||||
|
|
||||||
|
<!-- Fonts -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com"/>
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap"
|
||||||
|
rel="stylesheet"/>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="{% static 'file/assets/vendor/fonts/boxicons.css' %}"/>
|
||||||
|
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link rel="stylesheet" href="{% static 'file/kiosk/assets/vendor/css/core.css' %}"
|
||||||
|
class="template-customizer-core-css">
|
||||||
|
<link rel="stylesheet" href="{% static 'file/kiosk/assets/vendor/css/theme-default.css' %}"
|
||||||
|
class="template-customizer-theme-css">
|
||||||
|
<link rel="stylesheet" href="{% static 'file/kiosk/assets/css/demo.css' %}">
|
||||||
|
|
||||||
|
<!-- Vendors CSS -->
|
||||||
|
<link rel="stylesheet" href="{% static 'file/kiosk/assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.css' %}"/>
|
||||||
|
<link rel="stylesheet" href="{% static 'file/kiosk/assets/vendor/libs/apex-charts/apex-charts.css' %}"/>
|
||||||
|
|
||||||
|
<!-- Button CSS kiosk -->
|
||||||
|
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css'>
|
||||||
|
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css'>
|
||||||
|
<link rel="stylesheet" href="{% static 'file/kiosk/assets/css/style_button.css' %}">
|
||||||
|
|
||||||
|
<!--Server CSS-->
|
||||||
|
<link rel="stylesheet" href="{% static 'file/kiosk/css/style.css' %}">
|
||||||
|
|
||||||
|
|
||||||
|
<!--Server JS-->
|
||||||
|
<script src="{% static 'file/kiosk/js/jquery-3.5.1.min.js' %}"></script>
|
||||||
|
<script src="{% static 'file/upanel/js/update_server.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'file/kiosk/js/clock.js' %}"></script>
|
||||||
|
|
||||||
|
<!--Button js kiosk -->
|
||||||
|
<script type="text/javascript" src="{% static 'file/kiosk/js/button.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- Helpers -->
|
||||||
|
<script src="{% static 'file/kiosk/assets/vendor/js/helpers.js' %}"></script>
|
||||||
|
<!--! Template customizer & Theme config files MUST be included after core stylesheets and helpers.js in the <head> section -->
|
||||||
|
<!--? Config: Mandatory theme config file contain global vars & default theme options, Set your preferred theme option in this file. -->
|
||||||
|
<script src="{% static 'file/kiosk/assets/js/config.js' %}"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
</html>
|
||||||
49
kiosk/templates/kiosk/content/index.html
Normal file
49
kiosk/templates/kiosk/content/index.html
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{% extends 'kiosk/base/base.html' %}
|
||||||
|
{% load static %}
|
||||||
|
{% block content %}
|
||||||
|
<body>
|
||||||
|
<!-- Layout wrapper -->
|
||||||
|
<div class="layout-wrapper layout-content-navbar">
|
||||||
|
<div class="layout-container">
|
||||||
|
<!-- Layout container -->
|
||||||
|
<div class="layout-page">
|
||||||
|
<!-- Content wrapper -->
|
||||||
|
{% include 'kiosk/include/content_wrapper.html' %}
|
||||||
|
<!-- Content wrapper -->
|
||||||
|
</div>
|
||||||
|
<!-- / Layout page -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Overlay -->
|
||||||
|
<div class="layout-overlay layout-menu-toggle"></div>
|
||||||
|
</div>
|
||||||
|
<!-- / Layout wrapper -->
|
||||||
|
|
||||||
|
<script src="{% static 'file/assets/vendor/libs/jquery/jquery.js' %}"></script>
|
||||||
|
<script src="{% static 'file/assets/vendor/libs/popper/popper.js' %}"></script>
|
||||||
|
<script src="{% static 'file/assets/vendor/js/bootstrap.js' %}"></script>
|
||||||
|
<script src="{% static 'file/assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.js' %}"></script>
|
||||||
|
<script src="{% static 'file/assets/vendor/js/menu.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- endbuild -->
|
||||||
|
|
||||||
|
<!-- Vendors JS -->
|
||||||
|
<script src="{% static 'file/assets/vendor/libs/apex-charts/apexcharts.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- Main JS -->
|
||||||
|
<script src="{% static 'file/assets/js/main.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- Page JS -->
|
||||||
|
<script src="{% static 'file/assets/js/dashboards-analytics.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- Place this tag in your head or just before your close body tag. -->
|
||||||
|
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
setTimeout(function () {
|
||||||
|
window.location.reload();
|
||||||
|
}, 1800000)
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
{% endblock content %}
|
||||||
|
</html>
|
||||||
39
kiosk/templates/kiosk/content/smarthome.html
Normal file
39
kiosk/templates/kiosk/content/smarthome.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{% extends 'kiosk/base/base.html' %}
|
||||||
|
{% load static %}
|
||||||
|
{#Блоки температуры и влажности#}
|
||||||
|
{% block styleinclude %}
|
||||||
|
<link rel="stylesheet" href="{% static 'file/upanel/css/smart_style.css' %}">
|
||||||
|
{% endblock styleinclude %}
|
||||||
|
{#График#}
|
||||||
|
{% block js %}
|
||||||
|
<script src="{% static 'file/upanel/js/smart-size-reload.js' %}"></script>
|
||||||
|
<script src="{% static 'file/upanel/js/vue.min.js' %}"></script>
|
||||||
|
<script src="{% static 'file/upanel/js/highcharts.js' %}"></script>
|
||||||
|
<script src="{% static 'file/upanel/js/vue-highcharts.min.js' %}"></script>
|
||||||
|
{% endblock js %}
|
||||||
|
{% block content %}
|
||||||
|
<body onload="clockTimer();">
|
||||||
|
<div class="app-content">
|
||||||
|
<div class="projects-section">
|
||||||
|
<div class="projects-section-header">
|
||||||
|
{% include 'upanel/upanel/base/label.html' %}
|
||||||
|
<p class="time" id="dayOfWeek"></p>
|
||||||
|
{% include 'upanel/upanel/base/user.html' %}
|
||||||
|
<div class="projects-section-line">
|
||||||
|
{% include 'upanel/upanel/base/status.html' %}
|
||||||
|
<time id="clock"></time>
|
||||||
|
</div>
|
||||||
|
<ul class="breadcrumb">
|
||||||
|
<li><a href="{% url 'upanel' %}">Главная</a></li>
|
||||||
|
<li><a href="{% url 'smarthome' %}">Умный дом</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="breadcrumbs">
|
||||||
|
{% include 'upanel/upanel/base/temperature.html' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="{% static 'file/upanel/js/script.js' %}"></script>
|
||||||
|
</body>
|
||||||
|
{% endblock content %}
|
||||||
31
kiosk/templates/kiosk/include/content_wrapper.html
Normal file
31
kiosk/templates/kiosk/include/content_wrapper.html
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<!-- Content -->
|
||||||
|
|
||||||
|
<div class="container-xxl flex-grow-1 container-p-y">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<!--Sidebar-->
|
||||||
|
{% include 'kiosk/include/sidebar.html' %}
|
||||||
|
<!--Sidebar-->
|
||||||
|
|
||||||
|
<div class="col-lg-8 mb-6 order-0">
|
||||||
|
<!--Показания теплицы-->
|
||||||
|
{% include 'kiosk/include/greenhouse.html' %}
|
||||||
|
<!--End Показания теплицы-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<!-- Order Statistics -->
|
||||||
|
{% include 'kiosk/include/transaction.html' %}
|
||||||
|
<!--/ Order Statistics -->
|
||||||
|
|
||||||
|
<!-- Transactions -->
|
||||||
|
{% include 'kiosk/include/transaction.html' %}
|
||||||
|
<!--/ Transactions -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- / Content -->
|
||||||
|
|
||||||
|
<div class="content-backdrop fade"></div>
|
||||||
|
</div>
|
||||||
49
kiosk/templates/kiosk/include/greenhouse.html
Normal file
49
kiosk/templates/kiosk/include/greenhouse.html
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="row row-bordered g-0">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h5 class="card-header m-0 me-2 pb-3">Показания датчиков</h5>
|
||||||
|
<div id="totalRevenueChart" class="px-2"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="dropdown">
|
||||||
|
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="growthReportId">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="growthChart"></div>
|
||||||
|
<div class="text-center fw-medium pt-3 mb-2">Показания датчиков теплицы</div>
|
||||||
|
|
||||||
|
<div class="d-flex px-xxl-4 px-lg-2 p-4 gap-xxl-3 gap-lg-1 gap-3 justify-content-between">
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="me-2">
|
||||||
|
<span class="badge bg-label-primary p-2"><i
|
||||||
|
class="bx bx-health text-primary"></i></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<small>Температура</small>
|
||||||
|
{% if temp != 0 %}
|
||||||
|
<h6 class="mb-0" id="temp_green">+{{ temp }}°C</h6>
|
||||||
|
{% elif temp == 0 %}
|
||||||
|
<h6 class="mb-0" id="temp_green">+{{ temp }}°C</h6>
|
||||||
|
{% else %}
|
||||||
|
<h6 class="mb-0" id="temp_green">-{{ temp }}°C</h6>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="me-2">
|
||||||
|
<span class="badge bg-label-info p-2"><i
|
||||||
|
class="bx bx-water text-info"></i></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<small>Влаж. почвы</small>
|
||||||
|
<h6 id='damp' class="mb-0">{{ damp }}%</h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
100
kiosk/templates/kiosk/include/orderstatic.html
Normal file
100
kiosk/templates/kiosk/include/orderstatic.html
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="col-md-6 col-lg-4 col-xl-4 order-0 mb-4">
|
||||||
|
<div class="card h-100">
|
||||||
|
<div class="card-header d-flex align-items-center justify-content-between pb-0">
|
||||||
|
<div class="card-title mb-0">
|
||||||
|
<h5 class="m-0 me-2">Order Statistics</h5>
|
||||||
|
<small class="text-muted">42.82k Total Sales</small>
|
||||||
|
</div>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button
|
||||||
|
class="btn p-0"
|
||||||
|
type="button"
|
||||||
|
id="orederStatistics"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded="false">
|
||||||
|
<i class="bx bx-dots-vertical-rounded"></i>
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="orederStatistics">
|
||||||
|
<a class="dropdown-item" href="javascript:void(0);">Select All</a>
|
||||||
|
<a class="dropdown-item" href="javascript:void(0);">Refresh</a>
|
||||||
|
<a class="dropdown-item" href="javascript:void(0);">Share</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<div class="d-flex flex-column align-items-center gap-1">
|
||||||
|
<h2 class="mb-2">8,258</h2>
|
||||||
|
<span>Total Orders</span>
|
||||||
|
</div>
|
||||||
|
<div id="orderStatisticsChart"></div>
|
||||||
|
</div>
|
||||||
|
<ul class="p-0 m-0">
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<span class="avatar-initial rounded bg-label-primary"
|
||||||
|
><i class="bx bx-mobile-alt"></i
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<h6 class="mb-0">Electronic</h6>
|
||||||
|
<small class="text-muted">Mobile, Earbuds, TV</small>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress">
|
||||||
|
<small class="fw-medium">82.5k</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<span class="avatar-initial rounded bg-label-success"><i
|
||||||
|
class="bx bx-closet"></i></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<h6 class="mb-0">Fashion</h6>
|
||||||
|
<small class="text-muted">T-shirt, Jeans, Shoes</small>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress">
|
||||||
|
<small class="fw-medium">23.8k</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<span class="avatar-initial rounded bg-label-info"><i
|
||||||
|
class="bx bx-home-alt"></i></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<h6 class="mb-0">Decor</h6>
|
||||||
|
<small class="text-muted">Fine Art, Dining</small>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress">
|
||||||
|
<small class="fw-medium">849k</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<span class="avatar-initial rounded bg-label-secondary"
|
||||||
|
><i class="bx bx-football"></i
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<h6 class="mb-0">Sports</h6>
|
||||||
|
<small class="text-muted">Football, Cricket Kit</small>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress">
|
||||||
|
<small class="fw-medium">99</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
151
kiosk/templates/kiosk/include/sidebar.html
Normal file
151
kiosk/templates/kiosk/include/sidebar.html
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="col-lg-4 col-md-4 order-1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img
|
||||||
|
src="{% static 'file/assets/img/icons/unicons/data-collection.png' %}"
|
||||||
|
alt="chart success"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="fw-medium d-block mb-1">Сервер</span>
|
||||||
|
<h3 id="server"></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img
|
||||||
|
src="{% static 'file/assets/img/icons/unicons/internet.png' %}"
|
||||||
|
alt="temper"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span>Интернет</span>
|
||||||
|
<h3 id="internet"></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<input class="addoncheckbox" type="checkbox" name="" value="">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/humidity.png' %}"
|
||||||
|
alt="wet"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="d-block mb-1">Влажность</span>
|
||||||
|
<h3 class="card-title text-nowrap mb-2">50%</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/temperature.png' %}"
|
||||||
|
alt="Credit Card" class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="fw-medium d-block mb-1">Блок</span>
|
||||||
|
<h3 class="card-title mb-2">$147</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/humidity.png' %}"
|
||||||
|
alt="wet"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="d-block mb-1">Влажность</span>
|
||||||
|
<h3 class="card-title text-nowrap mb-2">125%</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/temperature.png' %}"
|
||||||
|
alt="Credit Card" class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="fw-medium d-block mb-1">Блок</span>
|
||||||
|
<h3 class="card-title mb-2">$147</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/temperature.png' %}"
|
||||||
|
alt="Credit Card" class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="fw-medium d-block mb-1">Блок</span>
|
||||||
|
<h3 class="card-title mb-2">$147</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/temperature.png' %}"
|
||||||
|
alt="Credit Card" class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="fw-medium d-block mb-1">Блок</span>
|
||||||
|
<h3 class="card-title mb-2">$147</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<label class="">
|
||||||
|
<input class="addoncheckbox" type="checkbox" name="" value="">
|
||||||
|
<span class="checkbox-icon card"><i class="fa fa-fw fa-plus"></i></span>
|
||||||
|
<div class="upgrade-site-name">
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<label class="">
|
||||||
|
<input class="addoncheckbox" type="checkbox" name="" value="">
|
||||||
|
<span class="checkbox-icon card"><i class="fa fa-fw fa-plus"></i></span>
|
||||||
|
<div class="upgrade-site-name">
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
76
kiosk/templates/kiosk/include/transaction.html
Normal file
76
kiosk/templates/kiosk/include/transaction.html
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="col-md-6 col-lg-4 order-2 mb-4">
|
||||||
|
<div class="card h-100">
|
||||||
|
<div class="card-body">
|
||||||
|
<ul class="p-0 m-0">
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/paypal.png' %}"
|
||||||
|
alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Paypal</small>
|
||||||
|
<h6 class="mb-0">Send money</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">+82.6</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/wallet.png' %}" alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Wallet</small>
|
||||||
|
<h6 class="mb-0">Mac'D</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">+270.69</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/chart.png' %}"
|
||||||
|
alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Transfer</small>
|
||||||
|
<h6 class="mb-0">Refund</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">+637.91</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/cc-success.png' %}"
|
||||||
|
alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Credit Card</small>
|
||||||
|
<h6 class="mb-0">Ordered Food</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">-838.71</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
3
kiosk/tests.py
Normal file
3
kiosk/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
6
kiosk/urls.py
Normal file
6
kiosk/urls.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.urls import path,include
|
||||||
|
from kiosk import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', views.kiosk, name='kiosk'),
|
||||||
|
]
|
||||||
21
kiosk/views.py
Normal file
21
kiosk/views.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
from upanel.models import *
|
||||||
|
import tinytuya
|
||||||
|
|
||||||
|
def turn_on_off(click):
|
||||||
|
devices = Device.objects.values('device_id', 'device_ip', 'local_key', 'device_version').order_by('id')
|
||||||
|
d = tinytuya.OutletDevice(
|
||||||
|
dev_id=str(devices[0]['device_id']),
|
||||||
|
address=str(devices[0]['device_ip']),
|
||||||
|
local_key=str(devices[0]['local_key']),
|
||||||
|
version=devices[0]['device_version'])
|
||||||
|
match click:
|
||||||
|
case 'on':
|
||||||
|
return d.turn_on()
|
||||||
|
case 'off':
|
||||||
|
return d.turn_off()
|
||||||
|
|
||||||
|
def kiosk(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
turn_on_off(request.POST['click'])
|
||||||
|
return render(request, 'kiosk/content/index.html',)
|
||||||
22
manage.py
Normal file
22
manage.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'miroca.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
0
miroca/__init__.py
Normal file
0
miroca/__init__.py
Normal file
16
miroca/asgi.py
Normal file
16
miroca/asgi.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
ASGI config for miroca project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'miroca.settings')
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
||||||
161
miroca/settings.py
Normal file
161
miroca/settings.py
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
"""
|
||||||
|
Django settings for miroca project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 3.2.25.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/3.2/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/3.2/ref/settings/
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-cy5#sc7)e)f$$fl@w0%p7i$xie-1qc3uxi4xri_q$8e2@s!kdi'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ['miroca.ru']
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'auth_miroca.apps.AuthMirocaConfig',
|
||||||
|
'upanel.apps.UpanelConfig',
|
||||||
|
'home.apps.HomeConfig',
|
||||||
|
'address.apps.AddressConfig',
|
||||||
|
'rest_framework',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
REST_FRAMEWORK = {
|
||||||
|
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||||
|
'rest_framework.authentication.BasicAuthentication',
|
||||||
|
'rest_framework.authentication.SessionAuthentication',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'miroca.urls'
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS = (
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
)
|
||||||
|
AUTH_USER_MODEL = 'auth_miroca.CustomUser'
|
||||||
|
LOGIN_REDIRECT_URL = "upanel"
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'miroca.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'miroca.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
|
||||||
|
|
||||||
|
# DATABASES = {
|
||||||
|
# 'default': {
|
||||||
|
# 'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
# 'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/3.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_L10N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/3.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = '/static/'
|
||||||
|
STATIC_ROOT = '/home/c76533/miroca.ru/www/static'
|
||||||
|
|
||||||
|
MEDIA_URL = '/media/'
|
||||||
|
MEDIA_ROOT = '/home/c76533/miroca.ru/www/media'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
# database settings
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||||
|
'HOST': 'postgres.c76533.h2',
|
||||||
|
'PORT': '5432',
|
||||||
|
'NAME': 'c76533_miroca_ru',
|
||||||
|
'USER': 'c76533_miroca_ru',
|
||||||
|
'PASSWORD': 'DaFsaQicrogot12',
|
||||||
|
},
|
||||||
|
}
|
||||||
23
miroca/urls.py
Normal file
23
miroca/urls.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
"""miroca URL Configuration
|
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||||
|
https://docs.djangoproject.com/en/3.2/topics/http/urls/
|
||||||
|
Examples:
|
||||||
|
Function views
|
||||||
|
1. Add an import: from my_app import views
|
||||||
|
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||||
|
Class-based views
|
||||||
|
1. Add an import: from other_app.views import Home
|
||||||
|
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||||
|
Including another URLconf
|
||||||
|
1. Import the include() function: from django.urls import include, path
|
||||||
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
|
"""
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.urls import path, include
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
# path('admin/', admin.site.urls),
|
||||||
|
path('', include('upanel.urls')),
|
||||||
|
path('api/', include('api.urls')),
|
||||||
|
]
|
||||||
16
miroca/wsgi.py
Normal file
16
miroca/wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
WSGI config for miroca project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'miroca.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
||||||
26
status/status.sh
Normal file
26
status/status.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Объявляем переменные
|
||||||
|
status="$(cat /home/orangepi/miroca.ru/status/status.log)"
|
||||||
|
# указывает IP хоста, количество пингов - 2 раза, и смотрим количество ошибок соединения
|
||||||
|
result=$(ping -c 2 91.201.52.229 2<&1| grep -icE 'unknown|expired|unreachable|time out|100% packet loss')
|
||||||
|
#Если система загружена более 10 мин
|
||||||
|
#if test $(cut -d '.' -f1 /proc/uptime) -gt 600; then
|
||||||
|
# systemctl restart gunicorn
|
||||||
|
#fi
|
||||||
|
if [[ "$result" == 0 ]]; then
|
||||||
|
echo "connect" > "/home/orangepi/miroca.ru/status/status.log"
|
||||||
|
else
|
||||||
|
echo "disconnect" > "/home/orangepi/miroca.ru/status/status.log"
|
||||||
|
fi
|
||||||
|
# Связь пропала
|
||||||
|
if [[ "$result" > 0 && "$status" == connect ]]; then
|
||||||
|
echo -e "$(date "+%d.%m.%Y %H:%M:%S") Связь пропала" >> /home/orangepi/miroca.ru/status/hoststatus.log
|
||||||
|
echo "disconnect" > "/home/orangepi/miroca.ru/status/status.log"
|
||||||
|
systemctl restart gunicorn
|
||||||
|
# Связь появилась
|
||||||
|
elif [[ "$result" == 0 && "$status" == disconnect ]]; then
|
||||||
|
echo -e "$(date "+%d.%m.%Y %H:%M:%S") Связь появилась" >> /home/orangepi/miroca.ru/status/hoststatus.log
|
||||||
|
echo "connect" > "/home/orangepi/miroca.ru/status/status.log"
|
||||||
|
systemctl restart gunicorn
|
||||||
|
# В других случаях ничего не делаем
|
||||||
|
fi
|
||||||
2
tasks/__init__.py
Normal file
2
tasks/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# import celery
|
||||||
|
from celery import app as celery_app
|
||||||
3
tasks/admin.py
Normal file
3
tasks/admin.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
6
tasks/apps.py
Normal file
6
tasks/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class TasksConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'tasks'
|
||||||
3
tasks/models.py
Normal file
3
tasks/models.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
7
tasks/tasks.py
Normal file
7
tasks/tasks.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
app = Celery('tasks', broker='amqp://172.17.0.4:5672')
|
||||||
|
|
||||||
|
@app.task
|
||||||
|
def add(x, y):
|
||||||
|
return x + y
|
||||||
3
tasks/tests.py
Normal file
3
tasks/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
3
tasks/views.py
Normal file
3
tasks/views.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
0
upanel/__init__.py
Normal file
0
upanel/__init__.py
Normal file
0
upanel/admin.py
Normal file
0
upanel/admin.py
Normal file
6
upanel/apps.py
Normal file
6
upanel/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class UpanelConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'upanel'
|
||||||
9
upanel/logout.py
Normal file
9
upanel/logout.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from django.shortcuts import render, redirect
|
||||||
|
|
||||||
|
def logout_view(func):
|
||||||
|
def wrapper(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
request.session.clear()
|
||||||
|
return redirect ('login')
|
||||||
|
return func(request)
|
||||||
|
return wrapper
|
||||||
57
upanel/migrations/0001_initial.py
Normal file
57
upanel/migrations/0001_initial.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-29 06:20
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Device',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('device_id', models.CharField(db_index=True, max_length=200, verbose_name='Id устройства')),
|
||||||
|
('name', models.TextField(max_length=300, null=True, verbose_name='Имя')),
|
||||||
|
('device_ip', models.CharField(db_index=True, max_length=200, null=True, verbose_name='IP адрес')),
|
||||||
|
('local_key', models.TextField(db_index=True, max_length=200, null=True, verbose_name='Ключ устройства')),
|
||||||
|
('device_version', models.FloatField(blank=True, null=True, verbose_name='Версия устройства')),
|
||||||
|
('on_off', models.BooleanField(null=True, verbose_name='Вкл')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Устройство',
|
||||||
|
'verbose_name_plural': 'Устройства',
|
||||||
|
'ordering': ['device_id'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Hostname',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(blank=True, max_length=255, null=True)),
|
||||||
|
('area', models.CharField(blank=True, max_length=255, null=True, verbose_name='Зона температуры')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Зона температуры',
|
||||||
|
'verbose_name_plural': 'Зона температуры',
|
||||||
|
'ordering': ['name'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Month',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(db_index=True, max_length=200, verbose_name='Месяц')),
|
||||||
|
('temp', models.JSONField(blank=True, default=list, null=True, verbose_name='Список температур')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Месяц года',
|
||||||
|
'verbose_name_plural': 'Месяц года',
|
||||||
|
'ordering': ['name'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
21
upanel/migrations/0002_device_customuser.py
Normal file
21
upanel/migrations/0002_device_customuser.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-30 14:32
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('upanel', '0001_initial'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='device',
|
||||||
|
name='customuser',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Пользователь'),
|
||||||
|
),
|
||||||
|
]
|
||||||
21
upanel/migrations/0003_hostname_customuser.py
Normal file
21
upanel/migrations/0003_hostname_customuser.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2024-11-30 15:03
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('upanel', '0002_device_customuser'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='hostname',
|
||||||
|
name='customuser',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Пользователь'),
|
||||||
|
),
|
||||||
|
]
|
||||||
0
upanel/migrations/__init__.py
Normal file
0
upanel/migrations/__init__.py
Normal file
47
upanel/models.py
Normal file
47
upanel/models.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.db.models.deletion import CASCADE
|
||||||
|
from django.db.models.fields.related import ForeignKey
|
||||||
|
|
||||||
|
class Hostname(models.Model):
|
||||||
|
customuser = ForeignKey('auth_miroca.CustomUser', null=True, blank=True, on_delete=CASCADE, related_name='+', verbose_name='Пользователь')
|
||||||
|
name = models.CharField(max_length=255, null=True, blank=True)
|
||||||
|
area = models.CharField(max_length=255, null=True, blank=True, verbose_name='Зона температуры')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ['name']
|
||||||
|
verbose_name = 'Зона температуры'
|
||||||
|
verbose_name_plural = 'Зона температуры'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class Month(models.Model):
|
||||||
|
name = models.CharField(max_length=200, db_index=True,verbose_name='Месяц')
|
||||||
|
temp = models.JSONField(default=list, null=True, blank=True, verbose_name='Список температур')
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ['name']
|
||||||
|
verbose_name = 'Месяц года'
|
||||||
|
verbose_name_plural = 'Месяц года'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class Device(models.Model):
|
||||||
|
customuser = ForeignKey('auth_miroca.CustomUser', null=True, blank=True, on_delete=CASCADE, related_name='+', verbose_name='Пользователь')
|
||||||
|
device_id=models.CharField(max_length=200,db_index=True,verbose_name='Id устройства')
|
||||||
|
name =models.TextField(max_length=300,null=True,verbose_name='Имя')
|
||||||
|
device_ip=models.CharField(max_length=200,db_index=True,null=True,verbose_name='IP адрес')
|
||||||
|
local_key=models.TextField(max_length=200,db_index=True,null=True,verbose_name='Ключ устройства')
|
||||||
|
device_version=models.FloatField(blank=True,null=True,verbose_name='Версия устройства')
|
||||||
|
on_off = models.BooleanField(null=True, verbose_name='Вкл')
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ['device_id']
|
||||||
|
verbose_name = 'Устройство'
|
||||||
|
verbose_name_plural = 'Устройства'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.device_id
|
||||||
64
upanel/templates/upanel/login.html
Normal file
64
upanel/templates/upanel/login.html
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
{% load static %}
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Система Miroca</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="{% static 'file/login/img/miroca.svg' %}">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="{% static 'file/login/css/style.css' %}">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<body class="align">
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
|
||||||
|
<form method="post" class="form login">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="miroca">
|
||||||
|
<img src="{% static 'file/login/img/miroca192.png' %}">
|
||||||
|
</div>
|
||||||
|
<div class="form__field">
|
||||||
|
<label for="login__username">
|
||||||
|
<svg class="icon">
|
||||||
|
<use xlink:href="#icon-user"></use>
|
||||||
|
</svg>
|
||||||
|
<span class="hidden">Имя</span></label>
|
||||||
|
<input autocomplete="username" id="login__username" type="text" name="username" class="form__input"
|
||||||
|
placeholder="Имя" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form__field">
|
||||||
|
<label for="login__password">
|
||||||
|
<svg class="icon">
|
||||||
|
<use xlink:href="#icon-lock"></use>
|
||||||
|
</svg>
|
||||||
|
<span class="hidden">Пароль</span></label>
|
||||||
|
<input id="login__password" type="password" name="password" class="form__input" placeholder="Пароль"
|
||||||
|
required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form__field">
|
||||||
|
<input type="submit" value="Войти">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="icons">
|
||||||
|
<symbol id="icon-arrow-right" viewBox="0 0 1792 1792">
|
||||||
|
<path d="M1600 960q0 54-37 91l-651 651q-39 37-91 37-51 0-90-37l-75-75q-38-38-38-91t38-91l293-293H245q-52 0-84.5-37.5T128 1024V896q0-53 32.5-90.5T245 768h704L656 474q-38-36-38-90t38-90l75-75q38-38 90-38 53 0 91 38l651 651q37 35 37 90z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="icon-lock" viewBox="0 0 1792 1792">
|
||||||
|
<path d="M640 768h512V576q0-106-75-181t-181-75-181 75-75 181v192zm832 96v576q0 40-28 68t-68 28H416q-40 0-68-28t-28-68V864q0-40 28-68t68-28h32V576q0-184 132-316t316-132 316 132 132 316v192h32q40 0 68 28t28 68z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="icon-user" viewBox="0 0 1792 1792">
|
||||||
|
<path d="M1600 1405q0 120-73 189.5t-194 69.5H459q-121 0-194-69.5T192 1405q0-53 3.5-103.5t14-109T236 1084t43-97.5 62-81 85.5-53.5T538 832q9 0 42 21.5t74.5 48 108 48T896 971t133.5-21.5 108-48 74.5-48 42-21.5q61 0 111.5 20t85.5 53.5 62 81 43 97.5 26.5 108.5 14 109 3.5 103.5zm-320-893q0 159-112.5 271.5T896 896 624.5 783.5 512 512t112.5-271.5T896 128t271.5 112.5T1280 512z"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
61
upanel/templates/upanel/upanel/base/base.html
Normal file
61
upanel/templates/upanel/upanel/base/base.html
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
{% load static %}
|
||||||
|
<html lang="ru"
|
||||||
|
class="light-style layout-menu-fixed layout-compact"
|
||||||
|
dir="ltr"
|
||||||
|
data-theme="theme-default"
|
||||||
|
data-assets-path="{% static 'assets' %}"
|
||||||
|
data-template="vertical-menu-template-free">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"/>
|
||||||
|
|
||||||
|
<title>Панель управления Умный дом Мирока</title>
|
||||||
|
|
||||||
|
<meta name="description" content=""/>
|
||||||
|
|
||||||
|
<!-- Favicon -->
|
||||||
|
<link rel="icon" type="image/x-icon" href="{% static 'file/upanel/img/favicon.ico' %}"/>
|
||||||
|
|
||||||
|
<!-- Fonts -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com"/>
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap"
|
||||||
|
rel="stylesheet"/>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="{% static 'file/assets/vendor/fonts/boxicons.css' %}"/>
|
||||||
|
|
||||||
|
<!-- Core CSS -->
|
||||||
|
<link rel="stylesheet" href="{% static 'file/assets/vendor/css/core.css' %}" class="template-customizer-core-css">
|
||||||
|
<link rel="stylesheet" href="{% static 'file/assets/vendor/css/theme-default.css' %}"
|
||||||
|
class="template-customizer-theme-css">
|
||||||
|
<link rel="stylesheet" href="{% static 'file/assets/css/demo.css' %}">
|
||||||
|
|
||||||
|
<!-- Vendors CSS -->
|
||||||
|
<link rel="stylesheet" href="{% static 'file/assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.css' %}"/>
|
||||||
|
<link rel="stylesheet" href="{% static 'file/assets/vendor/libs/apex-charts/apex-charts.css' %}"/>
|
||||||
|
|
||||||
|
<!-- Page CSS -->
|
||||||
|
|
||||||
|
<!--Server CSS-->
|
||||||
|
<link rel="stylesheet" href="{% static 'file/upanel/css/style.css' %}">
|
||||||
|
|
||||||
|
|
||||||
|
<!--Server JS-->
|
||||||
|
<script src="{% static 'file/upanel/js/jquery-3.5.1.min.js' %}"></script>
|
||||||
|
<script src="{% static 'file/upanel/js/update_server.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'file/upanel/js/clock.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- Helpers -->
|
||||||
|
<script src="{% static 'file/assets/vendor/js/helpers.js' %}"></script>
|
||||||
|
<!--! Template customizer & Theme config files MUST be included after core stylesheets and helpers.js in the <head> section -->
|
||||||
|
<!--? Config: Mandatory theme config file contain global vars & default theme options, Set your preferred theme option in this file. -->
|
||||||
|
<script src="{% static 'file/assets/js/config.js' %}"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
</html>
|
||||||
9
upanel/templates/upanel/upanel/base/button.html
Normal file
9
upanel/templates/upanel/upanel/base/button.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<button class="project-btn-more">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
|
||||||
|
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round" class="feather feather-more-vertical">
|
||||||
|
<circle cx="12" cy="12" r="1"/>
|
||||||
|
<circle cx="12" cy="5" r="1"/>
|
||||||
|
<circle cx="12" cy="19" r="1"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
7
upanel/templates/upanel/upanel/base/label.html
Normal file
7
upanel/templates/upanel/upanel/base/label.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="miroca">
|
||||||
|
<a href="/">
|
||||||
|
<img src="{% static 'file/upanel/img/miroca.svg' %}">
|
||||||
|
<h1>iroca</h1>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
21
upanel/templates/upanel/upanel/base/status.html
Normal file
21
upanel/templates/upanel/upanel/base/status.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="main-overview">
|
||||||
|
<div class="overviewCard">
|
||||||
|
<div class="overviewCard-icon overviewCard-icon--document">
|
||||||
|
<img src="{% static 'file/upanel/img/cloud.png' %}">
|
||||||
|
</div>
|
||||||
|
<div class="overviewCard-description">
|
||||||
|
<h3 id="update" class="overviewCard-title text-light"></h3>
|
||||||
|
<p class="overviewCard-subtitle">Облачный сервер</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="overviewCard">
|
||||||
|
<div class="overviewCard-icon overviewCard-icon--calendar">
|
||||||
|
<img src="{% static 'file/upanel/img/server.png' %}">
|
||||||
|
</div>
|
||||||
|
<div class="overviewCard-description">
|
||||||
|
<h3 class="overviewCard-title text-light update">OK</h3>
|
||||||
|
<p class="overviewCard-subtitle">Система контроля</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
29
upanel/templates/upanel/upanel/base/temperature.html
Normal file
29
upanel/templates/upanel/upanel/base/temperature.html
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<div class='container'>
|
||||||
|
<div class='card temp'>
|
||||||
|
<div class='inner'>
|
||||||
|
<div class='icon'></div>
|
||||||
|
<div class='title'>
|
||||||
|
<div class='text'>ТЕМПЕРАТУРА</div>
|
||||||
|
</div>
|
||||||
|
<div class='number'>22</div>
|
||||||
|
<div class='measure'>(°C)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='card energy'>
|
||||||
|
<div class='inner'>
|
||||||
|
<div class='icon'></div>
|
||||||
|
<div class='title'>
|
||||||
|
<div class='text'>ВЛАЖНОСТЬ</div>
|
||||||
|
</div>
|
||||||
|
<div class='number'>45</div>
|
||||||
|
<div class='measure'>г/м<sup>3</sup></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="diagram">
|
||||||
|
<div class="project-smart" style="background-color: #e9ebf0">
|
||||||
|
<div id="app">
|
||||||
|
<highcharts :options="options" ref="highcharts"></highcharts>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
22
upanel/templates/upanel/upanel/base/user.html
Normal file
22
upanel/templates/upanel/upanel/base/user.html
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="view-actions dropdown-profile">
|
||||||
|
<button onclick="myFunction()" class="profile-btn">
|
||||||
|
<img class="image-vignesh dropbtn-profile" src="{% static 'file/upanel/img/1.png' %}"/>
|
||||||
|
<span class="dropbtn-profile">{{ user.username }}</span>
|
||||||
|
</button>
|
||||||
|
<div id="myDropdown" class="dropdown-content">
|
||||||
|
<a class="dropdown-item line" href="#">
|
||||||
|
<i class="mdi mdi-account-outline me-1 mdi-20px"></i>
|
||||||
|
<span class="align-middle">Профиль</span>
|
||||||
|
</a>
|
||||||
|
<a class="dropdown-item line" href="#">
|
||||||
|
<i class="mdi mdi-cog-outline me-1 mdi-20px"></i>
|
||||||
|
<span class="align-middle">Настройки</span>
|
||||||
|
</a>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="submit" class="fadeIn fourth" value="Выход">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
51
upanel/templates/upanel/upanel/content/content_wrapper.html
Normal file
51
upanel/templates/upanel/upanel/content/content_wrapper.html
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<!-- Content -->
|
||||||
|
|
||||||
|
<div class="container-xxl flex-grow-1 container-p-y">
|
||||||
|
<div class="row">
|
||||||
|
<!--Top-->
|
||||||
|
{% include 'upanel/upanel/content/top.html' %}
|
||||||
|
<!--/End Top-->
|
||||||
|
|
||||||
|
<!--Ping server-->
|
||||||
|
{% include 'upanel/upanel/content/ping_server.html' %}
|
||||||
|
<!--End Ping server-->
|
||||||
|
|
||||||
|
<!--Показания теплицы-->
|
||||||
|
{% include 'upanel/upanel/content/greenhouse.html' %}
|
||||||
|
<!--End Показания теплицы-->
|
||||||
|
|
||||||
|
<!--/ Total Revenue -->
|
||||||
|
<div class="col-12 col-md-8 col-lg-4 order-3 order-md-2">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<!--Показания датчиков-->
|
||||||
|
{% include 'upanel/upanel/content/total.html' %}
|
||||||
|
<!--End Показания датчиков-->
|
||||||
|
|
||||||
|
<!--Profile-->
|
||||||
|
{% include 'upanel/upanel/content/profile.html' %}
|
||||||
|
<!--End Profile-->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<!-- Order Statistics -->
|
||||||
|
{% include 'upanel/upanel/content/orderstatic.html' %}
|
||||||
|
<!--/ Order Statistics -->
|
||||||
|
|
||||||
|
<!-- Transactions -->
|
||||||
|
{% include 'upanel/upanel/content/transaction.html' %}
|
||||||
|
<!--/ Transactions -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- / Content -->
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
{% include 'upanel/upanel/content/footer.html' %}
|
||||||
|
<!-- / Footer -->
|
||||||
|
|
||||||
|
<div class="content-backdrop fade"></div>
|
||||||
|
</div>
|
||||||
12
upanel/templates/upanel/upanel/content/footer.html
Normal file
12
upanel/templates/upanel/upanel/content/footer.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<footer class="content-footer footer bg-footer-theme">
|
||||||
|
<div class="container-xxl d-flex flex-wrap justify-content-between py-2 flex-md-row flex-column">
|
||||||
|
<div class="mb-2 mb-md-0">
|
||||||
|
©
|
||||||
|
<script>
|
||||||
|
document.write(new Date().getFullYear());
|
||||||
|
</script>
|
||||||
|
, made with ❤️ by
|
||||||
|
<a href="https://tsyrenschikov.ru" target="_blank" class="footer-link fw-medium">tsyrenschikov</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
52
upanel/templates/upanel/upanel/content/greenhouse.html
Normal file
52
upanel/templates/upanel/upanel/content/greenhouse.html
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<!-- Показания теплицы -->
|
||||||
|
<div class="col-12 col-lg-8 order-2 order-md-3 order-lg-2 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="row row-bordered g-0">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h5 class="card-header m-0 me-2 pb-3">Теплица показания датчиков</h5>
|
||||||
|
<div id="totalRevenueChart" class="px-2"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="text-center">
|
||||||
|
<div class="dropdown">
|
||||||
|
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="growthReportId">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="growthChart"></div>
|
||||||
|
<div class="text-center fw-medium pt-3 mb-2">Показания датчиков теплицы</div>
|
||||||
|
|
||||||
|
<div class="d-flex px-xxl-4 px-lg-2 p-4 gap-xxl-3 gap-lg-1 gap-3 justify-content-between">
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="me-2">
|
||||||
|
<span class="badge bg-label-primary p-2"><i
|
||||||
|
class="bx bx-health text-primary"></i></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<small>Температура</small>
|
||||||
|
{% if temp != 0 %}
|
||||||
|
<h6 class="mb-0" id="temp_green">+{{ temp }}°C</h6>
|
||||||
|
{% elif temp == 0 %}
|
||||||
|
<h6 class="mb-0" id="temp_green">+{{ temp }}°C</h6>
|
||||||
|
{% else %}
|
||||||
|
<h6 class="mb-0" id="temp_green">-{{ temp }}°C</h6>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="me-2">
|
||||||
|
<span class="badge bg-label-info p-2"><i
|
||||||
|
class="bx bx-water text-info"></i></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<small>Влаж. почвы</small>
|
||||||
|
<h6 id='damp' class="mb-0">{{ damp }}%</h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
100
upanel/templates/upanel/upanel/content/orderstatic.html
Normal file
100
upanel/templates/upanel/upanel/content/orderstatic.html
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="col-md-6 col-lg-4 col-xl-4 order-0 mb-4">
|
||||||
|
<div class="card h-100">
|
||||||
|
<div class="card-header d-flex align-items-center justify-content-between pb-0">
|
||||||
|
<div class="card-title mb-0">
|
||||||
|
<h5 class="m-0 me-2">Order Statistics</h5>
|
||||||
|
<small class="text-muted">42.82k Total Sales</small>
|
||||||
|
</div>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button
|
||||||
|
class="btn p-0"
|
||||||
|
type="button"
|
||||||
|
id="orederStatistics"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded="false">
|
||||||
|
<i class="bx bx-dots-vertical-rounded"></i>
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="orederStatistics">
|
||||||
|
<a class="dropdown-item" href="javascript:void(0);">Select All</a>
|
||||||
|
<a class="dropdown-item" href="javascript:void(0);">Refresh</a>
|
||||||
|
<a class="dropdown-item" href="javascript:void(0);">Share</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<div class="d-flex flex-column align-items-center gap-1">
|
||||||
|
<h2 class="mb-2">8,258</h2>
|
||||||
|
<span>Total Orders</span>
|
||||||
|
</div>
|
||||||
|
<div id="orderStatisticsChart"></div>
|
||||||
|
</div>
|
||||||
|
<ul class="p-0 m-0">
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<span class="avatar-initial rounded bg-label-primary"
|
||||||
|
><i class="bx bx-mobile-alt"></i
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<h6 class="mb-0">Electronic</h6>
|
||||||
|
<small class="text-muted">Mobile, Earbuds, TV</small>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress">
|
||||||
|
<small class="fw-medium">82.5k</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<span class="avatar-initial rounded bg-label-success"><i
|
||||||
|
class="bx bx-closet"></i></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<h6 class="mb-0">Fashion</h6>
|
||||||
|
<small class="text-muted">T-shirt, Jeans, Shoes</small>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress">
|
||||||
|
<small class="fw-medium">23.8k</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<span class="avatar-initial rounded bg-label-info"><i
|
||||||
|
class="bx bx-home-alt"></i></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<h6 class="mb-0">Decor</h6>
|
||||||
|
<small class="text-muted">Fine Art, Dining</small>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress">
|
||||||
|
<small class="fw-medium">849k</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<span class="avatar-initial rounded bg-label-secondary"
|
||||||
|
><i class="bx bx-football"></i
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<h6 class="mb-0">Sports</h6>
|
||||||
|
<small class="text-muted">Football, Cricket Kit</small>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress">
|
||||||
|
<small class="fw-medium">99</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
37
upanel/templates/upanel/upanel/content/ping_server.html
Normal file
37
upanel/templates/upanel/upanel/content/ping_server.html
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="col-lg-4 col-md-4 order-1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img
|
||||||
|
src="{% static 'file/assets/img/icons/unicons/data-collection.png' %}"
|
||||||
|
alt="chart success"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="fw-medium d-block mb-1">Сервер</span>
|
||||||
|
<h3 id="server"></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-12 col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img
|
||||||
|
src="{% static 'file/assets/img/icons/unicons/internet.png' %}"
|
||||||
|
alt="temper"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span>Интернет</span>
|
||||||
|
<h3 id="ethernet"></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
21
upanel/templates/upanel/upanel/content/profile.html
Normal file
21
upanel/templates/upanel/upanel/content/profile.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<div class="col-12 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex justify-content-between flex-sm-row flex-column gap-3">
|
||||||
|
<div class="d-flex flex-sm-column flex-row align-items-start justify-content-between">
|
||||||
|
<div class="card-title">
|
||||||
|
<h5 class="text-nowrap mb-2">Profile Report</h5>
|
||||||
|
<span class="badge bg-label-warning rounded-pill">Year 2021</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-sm-auto">
|
||||||
|
<small class="text-success text-nowrap fw-medium"
|
||||||
|
><i class="bx bx-chevron-up"></i> 68.2%</small>
|
||||||
|
<h3 class="mb-0">$84,686k</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="profileReportChart"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
25
upanel/templates/upanel/upanel/content/top.html
Normal file
25
upanel/templates/upanel/upanel/content/top.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="col-lg-8 mb-4 order-0">
|
||||||
|
<div class="card">
|
||||||
|
<div class="d-flex align-items-end row">
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title text-primary">Сервер конфигурации</h5>
|
||||||
|
<p class="mb-4">
|
||||||
|
Вы находитесь на <span class="fw-medium">главной</span> странице конфигуратора
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-5 text-center text-sm-left">
|
||||||
|
<div class="card-body pb-0 px-0 px-md-4">
|
||||||
|
<img
|
||||||
|
src="{% static 'file/assets/img/illustrations/man-with-laptop-light.png' %}"
|
||||||
|
height="140"
|
||||||
|
alt="View Badge User"
|
||||||
|
data-app-dark-img="illustrations/man-with-laptop-dark.png"
|
||||||
|
data-app-light-img="illustrations/man-with-laptop-light.png"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
30
upanel/templates/upanel/upanel/content/total.html
Normal file
30
upanel/templates/upanel/upanel/content/total.html
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/humidity.png' %}"
|
||||||
|
alt="wet"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="d-block mb-1">Влажность</span>
|
||||||
|
<h3 class="card-title text-nowrap mb-2">50%</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-title d-flex align-items-start justify-content-between">
|
||||||
|
<div class="avatar flex-shrink-0">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/temperature.png' %}"
|
||||||
|
alt="Credit Card" class="rounded"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="fw-medium d-block mb-1">Блок</span>
|
||||||
|
<h3 class="card-title mb-2">$147</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
120
upanel/templates/upanel/upanel/content/transaction.html
Normal file
120
upanel/templates/upanel/upanel/content/transaction.html
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="col-md-6 col-lg-4 order-2 mb-4">
|
||||||
|
<div class="card h-100">
|
||||||
|
<div class="card-header d-flex align-items-center justify-content-between">
|
||||||
|
<h5 class="card-title m-0 me-2">Transactions</h5>
|
||||||
|
<div class="dropdown">
|
||||||
|
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="transactionID">
|
||||||
|
<a class="dropdown-item" href="javascript:void(0);">Last 28 Days</a>
|
||||||
|
<a class="dropdown-item" href="javascript:void(0);">Last Month</a>
|
||||||
|
<a class="dropdown-item" href="javascript:void(0);">Last Year</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<ul class="p-0 m-0">
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/paypal.png' %}"
|
||||||
|
alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Paypal</small>
|
||||||
|
<h6 class="mb-0">Send money</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">+82.6</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/wallet.png' %}" alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Wallet</small>
|
||||||
|
<h6 class="mb-0">Mac'D</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">+270.69</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/chart.png' %}"
|
||||||
|
alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Transfer</small>
|
||||||
|
<h6 class="mb-0">Refund</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">+637.91</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/cc-success.png' %}"
|
||||||
|
alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Credit Card</small>
|
||||||
|
<h6 class="mb-0">Ordered Food</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">-838.71</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex mb-4 pb-1">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/wallet.png' %}"
|
||||||
|
alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Wallet</small>
|
||||||
|
<h6 class="mb-0">Starbucks</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">+203.33</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li class="d-flex">
|
||||||
|
<div class="avatar flex-shrink-0 me-3">
|
||||||
|
<img src="{% static 'file/assets/img/icons/unicons/cc-warning.png' %}"
|
||||||
|
alt="User"
|
||||||
|
class="rounded"/>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
|
<div class="me-2">
|
||||||
|
<small class="text-muted d-block mb-1">Mastercard</small>
|
||||||
|
<h6 class="mb-0">Ordered Food</h6>
|
||||||
|
</div>
|
||||||
|
<div class="user-progress d-flex align-items-center gap-1">
|
||||||
|
<h6 class="mb-0">-92.45</h6>
|
||||||
|
<span class="text-muted">USD</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
157
upanel/templates/upanel/upanel/index.html
Normal file
157
upanel/templates/upanel/upanel/index.html
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
{% extends 'upanel/upanel/base/base.html' %}
|
||||||
|
{% load static %}
|
||||||
|
{% block content%}
|
||||||
|
<body>
|
||||||
|
<!-- Layout wrapper -->
|
||||||
|
<div class="layout-wrapper layout-content-navbar">
|
||||||
|
<div class="layout-container">
|
||||||
|
<!--MENU-->
|
||||||
|
{# {% include 'upanel/upanel/menu.html' %}#}
|
||||||
|
|
||||||
|
<!-- Layout container -->
|
||||||
|
<div class="layout-page">
|
||||||
|
<!-- Navbar -->
|
||||||
|
|
||||||
|
<nav
|
||||||
|
class="layout-navbar container-xxl navbar navbar-expand-xl navbar-detached align-items-center bg-navbar-theme"
|
||||||
|
id="layout-navbar">
|
||||||
|
<div class="layout-menu-toggle navbar-nav align-items-xl-center me-3 me-xl-0 d-xl-none">
|
||||||
|
<a class="nav-item nav-link px-0 me-xl-4" href="javascript:void(0)">
|
||||||
|
<i class="bx bx-menu bx-sm"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="navbar-nav-right d-flex align-items-center" id="navbar-collapse">
|
||||||
|
<!-- Search -->
|
||||||
|
<div class="navbar-nav align-items-center">
|
||||||
|
<div class="nav-item d-flex align-items-center">
|
||||||
|
<i class="bx bx-search fs-4 lh-0"></i>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control border-0 shadow-none ps-1 ps-sm-2"
|
||||||
|
placeholder="Search..."
|
||||||
|
aria-label="Search..."/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /Search -->
|
||||||
|
|
||||||
|
<ul class="navbar-nav flex-row align-items-center ms-auto">
|
||||||
|
<!-- Place this tag where you want the button to render. -->
|
||||||
|
<li class="nav-item lh-1 me-3">
|
||||||
|
<a
|
||||||
|
class="github-button"
|
||||||
|
href="https://github.com/themeselection/sneat-html-admin-template-free"
|
||||||
|
data-icon="octicon-star"
|
||||||
|
data-size="large"
|
||||||
|
data-show-count="true"
|
||||||
|
aria-label="Star themeselection/sneat-html-admin-template-free on GitHub"
|
||||||
|
>Star</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- User -->
|
||||||
|
<li class="nav-item navbar-dropdown dropdown-user dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle hide-arrow" href="javascript:void(0);"
|
||||||
|
data-bs-toggle="dropdown">
|
||||||
|
<div class="avatar avatar-online">
|
||||||
|
<img src="../assets/img/avatars/1.png" alt class="w-px-40 h-auto rounded-circle"/>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end">
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="#">
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="flex-shrink-0 me-3">
|
||||||
|
<div class="avatar avatar-online">
|
||||||
|
<img src="../assets/img/avatars/1.png" alt
|
||||||
|
class="w-px-40 h-auto rounded-circle"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<span class="fw-medium d-block">John Doe</span>
|
||||||
|
<small class="text-muted">Admin</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="#">
|
||||||
|
<i class="bx bx-user me-2"></i>
|
||||||
|
<span class="align-middle">My Profile</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="#">
|
||||||
|
<i class="bx bx-cog me-2"></i>
|
||||||
|
<span class="align-middle">Settings</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item" href="#">
|
||||||
|
<span class="d-flex align-items-center align-middle">
|
||||||
|
<i class="flex-shrink-0 bx bx-credit-card me-2"></i>
|
||||||
|
<span class="flex-grow-1 align-middle ms-1">Billing</span>
|
||||||
|
<span class="flex-shrink-0 badge badge-center rounded-pill bg-danger w-px-20 h-px-20">4</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<form method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<a class="dropdown-item">
|
||||||
|
<i class="bx bx-power-off me-2"></i>
|
||||||
|
<input type="submit" class="drop align-middle" value="Выход">
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<!--/ User -->
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- / Navbar -->
|
||||||
|
|
||||||
|
<!-- Content wrapper -->
|
||||||
|
{% include 'upanel/upanel/content/content_wrapper.html' %}
|
||||||
|
<!-- Content wrapper -->
|
||||||
|
</div>
|
||||||
|
<!-- / Layout page -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Overlay -->
|
||||||
|
<div class="layout-overlay layout-menu-toggle"></div>
|
||||||
|
</div>
|
||||||
|
<!-- / Layout wrapper -->
|
||||||
|
|
||||||
|
<!-- Core JS -->
|
||||||
|
<!-- build:js assets/vendor/js/core.js -->
|
||||||
|
|
||||||
|
<script src="{% static 'file/assets/vendor/libs/jquery/jquery.js' %}"></script>
|
||||||
|
<script src="{% static 'file/assets/vendor/libs/popper/popper.js' %}"></script>
|
||||||
|
<script src="{% static 'file/assets/vendor/js/bootstrap.js' %}"></script>
|
||||||
|
<script src="{% static 'file/assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.js' %}"></script>
|
||||||
|
<script src="{% static 'file/assets/vendor/js/menu.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- endbuild -->
|
||||||
|
|
||||||
|
<!-- Vendors JS -->
|
||||||
|
<script src="{% static 'file/assets/vendor/libs/apex-charts/apexcharts.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- Main JS -->
|
||||||
|
<script src="{% static 'file/assets/js/main.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- Page JS -->
|
||||||
|
<script src="{% static 'file/assets/js/dashboards-analytics.js' %}"></script>
|
||||||
|
|
||||||
|
<!-- Place this tag in your head or just before your close body tag. -->
|
||||||
|
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||||
|
</body>
|
||||||
|
{% endblock content %}
|
||||||
|
</html>
|
||||||
65
upanel/templates/upanel/upanel/login.html
Normal file
65
upanel/templates/upanel/upanel/login.html
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
{% load static %}
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Система Miroca</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="{% static 'file/login/img/miroca.svg' %}">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="{% static 'file/login/css/style.css' %}">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<body class="align">
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
|
||||||
|
<form method="post" class="form login">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="miroca">
|
||||||
|
<img src="{% static 'file/login/img/miroca.svg' %}">
|
||||||
|
<h1>iroca</h1>
|
||||||
|
</div>
|
||||||
|
<div class="form__field">
|
||||||
|
<label for="login__username">
|
||||||
|
<svg class="icon">
|
||||||
|
<use xlink:href="#icon-user"></use>
|
||||||
|
</svg>
|
||||||
|
<span class="hidden">Имя</span></label>
|
||||||
|
<input autocomplete="username" id="login__username" type="text" name="username" class="form__input"
|
||||||
|
placeholder="Имя" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form__field">
|
||||||
|
<label for="login__password">
|
||||||
|
<svg class="icon">
|
||||||
|
<use xlink:href="#icon-lock"></use>
|
||||||
|
</svg>
|
||||||
|
<span class="hidden">Пароль</span></label>
|
||||||
|
<input id="login__password" type="password" name="password" class="form__input" placeholder="Пароль"
|
||||||
|
required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form__field">
|
||||||
|
<input type="submit" value="Войти">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="icons">
|
||||||
|
<symbol id="icon-arrow-right" viewBox="0 0 1792 1792">
|
||||||
|
<path d="M1600 960q0 54-37 91l-651 651q-39 37-91 37-51 0-90-37l-75-75q-38-38-38-91t38-91l293-293H245q-52 0-84.5-37.5T128 1024V896q0-53 32.5-90.5T245 768h704L656 474q-38-36-38-90t38-90l75-75q38-38 90-38 53 0 91 38l651 651q37 35 37 90z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="icon-lock" viewBox="0 0 1792 1792">
|
||||||
|
<path d="M640 768h512V576q0-106-75-181t-181-75-181 75-75 181v192zm832 96v576q0 40-28 68t-68 28H416q-40 0-68-28t-28-68V864q0-40 28-68t68-28h32V576q0-184 132-316t316-132 316 132 132 316v192h32q40 0 68 28t28 68z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="icon-user" viewBox="0 0 1792 1792">
|
||||||
|
<path d="M1600 1405q0 120-73 189.5t-194 69.5H459q-121 0-194-69.5T192 1405q0-53 3.5-103.5t14-109T236 1084t43-97.5 62-81 85.5-53.5T538 832q9 0 42 21.5t74.5 48 108 48T896 971t133.5-21.5 108-48 74.5-48 42-21.5q61 0 111.5 20t85.5 53.5 62 81 43 97.5 26.5 108.5 14 109 3.5 103.5zm-320-893q0 159-112.5 271.5T896 896 624.5 783.5 512 512t112.5-271.5T896 128t271.5 112.5T1280 512z"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
459
upanel/templates/upanel/upanel/menu.html
Normal file
459
upanel/templates/upanel/upanel/menu.html
Normal file
@@ -0,0 +1,459 @@
|
|||||||
|
<!-- Menu -->
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
<aside id="layout-menu" class="layout-menu menu-vertical menu bg-menu-theme">
|
||||||
|
<div class="app-brand demo">
|
||||||
|
<a href="{{ home }}" class="app-brand-link">
|
||||||
|
<span class="app-brand-logo demo">
|
||||||
|
<img src="{% static 'file/upanel/img/miroca.svg' %}">
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span class="app-brand-text demo menu-text fw-bold ms-2">iroca</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="javascript:void(0);" class="layout-menu-toggle menu-link text-large ms-auto d-block d-xl-none">
|
||||||
|
<i class="bx bx-chevron-left bx-sm align-middle"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="menu-inner-shadow"></div>
|
||||||
|
|
||||||
|
<ul class="menu-inner py-1">
|
||||||
|
<!-- Dashboards -->
|
||||||
|
<li class="menu-item active open">
|
||||||
|
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-home-circle"></i>
|
||||||
|
<div data-i18n="Dashboards">Dashboards</div>
|
||||||
|
<div class="badge bg-danger rounded-pill ms-auto">5</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- Layouts -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-layout"></i>
|
||||||
|
<div data-i18n="Layouts">Layouts</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<ul class="menu-sub">
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="layouts-without-menu.html" class="menu-link">
|
||||||
|
<div data-i18n="Without menu">Without menu</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="layouts-without-navbar.html" class="menu-link">
|
||||||
|
<div data-i18n="Without navbar">Without navbar</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="layouts-container.html" class="menu-link">
|
||||||
|
<div data-i18n="Container">Container</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="layouts-fluid.html" class="menu-link">
|
||||||
|
<div data-i18n="Fluid">Fluid</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="layouts-blank.html" class="menu-link">
|
||||||
|
<div data-i18n="Blank">Blank</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- Front Pages -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-store"></i>
|
||||||
|
<div data-i18n="Front Pages">Front Pages</div>
|
||||||
|
<div class="badge bg-label-primary fs-tiny rounded-pill ms-auto">Pro</div>
|
||||||
|
</a>
|
||||||
|
<ul class="menu-sub">
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/front-pages/landing-page.html"
|
||||||
|
class="menu-link"
|
||||||
|
target="_blank">
|
||||||
|
<div data-i18n="Landing">Landing</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/front-pages/pricing-page.html"
|
||||||
|
class="menu-link"
|
||||||
|
target="_blank">
|
||||||
|
<div data-i18n="Pricing">Pricing</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/front-pages/payment-page.html"
|
||||||
|
class="menu-link"
|
||||||
|
target="_blank">
|
||||||
|
<div data-i18n="Payment">Payment</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/front-pages/checkout-page.html"
|
||||||
|
class="menu-link"
|
||||||
|
target="_blank">
|
||||||
|
<div data-i18n="Checkout">Checkout</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/front-pages/help-center-landing.html"
|
||||||
|
class="menu-link"
|
||||||
|
target="_blank">
|
||||||
|
<div data-i18n="Help Center">Help Center</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="menu-header small text-uppercase">
|
||||||
|
<span class="menu-header-text">Apps & Pages</span>
|
||||||
|
</li>
|
||||||
|
<!-- Apps -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/vertical-menu-template/app-email.html"
|
||||||
|
target="_blank"
|
||||||
|
class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-envelope"></i>
|
||||||
|
<div data-i18n="Email">Email</div>
|
||||||
|
<div class="badge bg-label-primary fs-tiny rounded-pill ms-auto">Pro</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/vertical-menu-template/app-chat.html"
|
||||||
|
target="_blank"
|
||||||
|
class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-chat"></i>
|
||||||
|
<div data-i18n="Chat">Chat</div>
|
||||||
|
<div class="badge bg-label-primary fs-tiny rounded-pill ms-auto">Pro</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/vertical-menu-template/app-calendar.html"
|
||||||
|
target="_blank"
|
||||||
|
class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-calendar"></i>
|
||||||
|
<div data-i18n="Calendar">Calendar</div>
|
||||||
|
<div class="badge bg-label-primary fs-tiny rounded-pill ms-auto">Pro</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/vertical-menu-template/app-kanban.html"
|
||||||
|
target="_blank"
|
||||||
|
class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-grid"></i>
|
||||||
|
<div data-i18n="Kanban">Kanban</div>
|
||||||
|
<div class="badge bg-label-primary fs-tiny rounded-pill ms-auto">Pro</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<!-- Pages -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-dock-top"></i>
|
||||||
|
<div data-i18n="Account Settings">Account Settings</div>
|
||||||
|
</a>
|
||||||
|
<ul class="menu-sub">
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="pages-account-settings-account.html" class="menu-link">
|
||||||
|
<div data-i18n="Account">Account</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="pages-account-settings-notifications.html" class="menu-link">
|
||||||
|
<div data-i18n="Notifications">Notifications</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="pages-account-settings-connections.html" class="menu-link">
|
||||||
|
<div data-i18n="Connections">Connections</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-lock-open-alt"></i>
|
||||||
|
<div data-i18n="Authentications">Authentications</div>
|
||||||
|
</a>
|
||||||
|
<ul class="menu-sub">
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="auth-login-basic.html" class="menu-link" target="_blank">
|
||||||
|
<div data-i18n="Basic">Login</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="auth-register-basic.html" class="menu-link" target="_blank">
|
||||||
|
<div data-i18n="Basic">Register</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="auth-forgot-password-basic.html" class="menu-link" target="_blank">
|
||||||
|
<div data-i18n="Basic">Forgot Password</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-cube-alt"></i>
|
||||||
|
<div data-i18n="Misc">Misc</div>
|
||||||
|
</a>
|
||||||
|
<ul class="menu-sub">
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="pages-misc-error.html" class="menu-link">
|
||||||
|
<div data-i18n="Error">Error</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="pages-misc-under-maintenance.html" class="menu-link">
|
||||||
|
<div data-i18n="Under Maintenance">Under Maintenance</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<!-- Components -->
|
||||||
|
<li class="menu-header small text-uppercase"><span class="menu-header-text">Components</span></li>
|
||||||
|
<!-- Cards -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="cards-basic.html" class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-collection"></i>
|
||||||
|
<div data-i18n="Basic">Cards</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<!-- User interface -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="javascript:void(0)" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-box"></i>
|
||||||
|
<div data-i18n="User interface">User interface</div>
|
||||||
|
</a>
|
||||||
|
<ul class="menu-sub">
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-accordion.html" class="menu-link">
|
||||||
|
<div data-i18n="Accordion">Accordion</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-alerts.html" class="menu-link">
|
||||||
|
<div data-i18n="Alerts">Alerts</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-badges.html" class="menu-link">
|
||||||
|
<div data-i18n="Badges">Badges</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-buttons.html" class="menu-link">
|
||||||
|
<div data-i18n="Buttons">Buttons</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-carousel.html" class="menu-link">
|
||||||
|
<div data-i18n="Carousel">Carousel</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-collapse.html" class="menu-link">
|
||||||
|
<div data-i18n="Collapse">Collapse</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-dropdowns.html" class="menu-link">
|
||||||
|
<div data-i18n="Dropdowns">Dropdowns</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-footer.html" class="menu-link">
|
||||||
|
<div data-i18n="Footer">Footer</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-list-groups.html" class="menu-link">
|
||||||
|
<div data-i18n="List Groups">List groups</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-modals.html" class="menu-link">
|
||||||
|
<div data-i18n="Modals">Modals</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-navbar.html" class="menu-link">
|
||||||
|
<div data-i18n="Navbar">Navbar</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-offcanvas.html" class="menu-link">
|
||||||
|
<div data-i18n="Offcanvas">Offcanvas</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-pagination-breadcrumbs.html" class="menu-link">
|
||||||
|
<div data-i18n="Pagination & Breadcrumbs">Pagination & Breadcrumbs</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-progress.html" class="menu-link">
|
||||||
|
<div data-i18n="Progress">Progress</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-spinners.html" class="menu-link">
|
||||||
|
<div data-i18n="Spinners">Spinners</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-tabs-pills.html" class="menu-link">
|
||||||
|
<div data-i18n="Tabs & Pills">Tabs & Pills</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-toasts.html" class="menu-link">
|
||||||
|
<div data-i18n="Toasts">Toasts</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-tooltips-popovers.html" class="menu-link">
|
||||||
|
<div data-i18n="Tooltips & Popovers">Tooltips & popovers</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="ui-typography.html" class="menu-link">
|
||||||
|
<div data-i18n="Typography">Typography</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- Extended components -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="javascript:void(0)" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-copy"></i>
|
||||||
|
<div data-i18n="Extended UI">Extended UI</div>
|
||||||
|
</a>
|
||||||
|
<ul class="menu-sub">
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="extended-ui-perfect-scrollbar.html" class="menu-link">
|
||||||
|
<div data-i18n="Perfect Scrollbar">Perfect scrollbar</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="extended-ui-text-divider.html" class="menu-link">
|
||||||
|
<div data-i18n="Text Divider">Text Divider</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="icons-boxicons.html" class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-crown"></i>
|
||||||
|
<div data-i18n="Boxicons">Boxicons</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- Forms & Tables -->
|
||||||
|
<li class="menu-header small text-uppercase"><span class="menu-header-text">Forms & Tables</span>
|
||||||
|
</li>
|
||||||
|
<!-- Forms -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-detail"></i>
|
||||||
|
<div data-i18n="Form Elements">Form Elements</div>
|
||||||
|
</a>
|
||||||
|
<ul class="menu-sub">
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="forms-basic-inputs.html" class="menu-link">
|
||||||
|
<div data-i18n="Basic Inputs">Basic Inputs</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="forms-input-groups.html" class="menu-link">
|
||||||
|
<div data-i18n="Input groups">Input groups</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||||
|
<i class="menu-icon tf-icons bx bx-detail"></i>
|
||||||
|
<div data-i18n="Form Layouts">Form Layouts</div>
|
||||||
|
</a>
|
||||||
|
<ul class="menu-sub">
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="form-layouts-vertical.html" class="menu-link">
|
||||||
|
<div data-i18n="Vertical Form">Vertical Form</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="form-layouts-horizontal.html" class="menu-link">
|
||||||
|
<div data-i18n="Horizontal Form">Horizontal Form</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<!-- Form Validation -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/vertical-menu-template/form-validation.html"
|
||||||
|
target="_blank"
|
||||||
|
class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-list-check"></i>
|
||||||
|
<div data-i18n="Form Validation">Form Validation</div>
|
||||||
|
<div class="badge bg-label-primary fs-tiny rounded-pill ms-auto">Pro</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<!-- Tables -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a href="tables-basic.html" class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-table"></i>
|
||||||
|
<div data-i18n="Tables">Tables</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<!-- Data Tables -->
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/html/vertical-menu-template/tables-datatables-basic.html"
|
||||||
|
target="_blank"
|
||||||
|
class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-grid"></i>
|
||||||
|
<div data-i18n="Datatables">Datatables</div>
|
||||||
|
<div class="badge bg-label-primary fs-tiny rounded-pill ms-auto">Pro</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<!-- Misc -->
|
||||||
|
<li class="menu-header small text-uppercase"><span class="menu-header-text">Misc</span></li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://github.com/themeselection/sneat-html-admin-template-free/issues"
|
||||||
|
target="_blank"
|
||||||
|
class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-support"></i>
|
||||||
|
<div data-i18n="Support">Support</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item">
|
||||||
|
<a
|
||||||
|
href="https://demos.themeselection.com/sneat-bootstrap-html-admin-template/documentation/"
|
||||||
|
target="_blank"
|
||||||
|
class="menu-link">
|
||||||
|
<i class="menu-icon tf-icons bx bx-file"></i>
|
||||||
|
<div data-i18n="Documentation">Documentation</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</aside>
|
||||||
|
<!-- / Menu -->
|
||||||
39
upanel/templates/upanel/upanel/smarthome.html
Normal file
39
upanel/templates/upanel/upanel/smarthome.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{% extends 'upanel/upanel/base/base.html' %}
|
||||||
|
{% load static %}
|
||||||
|
{#Блоки температуры и влажности#}
|
||||||
|
{% block styleinclude %}
|
||||||
|
<link rel="stylesheet" href="{% static 'file/upanel/css/smart_style.css' %}">
|
||||||
|
{% endblock styleinclude %}
|
||||||
|
{#График#}
|
||||||
|
{% block js %}
|
||||||
|
<script src="{% static 'file/upanel/js/smart-size-reload.js' %}"></script>
|
||||||
|
<script src="{% static 'file/upanel/js/vue.min.js' %}"></script>
|
||||||
|
<script src="{% static 'file/upanel/js/highcharts.js' %}"></script>
|
||||||
|
<script src="{% static 'file/upanel/js/vue-highcharts.min.js' %}"></script>
|
||||||
|
{% endblock js %}
|
||||||
|
{% block content %}
|
||||||
|
<body onload="clockTimer();">
|
||||||
|
<div class="app-content">
|
||||||
|
<div class="projects-section">
|
||||||
|
<div class="projects-section-header">
|
||||||
|
{% include 'upanel/upanel/base/label.html' %}
|
||||||
|
<p class="time" id="dayOfWeek"></p>
|
||||||
|
{% include 'upanel/upanel/base/user.html' %}
|
||||||
|
<div class="projects-section-line">
|
||||||
|
{% include 'upanel/upanel/base/status.html' %}
|
||||||
|
<time id="clock"></time>
|
||||||
|
</div>
|
||||||
|
<ul class="breadcrumb">
|
||||||
|
<li><a href="{% url 'upanel' %}">Главная</a></li>
|
||||||
|
<li><a href="{% url 'smarthome' %}">Умный дом</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="breadcrumbs">
|
||||||
|
{% include 'upanel/upanel/base/temperature.html' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="{% static 'file/upanel/js/script.js' %}"></script>
|
||||||
|
</body>
|
||||||
|
{% endblock content %}
|
||||||
15
upanel/test.py
Normal file
15
upanel/test.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from sshtunnel import SSHTunnelForwarder
|
||||||
|
import os
|
||||||
|
|
||||||
|
hostname = "192.168.88.3"
|
||||||
|
response = os.system("ping -c 1 " + hostname)
|
||||||
|
if response == 0:
|
||||||
|
ssh_tunnel = SSHTunnelForwarder(
|
||||||
|
'192.168.88.3',
|
||||||
|
ssh_username="orangepi",
|
||||||
|
ssh_password="cbvgcjy0",
|
||||||
|
remote_bind_address=('192.168.88.3', 22)
|
||||||
|
)
|
||||||
|
|
||||||
|
ssh_tunnel.start()
|
||||||
|
print(ssh_tunnel.local_bind_port) # show assigned local port
|
||||||
3
upanel/tests.py
Normal file
3
upanel/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
18
upanel/urls.py
Normal file
18
upanel/urls.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from django.urls import path
|
||||||
|
from django.contrib.auth.views import LoginView, LogoutView, PasswordChangeView, PasswordChangeDoneView
|
||||||
|
from django.contrib.auth import logout
|
||||||
|
from .import views
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', views.home, name='upanel'),
|
||||||
|
path('connect/', views.connect, name='connect'),
|
||||||
|
# path('greenhouse/', views.greenhouse, name='greenhouse'),
|
||||||
|
# path('server_smart/', views.server_smart, name='server_smart'),
|
||||||
|
path('login/', LoginView.as_view(template_name='upanel/login.html'), name='login'),
|
||||||
|
path('logout/', LoginView.as_view(template_name='upanel/login.html'), name='logout'),
|
||||||
|
path('password_change/', PasswordChangeView.as_view(template_name='upanel/change_password.html'),
|
||||||
|
name='password_change'),
|
||||||
|
path('password_change/done/', PasswordChangeDoneView.as_view(template_name='upanel/change_password_done.html'),
|
||||||
|
name='password_change_done'),
|
||||||
|
]
|
||||||
56
upanel/views.py
Normal file
56
upanel/views.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import json
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from routeros_api.exceptions import RouterOsApiConnectionError
|
||||||
|
|
||||||
|
# from synology_api.exceptions import JSONDecodeError
|
||||||
|
User = get_user_model()
|
||||||
|
import os, requests,re
|
||||||
|
from django.shortcuts import render, redirect
|
||||||
|
from django.http import JsonResponse
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from .logout import logout_view
|
||||||
|
from upanel.models import *
|
||||||
|
import routeros_api
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url='/login/')
|
||||||
|
def connect(request):
|
||||||
|
try:
|
||||||
|
hosts = User.objects.values('ipaddress').distinct()[0]
|
||||||
|
connection = routeros_api.RouterOsApiPool(hosts['ipaddress'], username='api', password='cbvgcjy0',
|
||||||
|
plaintext_login=True)
|
||||||
|
api = connection.get_api()
|
||||||
|
ping=api.get_binary_resource('/').call('ping', {'address': str.encode(hosts['ipaddress']), 'count': b'2'}) #блять тут надо перевести в байт str.encode
|
||||||
|
return JsonResponse({'ethernet': bytes.decode(max([i['time'] for i in ping]))})
|
||||||
|
except RouterOsApiConnectionError as e:
|
||||||
|
return JsonResponse({'ethernet': 'false'})
|
||||||
|
|
||||||
|
|
||||||
|
# def server_smart(request):
|
||||||
|
# month_int = sorted([int(datetime.datetime.now().strftime('%m'))-i for i in range(6)])
|
||||||
|
# pattern = r'\+\d{2}+\.\d+'
|
||||||
|
# return JsonResponse({'month':list(Month.objects.using('miroca').filter(id__in=month_int).order_by('id').values_list('name', flat=True)),
|
||||||
|
# 'smart_server_temp':max(map(float,re.findall(pattern, os.popen('sensors').read())))})
|
||||||
|
|
||||||
|
|
||||||
|
# # @login_required(login_url='/login/')
|
||||||
|
# # @logout_view
|
||||||
|
# def greenhouse(request):
|
||||||
|
# connect_timeout = 18
|
||||||
|
# read_timeout = 30
|
||||||
|
# host_name_green = Hostname.objects.values('area')[0]['area']
|
||||||
|
# try:
|
||||||
|
# response = requests.get("http://" + host_name_green, timeout=(connect_timeout, read_timeout))
|
||||||
|
# return JsonResponse(response.json() | {'host_name_green':host_name_green})
|
||||||
|
# except Exception as e:
|
||||||
|
# return JsonResponse({'temp': [' ', ' '], 'sensor_lend_web': [' '], 'host_name_green':host_name_green})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required(login_url='/login/')
|
||||||
|
@logout_view
|
||||||
|
def home(request):
|
||||||
|
user = User.objects.get(id=request.user.id)
|
||||||
|
return render(request, 'upanel/upanel/index.html',# {'user': user, 'temp': res['temp'][0], 'damp': res['sensor_lend_web'][0]}
|
||||||
|
)
|
||||||
|
|
||||||
16
wsgi.py
Normal file
16
wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
WSGI config for miroca project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'miroca.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
||||||
Reference in New Issue
Block a user