Merge remote-tracking branch 'origin/main'

This commit is contained in:
SBD
2024-01-09 22:01:13 +03:00
23 changed files with 407 additions and 34 deletions

View File

@@ -112,6 +112,20 @@ class BaseModelViewPage(BaseModel):
class Meta: class Meta:
abstract = True abstract = True
def get_title(self):
if self.seo_title:
return self.seo_title
elif self.title:
return self.title
else:
return self.name
def get_description(self):
if self.seo_description:
return self.seo_description
else:
return self.description
def get_FAQ_items(self): def get_FAQ_items(self):
return self.FAQ_items.filter(enable=True).order_by('order') return self.FAQ_items.filter(enable=True).order_by('order')

View File

@@ -1,14 +1,38 @@
from django.http import HttpResponse, Http404, FileResponse from django.http import HttpResponse, Http404, FileResponse
from django.conf import settings
def get_inter_Dict(user): def get_inter_Dict(user):
from SubscribesApp.funcs import get_cur_user_subscribe from SubscribesApp.funcs import get_cur_user_subscribe
user_subscribe = get_cur_user_subscribe(user) user_subscribe = get_cur_user_subscribe(user)
return {'user_subscribe': user_subscribe} Dict = {
'user_subscribe': user_subscribe,
}
from PushMessages.views import get_key_Dict
Dict.update(get_key_Dict())
return Dict
def get_inter_http_respose(template_obj, context_Dict, request): def get_inter_http_respose(template_obj, context_Dict, request):
context_Dict.update(get_inter_Dict(request.user)) context_Dict.update(get_inter_Dict(request.user))
from PushMessages.views import send_push
if request and 'page' in context_Dict:
text = None
title = None
if context_Dict['page'] == dict:
if 'title' in context_Dict['page']:
title = context_Dict['page']['title']
if 'description' in context_Dict['page']:
text = context_Dict['page']['description']
else:
title = getattr(context_Dict['page'], 'title', None)
text = getattr(context_Dict['page'], 'description', None)
if text and title and not request.user.is_anonymous:
send_push(user=request.user, title=title, text=text)
return HttpResponse(template_obj.render(context_Dict, request)) return HttpResponse(template_obj.render(context_Dict, request))

View File

@@ -6,33 +6,64 @@ from django.contrib.auth.decorators import login_required
from .models import * from .models import *
from django.conf import settings from django.conf import settings
from .funcs import get_inter_http_respose from .funcs import get_inter_http_respose
from django.http.response import JsonResponse, HttpResponse
from django.views.decorators.http import require_GET, require_POST
from django.shortcuts import get_object_or_404
from django.contrib.auth.models import User
from django.views.decorators.csrf import csrf_exempt
from webpush import send_user_notification
import json
def test_code(request): def test_code(request):
from RoutesApp.funcs import get_city_by_type_transport_and_address_point from RoutesApp.funcs import get_city_by_type_transport_and_address_point
from RoutesApp.models import Route from RoutesApp.models import Route
from ReferenceDataApp.models import Airport, City from ReferenceDataApp.models import Airport, City
routes = Route.objects.all() try:
# body = request.body
# data = json.loads(body)
# if 'head' not in data or 'body' not in data or 'id' not in data:
# return JsonResponse(status=400, data={"message": "Invalid data format"})
# user_id = data['id']
user = request.user
payload = {'head': '123', 'body': 'qwerty'}
send_user_notification(user=user, payload=payload, ttl=1000)
return JsonResponse(status=200, data={"message": "Web push successful"})
except TypeError:
return JsonResponse(status=500, data={"message": "An error occurred"})
for route in routes: # routes = Route.objects.all()
print(route.id) #
required_save = False # for route in routes:
if not route.from_city: # print(route.id)
route.from_city = get_city_by_type_transport_and_address_point(route.type_transport, route.from_address_point) # required_save = False
required_save = True # if not route.from_city:
# route.from_city = get_city_by_type_transport_and_address_point(route.type_transport, route.from_address_point)
# required_save = True
#
# if not route.to_city:
# route.to_city = get_city_by_type_transport_and_address_point(route.type_transport,
# route.to_address_point)
# required_save = True
#
# if required_save:
# route.save()
if not route.to_city: # return HttpResponse('finished')
route.to_city = get_city_by_type_transport_and_address_point(route.type_transport,
route.to_address_point)
required_save = True
if required_save:
route.save()
return HttpResponse('finished')
def Page404(request, exeption=None):
Dict = {}
t = loader.get_template('404.html')
try:
res = get_inter_http_respose(t, Dict, request)
return HttpResponse(res, status=404)
except Exception as e:
return HttpResponse(str(e))
@@ -58,6 +89,8 @@ def MainPage(request):
'owner_type': 'mover' 'owner_type': 'mover'
} }
breadcrumbs_Dict = { breadcrumbs_Dict = {
} }
Dict.update({'breadcrumbs': breadcrumbs_Dict}) Dict.update({'breadcrumbs': breadcrumbs_Dict})

0
PushMessages/__init__.py Normal file
View File

3
PushMessages/admin.py Normal file
View File

@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
PushMessages/apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class PushmessagesConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'PushMessages'

View File

3
PushMessages/models.py Normal file
View File

@@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

3
PushMessages/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

16
PushMessages/urls.py Normal file
View File

@@ -0,0 +1,16 @@
# coding=utf-8
from django.urls import path, include
# from AuthApp.js_views import *
# from AuthApp.import_funcs import *
from .views import *
from django.contrib.auth import views
from RoutesApp.js_views import new_route_view_ajax
from django.views.generic import TemplateView
urlpatterns = [
path('send_push', send_push),
path('webpush/', include('webpush.urls')),
path('sw.js', TemplateView.as_view(template_name='sw.js', content_type='application/x-javascript')),
]

39
PushMessages/views.py Normal file
View File

@@ -0,0 +1,39 @@
from django.http.response import JsonResponse, HttpResponse
from django.views.decorators.http import require_GET, require_POST
from django.contrib.auth.models import User
from django.views.decorators.csrf import csrf_exempt
from webpush import send_user_notification
import json
from django.shortcuts import render, get_object_or_404
from django.conf import settings
def get_key_Dict():
webpush_settings = getattr(settings, 'WEBPUSH_SETTINGS', {})
vapid_key = webpush_settings.get('VAPID_PUBLIC_KEY')
Dict = {
'vapid_key': vapid_key
}
return Dict
def send_push(user, title, text, img=None):
try:
# body = request.body
# data = json.loads(body)
#
# if 'head' not in data or 'body' not in data or 'id' not in data:
# return JsonResponse(status=400, data={"message": "Invalid data format"})
#
# user_id = data['id']
# user = get_object_or_404(User, pk=user_id)
Dict = {
'head': title,
'body': text
}
# payload = {'head': data['head'], 'body': data['body']}
send_user_notification(user=user, payload=Dict, ttl=1000)
return JsonResponse(status=200, data={"message": "Web push successful"})
except TypeError:
return JsonResponse(status=500, data={"message": "An error occurred"})

View File

@@ -28,6 +28,14 @@ DEBUG = True
ALLOWED_HOSTS = ["*"] ALLOWED_HOSTS = ["*"]
WEBPUSH_SETTINGS = {
"VAPID_PUBLIC_KEY": "BKS8byh3MucwCF2h06JY9oey1s1RYII09j-j3ehI3qTYhs965UHv0qNPl-jFjQBbIJCvjVXm9RW6t_oJJK8yMOk",
"VAPID_PRIVATE_KEY": "f5NMgOntBtRqsyeKwEzloK-051ggMnZGF_GFimERY0w",
"VAPID_ADMIN_EMAIL": "admin@tripwb.com"
}
# NOTIFICATION_KEY = 'BJLyGzmo8sLI3Qkc6pN2cz11frCXiJdewvgve7Yps-_fM1lY1LSnTQfQxYtAgQ_26nAji_rgeYC1DkLiTwxw0Mo'
# SESSION_COOKIE_HTTPONLY = False # SESSION_COOKIE_HTTPONLY = False
# Application definition # Application definition
@@ -51,12 +59,15 @@ INSTALLED_APPS = [
'ckeditor', 'ckeditor',
'ckeditor_uploader', 'ckeditor_uploader',
'webpush',
'GeneralApp', 'GeneralApp',
'AuthApp', 'AuthApp',
'RoutesApp', 'RoutesApp',
'ReferenceDataApp', 'ReferenceDataApp',
'ArticlesApp', 'ArticlesApp',
'SubscribesApp', 'SubscribesApp',
'PushMessages',
] ]
MIDDLEWARE = [ MIDDLEWARE = [

View File

@@ -3,12 +3,17 @@ from django.contrib import admin
from django.urls import path, include from django.urls import path, include
from django.conf.urls.static import static from django.conf.urls.static import static
from django.conf import settings from django.conf import settings
from GeneralApp.views import Page404
handler404 = Page404
urlpatterns = [ urlpatterns = [
# path('admin/', admin.site.urls), # path('admin/', admin.site.urls),
path('ckeditor/', include('ckeditor_uploader.urls')), path('ckeditor/', include('ckeditor_uploader.urls')),
path('i18n/', include('django.conf.urls.i18n')), path('i18n/', include('django.conf.urls.i18n')),
# path('webpush/', include('webpush.urls')),
path('messages/', include('ChatServiceApp.urls')), path('messages/', include('ChatServiceApp.urls')),
path('user_account/', include('AuthApp.js_urls')), path('user_account/', include('AuthApp.js_urls')),
@@ -22,6 +27,10 @@ urlpatterns = [
path('reference_data/', include('ReferenceDataApp.js_urls')), path('reference_data/', include('ReferenceDataApp.js_urls')),
path('', include('ArticlesApp.js_urls')), path('', include('ArticlesApp.js_urls')),
path('test_404', Page404, name='page_404'),
path('', include('PushMessages.urls'))
] ]
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns

View File

@@ -10,4 +10,5 @@ channels==4.0.0
daphne==4.0.0 daphne==4.0.0
channels-redis==4.1.0 channels-redis==4.1.0
django-colorfield django-colorfield
django-webpush==0.3.5

View File

@@ -1240,7 +1240,7 @@
.not_found_routes{ .not_found_routes{
width: 96%; width: 96%;
height: 250px; min-height: 250px;
background: #FFFFFF; background: #FFFFFF;
box-shadow: -1px 4px 10px 0 rgba(198, 199, 203, 0.20), 0 -1px 10px 0 rgba(198, 199, 203, 0.20); box-shadow: -1px 4px 10px 0 rgba(198, 199, 203, 0.20), 0 -1px 10px 0 rgba(198, 199, 203, 0.20);
position: relative; position: relative;

View File

@@ -773,6 +773,20 @@ span.btn_profile_name {
display: block; display: block;
} }
#create_route{
border-radius: 10px;
color: #FFFFFF;
background: #FF613A;
/*height: 60px;*/
font-size: 18px;
font-weight: 500;
width: 100%;
margin-top: 10px;
display: inline-block;
padding: 15px 0px;
}
/* Change color of dropdown links on hover */ /* Change color of dropdown links on hover */
.dropdown-content-lang a:hover {background-color: #f1f1f1} .dropdown-content-lang a:hover {background-color: #f1f1f1}
@@ -2056,6 +2070,26 @@ button.cancel_remove.show, button.confirm_remove.show{
/*Static_pages*/ /*Static_pages*/
.not_found_wrap{
padding-top: 20px;
}
.not_found_text{
text-align: center;
font-style: normal;
font-weight: 700;
line-height: 52px;
margin-bottom: 20px;
}
.not_found_title{
font-size: 60px;
}
.not_found_sub_title{
font-size: 26px;
}
#title_static{ #title_static{
text-align: center; text-align: center;
font-size: 44px; font-size: 44px;

View File

@@ -0,0 +1,91 @@
const registerSw = async () => {
if ('serviceWorker' in navigator) {
const reg = await navigator.serviceWorker.register('/sw.js');
initialiseState(reg)
} else {
showNotAllowed("You can't send push notifications ☹️😢")
}
};
const initialiseState = (reg) => {
if (!reg.showNotification) {
showNotAllowed('Showing notifications isn\'t supported ☹️😢');
return
}
if (Notification.permission === 'denied') {
showNotAllowed('You prevented us from showing notifications ☹️🤔');
return
}
if (!'PushManager' in window) {
showNotAllowed("Push isn't allowed in your browser 🤔");
return
}
subscribe(reg);
}
const showNotAllowed = (message) => {
const button = document.querySelector('form>button');
button.innerHTML = `${message}`;
button.setAttribute('disabled', 'true');
};
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
const outputData = outputArray.map((output, index) => rawData.charCodeAt(index));
return outputData;
}
const subscribe = async (reg) => {
const subscription = await reg.pushManager.getSubscription();
if (subscription) {
sendSubData(subscription);
return;
}
const vapidMeta = document.querySelector('meta[name="vapid-key"]');
const key = vapidMeta.content;
const options = {
userVisibleOnly: true,
// if key exists, create applicationServerKey property
...(key && {applicationServerKey: urlB64ToUint8Array(key)})
};
const sub = await reg.pushManager.subscribe(options);
sendSubData(sub)
};
const sendSubData = async (subscription) => {
const browser = navigator.userAgent.match(/(firefox|msie|chrome|safari|trident)/ig)[0].toLowerCase();
const data = {
status_type: 'subscribe',
subscription: subscription.toJSON(),
browser: browser,
user_agent: browser,
};
const res = await fetch('/webpush/save_information', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'content-type': 'application/json',
},
credentials: "include"
});
handleResponse(res);
};
const handleResponse = (res) => {
console.log(res.status);
};
registerSw();

27
templates/404.html Normal file
View File

@@ -0,0 +1,27 @@
{% extends "tb_base.html" %}
{% load i18n %}
{% block content %}
<div class="not_found_wrap">
<div class="not_found_text">
<div
class="not_found_title">
404
</div>
<div class="not_found_sub_title">
{% translate "Страница не найдена" %}
</div>
</div>
<div class="button_container">
<a
class="a_btn_standart"
href="{% url 'main' %}">
{% translate "Вернуться на главную" %}
</a>
</div>
</div>
{% endblock %}

View File

@@ -11,8 +11,43 @@
<div class="text-align-center fw-700 font-large c-txt-b2 m-a w-80 m-t-8p"> <div class="text-align-center fw-700 font-large c-txt-b2 m-a w-80 m-t-8p">
{% blocktranslate %} {% blocktranslate %}
Упс... <span class="orange-text">Ничего не найдено</span>, попробуйте Упс... <span class="orange-text">Ничего не найдено</span>, попробуйте
изменить параметры поиска изменить параметры поиска <span class="orange-text"> или создайте своё собственное объявление, чтобы все могли найти
{% endblocktranslate %} {% endblocktranslate %}
{% if owner_type == "mover" %}
{% translate "Отправителя" %}
{% elif owner_type == "customer" %}
{% translate "Перевозчика" %}
{% endif %}
</span>
{% if user.is_authenticated %}
<a
id="create_route"
{% if owner_type == "mover" %}
href="{% url 'profile_page' 'create_route_for_customer' %}"
{% elif owner_type == "customer" %}
href="{% url 'profile_page' 'create_route_for_mover' %}"
{% endif %}
>
{% translate "Создать объявление" %}
</a>
{% endif %}
{% if not user.is_authenticated %}
<a
id="create_route"
href="{% url "login_profile" %}"
>
{% translate " Войти и Создать объявление" %}
</a>
{% endif %}
</div> </div>
<img class="boxes_not_fond_routes left" src="{% static "/img/boxes_for_not_found_routes/b_1.svg" %}"> <img class="boxes_not_fond_routes left" src="{% static "/img/boxes_for_not_found_routes/b_1.svg" %}">
<img class="boxes_not_fond_routes right" src="{% static "/img/boxes_for_not_found_routes/b_2.svg" %}"> <img class="boxes_not_fond_routes right" src="{% static "/img/boxes_for_not_found_routes/b_2.svg" %}">

View File

@@ -13,7 +13,17 @@
{# <h1>Техническая поддержка</h1>#} {# <h1>Техническая поддержка</h1>#}
{# </div>#} {# </div>#}
{% if user.is_staff or staff %} {% if user.is_staff or staff %}
<div class="menu_buttons curtain left {% if mobile %}{% if not ticket %}open{% else %}close{% endif %}{% else %}open{% endif %}{% if name.ticket %}margin{% endif %}" data-name="<img style='width: 25px;display: block;position: relative;bottom: 0;' src='{% static "/img/svg/users-solid.svg" %}'>"> <div class="menu_buttons curtain left
{% if mobile %}
{% if not ticket %}open
{% else %}close
{% endif %}
{% else %}
open
{% endif %}
{% if name.ticket %}margin{% endif %}"
data-name="<img style='width: 25px;display: block;position: relative;bottom: 0;' src='{% static "/img/svg/users-solid.svg" %}'>"
>
<div class="container_block_list_of_users"> <div class="container_block_list_of_users">
{% include 'blocks/profile/b_list_of_tickets_support_chat.html' %} {% include 'blocks/profile/b_list_of_tickets_support_chat.html' %}
</div> </div>

View File

@@ -1,19 +1,11 @@
{% if page.seo_title %} <title>{{ page.get_title }}</title>
<title>{{ page.seo_title }}</title>
{% elif page.title %}
<title>{{ page.title }}</title>
{% elif page.name %}
<title>{{ page.name }}</title>
{% endif %}
{% if page.seo_description %} {% if page.get_description %}
<meta name="description" content="{{ page.seo_description }}"/> <meta name="description" content="{{ page.get_description }}"/>
{% elif page.description %}
<meta name="description" content="{{ page.description }}"/>
{% endif %} {% endif %}
{% if page.seo_keywords %} {% if page.seo_keywords %}
<meta name="keywords" content="{{ page.seo_keywords }}"/> <meta name="keywords" content="{{ page.seo_keywords }}"/>
{% elif page.description %} {% elif page.get_description %}
<meta name="keywords" content="{{ page.description }}"/> <meta name="keywords" content="{{ page.get_description }}"/>
{% endif %} {% endif %}

18
templates/sw.js Normal file
View File

@@ -0,0 +1,18 @@
// Register event listener for the 'push' event.
self.addEventListener('push', function (event) {
// Retrieve the textual payload from event.data (a PushMessageData object).
// Other formats are supported (ArrayBuffer, Blob, JSON), check out the documentation
// on https://developer.mozilla.org/en-US/docs/Web/API/PushMessageData.
const eventInfo = event.data.text();
const data = JSON.parse(eventInfo);
const head = data.head || 'New Notification 🕺🕺';
const body = data.body || 'This is default content. Your notification didn\'t have one 🙄🙄';
// Keep the service worker alive until the notification is created.
event.waitUntil(
self.registration.showNotification(head, {
body: body,
icon: 'static/img/svg/Logo.svg'
})
);
});

View File

@@ -8,6 +8,8 @@
{# <meta name="viewport" content="width=100%,maximum-scale=5,minimum-scale=1,initial-scale=1">#} {# <meta name="viewport" content="width=100%,maximum-scale=5,minimum-scale=1,initial-scale=1">#}
<meta name="viewport" content="width=device-width,maximum-scale=1,minimum-scale=1,initial-scale=1"> <meta name="viewport" content="width=device-width,maximum-scale=1,minimum-scale=1,initial-scale=1">
<meta name="vapid-key" content="{{ vapid_key }}">
{% include "inter/meta_names.html" %} {% include "inter/meta_names.html" %}
{# <script src='{% static "js/jquery_v3_6_4.js" %}'> </script>#} {# <script src='{% static "js/jquery_v3_6_4.js" %}'> </script>#}
@@ -15,6 +17,7 @@
<script type="text/javascript" src="{% static "js/moment_js.js" %}"></script> <script type="text/javascript" src="{% static "js/moment_js.js" %}"></script>
<script type="text/javascript" src="{% static "js/moment-with-locales.js" %}"></script> <script type="text/javascript" src="{% static "js/moment-with-locales.js" %}"></script>
<script type="text/javascript" src="{% static "js/datarangepicker.js" %}"></script> <script type="text/javascript" src="{% static "js/datarangepicker.js" %}"></script>
<script type="text/javascript" src="{% static "js/push/registerSw.js" %}"></script>
<script src="{% static "js/rangecalendartech.js" %}"></script> <script src="{% static "js/rangecalendartech.js" %}"></script>
<link rel="stylesheet" href="{% static 'css/datarangepicker.css' %}" /> <link rel="stylesheet" href="{% static 'css/datarangepicker.css' %}" />
@@ -56,6 +59,7 @@
</head> </head>
<body{% if page_type == 'routes' %} onscroll="scroll_ev(event,this)"{% endif %}> <body{% if page_type == 'routes' %} onscroll="scroll_ev(event,this)"{% endif %}>
{% if page_type != 'routes' %} {% if page_type != 'routes' %}
<script> <script>
let body = document.querySelector("body") let body = document.querySelector("body")
@@ -103,7 +107,7 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
<div class="wrapper_content {% if page.url == 'customer_service'%} m_h_0 {% elif page.url == 'contacts' %}m_h_0{% endif %}"> <div class="wrapper_content {% if page.url == 'customer_service'%} m_h_0 {% elif page.url == 'contacts' %}m_h_0{% elif request.path == '/test_404' %}m_h_0{% endif %}">
{% block content %} {% block content %}
{% endblock %} {% endblock %}