103 Commits

Author SHA1 Message Date
Philip
15c9d589fe serializer 2024-03-05 20:06:38 +03:00
Philip
fa116c08c1 fix task 2024-03-05 13:47:36 +03:00
Philip
4f9129e718 sample 2024-02-28 14:10:20 +03:00
Philip
df45f3a704 not found 2024-02-25 13:41:26 +03:00
Philip
90ef093fca supscriptions 2024-02-24 19:54:57 +03:00
4331b26542 0.1.362 fix language bug redirect to main page 2024-02-22 18:54:15 +03:00
SDE
dd8a8ddd53 0.12.26 get_phone_valid_error change 2024-02-21 17:12:45 +03:00
SBD
abb0d488eb 14 2024-02-21 15:10:34 +03:00
SBD
be97b848d0 14 2024-02-21 14:56:25 +03:00
SBD
6bc112d689 13 2024-02-21 14:37:31 +03:00
SBD
dc534a0c51 12 2024-02-21 14:21:48 +03:00
SDE
e71ed05e6c 0.12.25 timezone in chat messages 2024-02-21 14:12:03 +03:00
SBD
2048ed6baf 11 2024-02-20 19:31:10 +03:00
SBD
c146bd6155 10 2024-02-20 18:57:17 +03:00
SBD
98665abf4d 9 2024-02-20 18:27:36 +03:00
SBD
9954140d3a 9 2024-02-20 17:43:08 +03:00
SBD
fafee63a64 7 2024-02-20 17:35:01 +03:00
c623d69767 0.1.361 comment red marker on mobile_header temp 2024-02-12 17:22:24 +03:00
670eb28bc0 0.1.360 add red marker on mobile_header temp 2024-02-12 17:17:21 +03:00
144ff286f6 0.1.359 add red marker on mobile_header temp 2024-02-12 17:12:44 +03:00
05f94de0b4 Merge remote-tracking branch 'origin/main' 2024-02-12 16:09:24 +03:00
c4650ce603 0.1.358 upd profile_button width 2024-02-12 16:09:13 +03:00
SDE
3971a8ee23 0.12.24 timezone in chat messages 2024-02-09 20:33:04 +03:00
SDE
a3ba6bc783 0.12.23 timezone in chat messages 2024-02-09 18:18:21 +03:00
SDE
b87df02714 0.12.22 timezone in chat messages 2024-02-09 18:01:11 +03:00
SDE
713695cf7d 0.12.21 timezone in chat messages 2024-02-09 17:00:28 +03:00
SDE
a25f30eda7 0.12.20 timezone in chat messages 2024-02-09 16:57:27 +03:00
SDE
eddb3a1858 0.12.19 timezone in chat messages 2024-02-09 15:12:10 +03:00
SDE
5a89200f1d Merge remote-tracking branch 'origin/main' 2024-02-08 14:51:27 +03:00
SDE
2f47a9e3db 0.12.18 registration mail to user 2024-02-08 14:51:19 +03:00
155b6272ec 0.1.357 upd mobile_styles.css for menu_profile 2024-02-08 14:20:50 +03:00
SDE
1479584bfc 0.12.17 change_avatar_confirm_ajax RequestDataTooBig 2024-02-05 23:02:11 +03:00
SDE
f86be5bd97 Merge remote-tracking branch 'origin/main' 2024-02-05 22:41:58 +03:00
SDE
c87a7095ad 0.12.16 change_avatar_confirm_ajax RequestDataTooBig 2024-02-05 22:41:50 +03:00
ac4df7a5f7 0.1.356 upd text_block 2024-02-05 14:34:15 +03:00
SDE
c48839ff8c 0.12.15 subscribe mailing 2024-02-02 18:50:51 +03:00
SDE
ea296e3f05 0.12.14 subscribe mailing 2024-02-02 18:15:51 +03:00
SDE
8124ed62fe 0.12.13 subscribe mailing 2024-02-02 18:08:28 +03:00
SDE
cc643d2641 0.12.12 subscribe mailing 2024-02-02 18:06:35 +03:00
SDE
6de42c5ba9 Merge remote-tracking branch 'origin/main' 2024-02-02 17:44:50 +03:00
SDE
36b7f4dee7 0.12.11 subscribe mailing 2024-02-02 17:44:43 +03:00
2328f09023 0.1.355 mailingSubscribeRequired functional UPD 2024-02-02 17:41:01 +03:00
60faeeace9 Merge remote-tracking branch 'origin/main' 2024-02-02 17:37:35 +03:00
abe53dd88b 0.1.354 mailingSubscribeRequired functional 2024-02-02 17:37:25 +03:00
SDE
c76a18c5ff Merge remote-tracking branch 'origin/main' 2024-02-02 15:51:45 +03:00
SDE
3725ce1882 0.12.10 routes order 2024-02-02 15:51:37 +03:00
6a69ff02b1 0.1.353 add font-display for lcp test 2024-02-02 15:04:30 +03:00
6ba41af305 0.1.352 small bug_fix 2024-02-02 12:50:59 +03:00
SDE
5815a08b55 0.12.9 subscribe mailing 2024-02-01 19:13:26 +03:00
SDE
7805161829 0.12.8 subscribe mailing 2024-02-01 19:07:48 +03:00
6fa31f3866 Merge remote-tracking branch 'origin/main' 2024-02-01 18:51:01 +03:00
0763faf224 0.1.351 upd footer 2024-02-01 18:50:28 +03:00
SDE
a3d3e12467 0.12.7 subscribe mailing 2024-02-01 18:43:16 +03:00
SDE
ab22a3ec88 0.12.6 subscribe mailing 2024-02-01 18:32:29 +03:00
SDE
9d0a059909 0.12.5 subscribe mailing 2024-02-01 18:24:02 +03:00
SDE
1011f112b2 0.12.4 subscribe mailing 2024-02-01 17:49:57 +03:00
SDE
d07ab2c71f Merge remote-tracking branch 'origin/main' 2024-02-01 17:46:55 +03:00
SDE
96bfef04a8 0.12.3 subscribe mailing 2024-02-01 17:46:44 +03:00
SBD
779dd7e93d 7 2024-02-01 15:06:05 +03:00
SBD
0abcb34829 7 2024-02-01 14:58:26 +03:00
SBD
33c028207a 6 2024-02-01 14:36:08 +03:00
SBD
64b3e40ed0 6 2024-02-01 14:14:35 +03:00
SBD
0023676b28 Merge remote-tracking branch 'origin/main' 2024-02-01 13:26:53 +03:00
SBD
b90039f21a 5 2024-02-01 13:26:42 +03:00
b5f24ebf2e 0.1.350 small upd for .css 2024-01-31 17:49:03 +03:00
SBD
f99a010e4a 5 2024-01-31 17:17:53 +03:00
SBD
a4944360a6 5 2024-01-31 17:13:15 +03:00
SBD
a2b5d81c98 5 2024-01-31 17:11:12 +03:00
SBD
13b7c2572d Merge remote-tracking branch 'origin/main' 2024-01-31 16:57:06 +03:00
SBD
47b12882ba 5 2024-01-31 16:56:57 +03:00
SDE
c008aa585b Merge remote-tracking branch 'origin/main' 2024-01-31 16:39:12 +03:00
SDE
406b5e8480 0.12.2 registration mail 2024-01-31 16:39:03 +03:00
SBD
584a196784 5 2024-01-31 15:20:50 +03:00
SBD
618f7751d1 5 2024-01-31 15:20:20 +03:00
SBD
faaea1129a 5 2024-01-31 15:11:39 +03:00
SBD
dd7afc28f7 5 2024-01-31 15:00:48 +03:00
SBD
9ecf5ce073 5 2024-01-31 14:55:04 +03:00
SBD
422373f00e 5 2024-01-31 14:46:18 +03:00
SBD
60636daeb8 Merge remote-tracking branch 'origin/main' 2024-01-31 14:40:19 +03:00
SBD
9d47f4c2bc 5 2024-01-31 14:40:11 +03:00
SDE
4d6dbddd28 Merge remote-tracking branch 'origin/main' 2024-01-31 14:37:49 +03:00
SDE
3f00ff39d2 0.12.1 fix form from and to place fields choices 2024-01-31 14:37:41 +03:00
SBD
bff6a81586 Merge remote-tracking branch 'origin/main' 2024-01-31 14:12:55 +03:00
SBD
9cb8036d3c 3 2024-01-31 14:12:44 +03:00
SDE
a43de1fa91 Merge remote-tracking branch 'origin/main' 2024-01-31 13:44:18 +03:00
SDE
93717bee2d 0.12.11 del mobile markers for response 2024-01-31 13:44:08 +03:00
SBD
8db1d6fdce 3 2024-01-31 13:41:47 +03:00
SBD
b41f8c7eca 3 2024-01-31 13:37:31 +03:00
SBD
c19405d32a Merge remote-tracking branch 'origin/main' 2024-01-31 13:24:02 +03:00
SBD
7b75c533a8 3 2024-01-31 13:23:50 +03:00
SDE
649dbab901 0.12.10 fix allauth google cancel 2024-01-26 19:02:17 +03:00
SDE
1a4498d19f 0.12.9 fix allauth google cancel 2024-01-26 19:00:47 +03:00
SDE
2786ef454d Merge remote-tracking branch 'origin/main' 2024-01-26 18:26:52 +03:00
SDE
961c0dd2a5 0.12.8 switch off push for static pages 2024-01-26 18:26:37 +03:00
SBD
0a0835d3a6 3 2024-01-26 18:20:25 +03:00
SBD
bc87d10d59 Merge remote-tracking branch 'origin/main' 2024-01-26 18:14:50 +03:00
SBD
792693848b 2 2024-01-26 18:14:41 +03:00
SDE
de229c5f78 0.12.7 chat fixes 2024-01-26 17:45:48 +03:00
SDE
03f9a836e6 0.12.6 chat fixes 2024-01-26 17:09:42 +03:00
SBD
91751574cc 1 2024-01-26 16:31:58 +03:00
d5453dada6 0.1.349 small upd 2024-01-26 14:37:50 +03:00
22adb18a39 Merge remote-tracking branch 'origin/main' 2024-01-26 13:59:36 +03:00
0a3c40dd5d 0.1.348 upd input_list for main page 2024-01-26 13:58:51 +03:00
60 changed files with 1142 additions and 163 deletions

1
.gitignore vendored
View File

@@ -414,4 +414,5 @@ fabric.properties
# Android studio 3.1+ serialized cache file # Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser .idea/caches/build_file_checksums.ser
celerybeat-schedule.db

View File

@@ -43,6 +43,7 @@ class Admin_ProfileInline(admin.StackedInline):
('enable',), ('enable',),
('phone',), ('phone',),
('country', 'city'), ('country', 'city'),
('mailing_on', ),
('authMailCode',), ('authMailCode',),
('birthdate'), ('birthdate'),
'comment', 'creator' 'comment', 'creator'
@@ -71,6 +72,10 @@ class Admin_ProfileInline(admin.StackedInline):
class Admin_User(UserAdmin): class Admin_User(UserAdmin):
def mailing_on(self, obj):
return obj.user_profile.mailing_on
mailing_on.boolean = True
fieldsets = ( fieldsets = (
(None, { (None, {
'classes': ['wide'], 'classes': ['wide'],
@@ -91,16 +96,18 @@ class Admin_User(UserAdmin):
save_on_top = True save_on_top = True
list_display = ['id', 'last_name', 'first_name', 'email', 'is_staff', list_display = ['id', 'last_name', 'first_name', 'mailing_on', 'email', 'is_staff',
'is_active'] 'is_active']
list_editable = ['is_staff', 'is_active'] list_editable = ['is_staff', 'is_active']
list_display_links = ['first_name', 'last_name', 'email'] list_display_links = ['first_name', 'last_name', 'email']
search_fields = ['first_name', 'last_name', 'email'] search_fields = ['first_name', 'last_name', 'email']
list_filter = ['user_profile__mailing_on', 'is_staff', 'is_active']
inlines = (Admin_ProfileInline,) inlines = (Admin_ProfileInline,)
# actions = ['del_all_temp_users', ] # actions = ['del_all_temp_users', ]
ordering = ['is_staff', 'last_name', 'first_name'] ordering = ['is_staff', '-id', 'last_name', 'first_name']
# Re-register UserAdmin # Re-register UserAdmin
admin.site.unregister(User) admin.site.unregister(User)

View File

@@ -1,5 +1,19 @@
from django.template.loader import render_to_string from django.template.loader import render_to_string
def get_user_timezone_Dict(user, request=None):
tz = None
if request:
tz = request.COOKIES.get("user_tz")
if not tz and user.is_authenticated:
tz = user.user_profile.get_timezone()
if not tz:
from django.conf import settings
tz = settings.TIME_ZONE
return {'user_tz': tz}
def get_dashboard_page_content_html(request): def get_dashboard_page_content_html(request):
from ChatServiceApp.funcs import get_unanswered_msgs_count_for_user from ChatServiceApp.funcs import get_unanswered_msgs_count_for_user
@@ -76,5 +90,7 @@ def get_profile_support_page_content_html(request, data=None):
} }
tpl_name = 'blocks/profile/b_support_tickets.html' tpl_name = 'blocks/profile/b_support_tickets.html'
Dict.update(get_user_timezone_Dict(request.user, request=request))
html = render_to_string(tpl_name, Dict, request=request) html = render_to_string(tpl_name, Dict, request=request)
return html return html

View File

@@ -28,6 +28,8 @@ urlpatterns = [
path('change_profile_confirm/', change_profile_confirm_ajax, name='change_profile_confirm_ajax'), path('change_profile_confirm/', change_profile_confirm_ajax, name='change_profile_confirm_ajax'),
path('change_avatar_confirm/', change_avatar_confirm_ajax, name='change_avatar_confirm_ajax'), path('change_avatar_confirm/', change_avatar_confirm_ajax, name='change_avatar_confirm_ajax'),
path('send_message/', send_message_ajax, name='send_message_ajax') path('send_message/', send_message_ajax, name='send_message_ajax'),
path('mailing_subscribe/', mailing_subscribe_ajax, name='mailing_subscribe_ajax')
] ]

View File

@@ -17,6 +17,7 @@ import json
from django.core.files import File from django.core.files import File
import base64 import base64
from django.core.validators import validate_email from django.core.validators import validate_email
from django.urls import reverse
# @login_required(login_url='/profile/login/') # @login_required(login_url='/profile/login/')
@@ -31,6 +32,49 @@ from django.core.validators import validate_email
# return JsonResponse({'html': html}, status=200) # return JsonResponse({'html': html}, status=200)
def mailing_subscribe_ajax(request):
if request.method != 'POST':
raise Http404
try:
email = request.POST['email']
user = None
if request.user and request.user.is_authenticated:
user = request.user
user.user_profile.mailing_on = True
user.user_profile.save(update_fields=['mailing_on'])
return JsonResponse({
'status': 'sended',
'del_form': True,
'html': _('Подписка на рассылку для адреса ') + user.email + _(' одобрена')
})
if not user:
try:
user = User.objects.get(email=email)
except User.DoesNotExist:
user = None
if user:
redirect_url = f"{reverse('login_profile')}?mailingSubscribeRequired=true"
else:
redirect_url = f"{reverse('registration_page')}?mailingSubscribeRequired=true"
return JsonResponse({
'status': 'sended',
'redirect_url': redirect_url,
'email': email
})
except Exception as e:
return JsonResponse({
'status': 'error',
'html': str(e)
}, status=400)
def send_message_ajax(request): def send_message_ajax(request):
if request.method != 'POST': if request.method != 'POST':
@@ -188,6 +232,7 @@ def chats_ajax(request):
'receivers': receivers, 'receivers': receivers,
# 'messages': cur_chat_msgs # 'messages': cur_chat_msgs
} }
Dict.update(get_user_timezone_Dict(request.user, request=request))
html = render_to_string('blocks/profile/b_chats.html', Dict, request=request) html = render_to_string('blocks/profile/b_chats.html', Dict, request=request)
return JsonResponse({'html': html}, status=200) return JsonResponse({'html': html}, status=200)
@@ -205,6 +250,7 @@ def support_tickets_ajax(request):
@login_required(login_url='/profile/login/') @login_required(login_url='/profile/login/')
def change_avatar_confirm_ajax(request): def change_avatar_confirm_ajax(request):
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.core.exceptions import RequestDataTooBig
if request.method != 'POST': if request.method != 'POST':
raise Http404 raise Http404
@@ -217,11 +263,15 @@ def change_avatar_confirm_ajax(request):
file = ContentFile(content) file = ContentFile(content)
request.user.user_profile.avatar.save(file_data['file_name'], file) request.user.user_profile.avatar.save(file_data['file_name'], file)
request.user.user_profile.save(update_fields=['avatar']) request.user.user_profile.save(update_fields=['avatar'])
except RequestDataTooBig:
msg = _('Слишком большой размер файла. Размер файла не должен быть больше 3МБ')
print(msg)
return JsonResponse({'error': msg}, status=400)
except Exception as e: except Exception as e:
msg = f'change_avatar_confirm_ajax Error = {str(e)}' msg = f'change_avatar_confirm_ajax Error = {str(e)}'
print(msg) print(msg)
JsonResponse({'error': msg}) return JsonResponse({'error': msg}, status=400)
return JsonResponse({'url': request.user.user_profile.avatar.url}) return JsonResponse({'url': request.user.user_profile.avatar.url})
@@ -361,6 +411,9 @@ def login_ajax(request):
user = authenticate(username=form.data['username'], password=form.data['password']) user = authenticate(username=form.data['username'], password=form.data['password'])
if user is not None: if user is not None:
auth.login(request, user) auth.login(request, user)
if 'mailingSubscribeRequired' in data and data['mailingSubscribeRequired'] == 'true':
user.user_profile.mailing_on = True
user.user_profile.save(update_fields=['mailing_on'])
else: else:
errors_Dict = { errors_Dict = {
'errors': { 'errors': {
@@ -390,6 +443,42 @@ def login_ajax(request):
return JsonResponse({'html': html}, status=400) return JsonResponse({'html': html}, status=400)
def send_registration_mail(data_Dict, user):
try:
from GeneralApp.funcs_options import get_options_by_opt_types, get_mail_send_options
sets = get_options_by_opt_types(['domain', 'project_name'], only_vals=True)
subject = _('Добро пожаловать в Trip With Bonus!')
Dict = {
'logo': f'{sets["domain"]}/static/img/svg/LogoMobile.svg',
'project_name': sets['project_name'],
'message_title': subject,
}
Dict.update(data_Dict)
html = render_to_string('mail/m_registration.html', Dict)
from BaseModels.mailSender import admin_send_mail_by_SMTPlib
mail_sets = get_mail_send_options()
to = [user.email, 'web@syncsystems.net', 'sa@a3-global.com', 'sysadmin.hax@gmail.com']
res = admin_send_mail_by_SMTPlib(
mail_sets,
subject=subject,
from_email=mail_sets['sender_email'], to=to,
html_content=html
)
return res
except Exception as e:
print(f'send_registration_mail Error = {str(e)}')
return None
def registration_ajax(request): def registration_ajax(request):
if request.method != 'POST': if request.method != 'POST':
raise Http404 raise Http404
@@ -417,12 +506,21 @@ def registration_ajax(request):
if user: if user:
auth.login(request, user, backend='django.contrib.auth.backends.ModelBackend') auth.login(request, user, backend='django.contrib.auth.backends.ModelBackend')
if 'mailingSubscribeRequired' in data and data['mailingSubscribeRequired'] == 'true':
user.user_profile.mailing_on = True
user.last_name = form.data['lastname'] user.last_name = form.data['lastname']
user.first_name = form.data['firstname'] user.first_name = form.data['firstname']
user.save() user.save()
user.user_profile.phone = form.data['tel'] user.user_profile.phone = form.data['tel']
user.user_profile.save() user.user_profile.save()
mail_Dict = {
'user': user,
'pass': form.data['password']
}
res = send_registration_mail(mail_Dict, user)
res_Dict = { res_Dict = {
'redirect_url': reverse('profile_page', args=['dashboard']) 'redirect_url': reverse('profile_page', args=['dashboard'])
} }

View File

@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2024-02-01 17:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('AuthApp', '0004_alter_userprofile_account_type'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='mailing_on',
field=models.BooleanField(default=False, verbose_name='Рассылка'),
),
]

View File

@@ -51,6 +51,14 @@ class UserProfile(BaseModel):
on_delete=models.SET_NULL on_delete=models.SET_NULL
) )
mailing_on = models.BooleanField(default=False, verbose_name=_('Рассылка'))
def get_timezone(self):
tz = None
if 'user_timezone' in self.json_data:
tz = self.json_data['user_timezone']
return tz
def save_user_alerts_to_session(self, request): def save_user_alerts_to_session(self, request):
for_save_to_session = self.get_node_by_name('for_save_to_session') for_save_to_session = self.get_node_by_name('for_save_to_session')
if for_save_to_session: if for_save_to_session:

View File

@@ -19,6 +19,11 @@ def registration_View(request):
Dict = {} Dict = {}
if request.GET and 'mailingSubscribeRequired' in request.GET and request.GET['mailingSubscribeRequired'] == 'true':
request.session['mailingSubscribeRequired'] = 'true'
# if request.p
t = loader.get_template('pages/profile/p_registration.html') t = loader.get_template('pages/profile/p_registration.html')
return get_inter_http_respose(t, Dict, request) return get_inter_http_respose(t, Dict, request)
# return HttpResponse(t.render(Dict, request)) # return HttpResponse(t.render(Dict, request))
@@ -44,6 +49,11 @@ def profile_page_View(request, page_name, id=None):
'page_type': 'profile' 'page_type': 'profile'
} }
if request.session and 'mailingSubscribeRequired' in request.session and request.session['mailingSubscribeRequired'] == 'true':
request.user.user_profile.mailing_on = True
request.user.user_profile.save(update_fields=['mailing_on'])
del request.session['mailingSubscribeRequired']
title = f"{_('Личный кабинет пользователя')} {request.user.first_name} {request.user.last_name}" title = f"{_('Личный кабинет пользователя')} {request.user.first_name} {request.user.last_name}"
Dict.update({ Dict.update({
@@ -54,10 +64,10 @@ def profile_page_View(request, page_name, id=None):
} }
}) })
if request.GET and 'mobile' in request.GET and request.GET['mobile'] == 'true': # if request.GET and 'mobile' in request.GET and request.GET['mobile'] == 'true':
Dict.update({ # Dict.update({
'mobile': True # 'mobile': True
}) # })
t = loader.get_template('pages/profile/p_user_profile.html') t = loader.get_template('pages/profile/p_user_profile.html')
return get_inter_http_respose(t, Dict, request) return get_inter_http_respose(t, Dict, request)
@@ -123,6 +133,9 @@ def login_View(request):
'auth_google_allow': auth_google_allow 'auth_google_allow': auth_google_allow
} }
if request.GET and 'mailingSubscribeRequired' in request.GET and request.GET['mailingSubscribeRequired'] == 'true':
request.session['mailingSubscribeRequired'] = 'true'
t = loader.get_template('pages/profile/p_login.html') t = loader.get_template('pages/profile/p_login.html')
return get_inter_http_respose(t, Dict, request) return get_inter_http_respose(t, Dict, request)
# return HttpResponse(t.render(Dict, request)) # return HttpResponse(t.render(Dict, request))

View File

@@ -3,7 +3,7 @@ from django.utils.safestring import mark_safe
def get_phone_valid_error(val): def get_phone_valid_error(val):
allow_chars = '01234567890()+ -' allow_chars = '01234567890()+ -'
error_msg = mark_safe(_('Некорректные символы в номере телефона,<br> пример корректного ввода +7 925 8600100')) error_msg = mark_safe(_('Некорректные символы в номере, введите номер в международном формате с кодом страны'))
if not val: if not val:
return None return None

View File

@@ -1,3 +1,5 @@
import copy
from .models import * from .models import *
from django.db.models import Q, Value as V, Count, OuterRef, Subquery from django.db.models import Q, Value as V, Count, OuterRef, Subquery
from django.http import HttpResponse, Http404, JsonResponse from django.http import HttpResponse, Http404, JsonResponse
@@ -11,7 +13,7 @@ from django.urls import reverse
import json import json
from datetime import datetime, time from datetime import datetime, time
from django.conf import settings from django.conf import settings
from AuthApp.funcs import get_user_timezone_Dict
def get_unanswered_msgs_count_for_user(user): def get_unanswered_msgs_count_for_user(user):
@@ -52,11 +54,22 @@ def get_update_chat_Dict(data):
receiver = User.objects.get(id=data['receiver']) receiver = User.objects.get(id=data['receiver'])
if data['sender'] == data['cur_user']: if data['sender'] == data['cur_user']:
context_Dict.update({'user': sender}) user = copy.copy(sender)
cur_receiver = copy.copy(receiver)
else: else:
context_Dict.update({'user': receiver}) user = copy.copy(receiver)
cur_receiver = copy.copy(sender)
# context_Dict.update({'user': receiver})
context_Dict.update({'cur_receiver': receiver}) # context_Dict.update({'cur_receiver': receiver})
context_Dict.update({
'cur_receiver': cur_receiver,
'user': user,
})
context_Dict.update(get_user_timezone_Dict(user))
if sender == receiver:
print('!')
required_beep = data['required_beep'] required_beep = data['required_beep']
@@ -99,7 +112,7 @@ def get_update_chat_Dict(data):
context_Dict.update({ context_Dict.update({
'messages': msgs, 'messages': msgs,
'MEDIA_URL': settings.MEDIA_URL 'MEDIA_URL': settings.MEDIA_URL,
}) })
html = render_to_string(tpl_name, context_Dict) html = render_to_string(tpl_name, context_Dict)
if required_full_support_chat_html: if required_full_support_chat_html:
@@ -275,6 +288,7 @@ def send_msg(data):
def get_chat_page_content_html(request, receiver_id=None): def get_chat_page_content_html(request, receiver_id=None):
from AuthApp.models import User from AuthApp.models import User
from AuthApp.funcs import get_user_timezone_Dict
msgs = [] msgs = []
try: try:
@@ -294,6 +308,7 @@ def get_chat_page_content_html(request, receiver_id=None):
'receivers': receivers, 'receivers': receivers,
'page': 'chat', 'page': 'chat',
} }
Dict.update(get_user_timezone_Dict(request.user, request=request))
tpl_name = 'blocks/profile/b_chats.html' tpl_name = 'blocks/profile/b_chats.html'
html = render_to_string(tpl_name, Dict, request=request) html = render_to_string(tpl_name, Dict, request=request)

View File

@@ -53,6 +53,7 @@ def show_chat_w_user_ajax(request):
data = json.loads(request.body) data = json.loads(request.body)
Dict = get_chat_page_content_Dict(request, data['user_id']) Dict = get_chat_page_content_Dict(request, data['user_id'])
Dict.update(get_user_timezone_Dict(request.user, request=request))
tpl_name = 'blocks/profile/b_chats.html' tpl_name = 'blocks/profile/b_chats.html'
@@ -99,7 +100,7 @@ def update_chat_ajax2(request):
receiver = User.objects.get(id=data['receiver']) receiver = User.objects.get(id=data['receiver'])
context_Dict.update({'cur_receiver': receiver}) context_Dict.update({'cur_receiver': receiver})
context_Dict.update(get_user_timezone_Dict(request.user, request=request))
if not ticket: if not ticket:
@@ -123,6 +124,7 @@ def update_chat_ajax2(request):
# формируем правую панель # формируем правую панель
context_Dict.update({'receivers': receivers}) context_Dict.update({'receivers': receivers})
users_list_html = render_to_string( users_list_html = render_to_string(
'blocks/profile/b_list_of_users_messenger.html', context_Dict, request=request) 'blocks/profile/b_list_of_users_messenger.html', context_Dict, request=request)
res_Dict.update({ res_Dict.update({
@@ -190,6 +192,7 @@ def update_chat_ajax(request):
receiver = User.objects.get(id=data['receiver']) receiver = User.objects.get(id=data['receiver'])
context_Dict.update({'cur_receiver': receiver}) context_Dict.update({'cur_receiver': receiver})
context_Dict.update(get_user_timezone_Dict(request.user, request=request))
if ticket: if ticket:
@@ -201,6 +204,8 @@ def update_chat_ajax(request):
context_Dict.update({'messages': msgs}) context_Dict.update({'messages': msgs})
context_Dict = get_ticketsDict_for_staff(request.user) context_Dict = get_ticketsDict_for_staff(request.user)
context_Dict.update(get_user_timezone_Dict(request.user))
tickets_list_html = render_to_string( tickets_list_html = render_to_string(
'blocks/profile/b_list_of_tickets_support_chat.html', context_Dict, request=request) 'blocks/profile/b_list_of_tickets_support_chat.html', context_Dict, request=request)
res_Dict.update({ res_Dict.update({
@@ -220,6 +225,8 @@ def update_chat_ajax(request):
required_beep = True required_beep = True
context_Dict.update({'receivers': receivers}) context_Dict.update({'receivers': receivers})
context_Dict.update(get_user_timezone_Dict(request.user))
users_list_html = render_to_string( users_list_html = render_to_string(
'blocks/profile/b_list_of_users_messenger.html', context_Dict, request=request) 'blocks/profile/b_list_of_users_messenger.html', context_Dict, request=request)
res_Dict.update({ res_Dict.update({
@@ -404,12 +411,14 @@ def support_show_chat_by_ticket_ajax(request):
'cur_receiver': cur_receiver, 'cur_receiver': cur_receiver,
'new_msg_allow': new_msg_allow, 'new_msg_allow': new_msg_allow,
'staff': request.user.is_staff, 'staff': request.user.is_staff,
'mobile': data['mobile'] # 'mobile': data['mobile']
} }
Dict.update(get_ticketsDict_for_staff(request.user)) Dict.update(get_ticketsDict_for_staff(request.user))
tpl_name = 'blocks/profile/b_support_chat.html' Dict.update(get_user_timezone_Dict(request.user))
tpl_name = 'blocks/profile/b_support_chat.html'
Dict.update(get_user_timezone_Dict(request.user, request=request))
html = render_to_string(tpl_name, Dict, request=request) html = render_to_string(tpl_name, Dict, request=request)
return JsonResponse({'html': html}, status=200) return JsonResponse({'html': html}, status=200)
@@ -429,6 +438,9 @@ def support_create_ticket_form_ajax(request):
Dict = { Dict = {
'form': TicketForm() 'form': TicketForm()
} }
Dict.update(get_user_timezone_Dict(request.user))
tpl_name = 'blocks/profile/b_create_ticket.html' tpl_name = 'blocks/profile/b_create_ticket.html'
html = render_to_string(tpl_name, Dict, request=request) html = render_to_string(tpl_name, Dict, request=request)
@@ -450,6 +462,8 @@ def create_ticket_ajax(request):
if not form.is_valid(): if not form.is_valid():
form.initial = form.cleaned_data form.initial = form.cleaned_data
Dict = {'form': form} Dict = {'form': form}
Dict.update(get_user_timezone_Dict(request.user))
html = render_to_string('blocks/profile/b_create_ticket.html', Dict, request=request) html = render_to_string('blocks/profile/b_create_ticket.html', Dict, request=request)
return JsonResponse({'html': html}, status=400) return JsonResponse({'html': html}, status=400)
@@ -490,6 +504,8 @@ def create_ticket_ajax(request):
'messages': msgs_for_ticket 'messages': msgs_for_ticket
} }
Dict.update(get_user_timezone_Dict(request.user))
html = render_to_string('blocks/profile/b_support_chat.html', Dict, request=request) html = render_to_string('blocks/profile/b_support_chat.html', Dict, request=request)
res_Dict = { res_Dict = {
@@ -500,9 +516,11 @@ def create_ticket_ajax(request):
except Exception as e: except Exception as e:
msg = f'{_("ошибка в запросе")} = {str(e)}'
errors_Dict = { errors_Dict = {
'errors': { 'errors': {
'all__': f'{_("ошибка в запросе")} = {str(e)}' 'all__': msg
} }
} }
Dict = {'form': errors_Dict} Dict = {'form': errors_Dict}

View File

@@ -46,7 +46,7 @@ class MsgGroup(BaseModel):
if msg.text: if msg.text:
return msg.text return msg.text
elif msg.files: elif msg.files:
return msg.files[0].file_name return msg.files[0]['file_name']
return self.name return self.name

View File

@@ -41,6 +41,10 @@ def get_filesize(size):
@register.simple_tag @register.simple_tag
def get_msg_side(cur_user, ticket, msg): def get_msg_side(cur_user, ticket, msg):
if msg: if msg:
# if msg.sender == cur_user:
# return 'left'
# else:
# return 'right'
if msg.sender == cur_user: if msg.sender == cur_user:
return 'right' return 'right'
else: else:

View File

@@ -6,9 +6,16 @@ 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)
Dict = { Dict = {
'user_subscribe': user_subscribe, 'user_subscribe': user_subscribe,
'prod': True
} }
if settings.WS_ADDRESS == 'localhost:8000':
Dict.update({'prod': False})
from PushMessages.views import get_key_Dict from PushMessages.views import get_key_Dict
Dict.update(get_key_Dict()) Dict.update(get_key_Dict())
@@ -32,7 +39,7 @@ def get_inter_http_respose(template_obj, context_Dict, request):
title = getattr(context_Dict['page'], 'title', None) title = getattr(context_Dict['page'], 'title', None)
text = getattr(context_Dict['page'], 'description', None) text = getattr(context_Dict['page'], 'description', None)
if text and title and not request.user.is_anonymous: # if text and title and not request.user.is_anonymous:
send_push(user=request.user, title=title, text=text) # 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))

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
celery -A TWB.celery:app worker -l info
celery -A TWB.celery:app beat -l info

View File

@@ -6,6 +6,47 @@ from django.core.exceptions import ValidationError
from .models import * from .models import *
def routeForm_assign_choices_by_type_transport(form, type_transport):
if type_transport == 'avia':
transfer_location_choices = (
('airport', _('В аэропорту')),
('city', _('По городу')),
('other', _('По договоренности'))
)
cargo_type_choices = (
('cargo', _('Груз')),
('parcel', _('Бандероль')),
('package', _('Посылка')),
('letter', _('Письмо\Документ'))
)
else:
transfer_location_choices = (
('city', _('По городу')),
('other', _('По договоренности'))
)
cargo_type_choices = (
('passenger', _('Пассажир')),
('cargo', _('Груз')),
('parcel', _('Бандероль')),
('package', _('Посылка')),
('letter', _('Письмо\Документ'))
)
form.fields['from_place'].choices = transfer_location_choices
form.fields['to_place'].choices = transfer_location_choices
form.fields['cargo_type'].choices = cargo_type_choices
form.base_fields['from_place'].choices = transfer_location_choices
form.base_fields['to_place'].choices = transfer_location_choices
form.base_fields['cargo_type'].choices = cargo_type_choices
return form
class RouteForm(forms.ModelForm): class RouteForm(forms.ModelForm):
from_address_point_txt = forms.CharField(required=True) from_address_point_txt = forms.CharField(required=True)
to_address_point_txt = forms.CharField(required=True) to_address_point_txt = forms.CharField(required=True)

View File

@@ -7,12 +7,19 @@ from datetime import datetime
elements_on_page = 25 elements_on_page = 25
def get_profile_new_route_page_html(request, data): def get_profile_new_route_page_html(request, data):
form = RouteForm() form = RouteForm()
Dict = { Dict = {
'form': form 'form': form
} }
try: try:
errors_off = True errors_off = True
@@ -27,48 +34,51 @@ def get_profile_new_route_page_html(request, data):
if 'to_address_point_txt' in data: if 'to_address_point_txt' in data:
del data['to_address_point_txt'] del data['to_address_point_txt']
if 'type_transport' in data:
if data['type_transport'] == 'avia':
transfer_location_choices = (
('airport', _('В аэропорту')),
('city', _('По городу')),
('other', _('По договоренности'))
)
cargo_type_choices = ( # if data['type_transport'] == 'avia':
('cargo', _('Груз')), # transfer_location_choices = (
('parcel', _('Бандероль')), # ('airport', _('В аэропорту')),
('package', _('Посылка')), # ('city', _('По городу')),
('letter', _('Письмо\Документ')) # ('other', _('По договоренности'))
) # )
#
# cargo_type_choices = (
else: # ('cargo', _('Груз')),
transfer_location_choices = ( # ('parcel', _('Бандероль')),
('city', _('По городу')), # ('package', _('Посылка')),
('other', _('По договоренности')) # ('letter', _('Письмо\Документ'))
) # )
#
cargo_type_choices = ( #
('passenger', _('Пассажир')), # else:
('cargo', _('Груз')), # transfer_location_choices = (
('parcel', _('Бандероль')), # ('city', _('По городу')),
('package', _('Посылка')), # ('other', _('По договоренности'))
('letter', _('Письмо\Документ')) # )
) #
# cargo_type_choices = (
# ('passenger', _('Пассажир')),
# ('cargo', _('Груз')),
# ('parcel', _('Бандероль')),
# ('package', _('Посылка')),
# ('letter', _('Письмо\Документ'))
# )
form = RouteForm(data) form = RouteForm(data)
if not form.is_valid(): if not form.is_valid():
pass pass
form = RouteForm(initial=form.cleaned_data) form = RouteForm(initial=form.cleaned_data)
form.fields['from_place'].choices = transfer_location_choices if 'type_transport' in data:
form.fields['to_place'].choices = transfer_location_choices form = routeForm_assign_choices_by_type_transport(form, data['type_transport'])
form.fields['cargo_type'].choices = cargo_type_choices
form.base_fields['from_place'].choices = transfer_location_choices # form.fields['from_place'].choices = transfer_location_choices
form.base_fields['to_place'].choices = transfer_location_choices # form.fields['to_place'].choices = transfer_location_choices
form.base_fields['cargo_type'].choices = cargo_type_choices # form.fields['cargo_type'].choices = cargo_type_choices
#
# form.base_fields['from_place'].choices = transfer_location_choices
# form.base_fields['to_place'].choices = transfer_location_choices
# form.base_fields['cargo_type'].choices = cargo_type_choices
# form = CreateRouteForm(initial=data) # form = CreateRouteForm(initial=data)
@@ -213,7 +223,7 @@ def get_routes_Dict(user=None, data=None):
if key == 'to_el': if key == 'to_el':
to_el = int(val) to_el = int(val)
routes = Route.objects.filter(**kwargs).order_by('departure_DT', 'arrival_DT', '-modifiedDT') routes = Route.objects.filter(**kwargs).order_by('-departure_DT', '-arrival_DT', '-modifiedDT')
routes_count = routes.count() routes_count = routes.count()
if from_el and to_el: if from_el and to_el:

View File

@@ -67,6 +67,8 @@ def edit_route_ajax(request):
route = Route.objects.get(id=data['route_id']) route = Route.objects.get(id=data['route_id'])
form = RouteForm(instance=route) form = RouteForm(instance=route)
form = routeForm_assign_choices_by_type_transport(form, route.type_transport)
route_address_points_Dict = route.get_address_points() route_address_points_Dict = route.get_address_points()
form.initial.update({ form.initial.update({
'from_address_point_txt': route_address_points_Dict['from_address_point_txt'], 'from_address_point_txt': route_address_points_Dict['from_address_point_txt'],

View File

@@ -0,0 +1,7 @@
from rest_framework import serializers
class SubscribersSerializer(serializers.Serializer):
email = serializers.EmailField(error_messages={'invalid': 'Invalid email'})
email_notification = serializers.BooleanField()
auto_subscribe = serializers.BooleanField()

9
SubscribesApp/urls.py Normal file
View File

@@ -0,0 +1,9 @@
from django.urls import path
from SubscribesApp.views import SubscribersView
urlpatterns = [
path('auto-subscribe/', SubscribersView.as_view(), name='auto_subscribe'),
]

View File

@@ -1,3 +1,43 @@
from django.shortcuts import render from django.contrib.auth.models import User
from django.http import JsonResponse
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
# Create your views here. from SubscribesApp.models import SubscribeForUser
from SubscribesApp.serializers import SubscribersSerializer
class SubscribersView(APIView):
# permission_classes = [IsAuthenticated]
def post(self, request):
serializer = SubscribersSerializer(data=request.data)
if serializer.is_valid():
validated_data = serializer.validated_data
email = validated_data['email']
email_notification = validated_data['email_notification']
auto_subscribe = validated_data['auto_subscribe']
user = User.objects.filter(email=email)
if user:
subscribe_for_user = SubscribeForUser.objects.filter(user_id=user[0].id)
if email_notification:
subscribe_for_user.update(receive_finish_subscribe_msg=True)
else:
subscribe_for_user.update(receive_finish_subscribe_msg=False)
if auto_subscribe:
subscribe_for_user.update(auto_continue=True)
else:
subscribe_for_user.update(auto_continue=False)
return JsonResponse({"message": "Subscriptions updated successfully"}, status=status.HTTP_200_OK)
else:
return JsonResponse({"message": "User not found"}, status=status.HTTP_404_NOT_FOUND)
else:
return JsonResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

27
TWB/celery.py Executable file
View File

@@ -0,0 +1,27 @@
from __future__ import absolute_import
import os
from celery import Celery
from celery.schedules import crontab
from django.conf import settings
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "TWB.settings")
app = Celery('bo', include=['TWB.tasks'])
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
app.conf.beat_schedule = {
'update-currency-rates': {
'task': 'TWB.tasks.check_auto_subscribe',
'schedule': crontab(minute=0, hour='*/1'),
},
'subscription_expiration_check': {
'task': 'TWB.tasks.subscription_expiration_check',
'schedule': crontab(hour=0, minute=0),
# 'schedule': crontab(minute='*', hour='*'),
},
}
app.conf.broker_url = settings.CELERY_BROKER_URL

View File

@@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/4.2/ref/settings/
""" """
from pathlib import Path from pathlib import Path
from decouple import config
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
@@ -45,7 +46,10 @@ ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email' ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_VERIFICATION = 'optional' ACCOUNT_EMAIL_VERIFICATION = 'optional'
LOGIN_REDIRECT_URL = '/profile/page/dashboard/' LOGIN_REDIRECT_URL = '/profile/page/dashboard/'
LOGIN_URL = '/profile/login/'
LOGOUT_REDIRECT_URL = '/profile/login/' LOGOUT_REDIRECT_URL = '/profile/login/'
ACCOUNT_SIGNUP_REDIRECT_URL = '/profile/page/dashboard/' ACCOUNT_SIGNUP_REDIRECT_URL = '/profile/page/dashboard/'
ACCOUNT_LOGOUT_ON_GET = True ACCOUNT_LOGOUT_ON_GET = True
# SOCIALACCOUNT_ADAPTER = 'GeneralApp.allauth_funcs.MyAccountAdapter' # SOCIALACCOUNT_ADAPTER = 'GeneralApp.allauth_funcs.MyAccountAdapter'
@@ -57,7 +61,6 @@ AUTHENTICATION_BACKENDS = [
] ]
SOCIALACCOUNT_PROVIDERS = { SOCIALACCOUNT_PROVIDERS = {
'google': { 'google': {
'SCOPE': [ 'SCOPE': [
@@ -123,6 +126,8 @@ MIDDLEWARE = [
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'AuthApp.middleware.ResponseInterceptionMiddleware', 'AuthApp.middleware.ResponseInterceptionMiddleware',
'TWB.tz_middelware.TimezoneMiddleware',
# 'tz_detect.middleware.TimezoneMiddleware',
"allauth.account.middleware.AccountMiddleware", "allauth.account.middleware.AccountMiddleware",
] ]
@@ -167,11 +172,8 @@ CHANNEL_LAYERS = {
} }
POSTGRES_DB = config('POSTGRES_DB')
POSTGRES_USER = config('POSTGRES_USER')
# Database # Database
@@ -180,8 +182,8 @@ CHANNEL_LAYERS = {
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2', 'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'twbDB', 'NAME': POSTGRES_DB,
'USER': 'test_user', 'USER': POSTGRES_USER,
'PASSWORD': 'test_db_pass', 'PASSWORD': 'test_db_pass',
'HOST': '127.0.0.1', 'HOST': '127.0.0.1',
'PORT': '5432', 'PORT': '5432',
@@ -267,6 +269,7 @@ django.conf.locale.LANG_INFO = LANG_INFO
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
DATA_UPLOAD_MAX_MEMORY_SIZE = 4145728
CKEDITOR_BASEPATH = "/static/ckeditor/ckeditor/" CKEDITOR_BASEPATH = "/static/ckeditor/ckeditor/"
CKEDITOR_UPLOAD_PATH = "uploads/" CKEDITOR_UPLOAD_PATH = "uploads/"
@@ -330,6 +333,16 @@ CKEDITOR_CONFIGS = {
} }
} }
CELERY_BROKER_URL = config('CELERY_BROKER_URL')
CELERY_RESULT_BACKEND = config('CELERY_RESULT_BACKEND')
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = config('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')
# CKEDITOR_OPTIONS = { # CKEDITOR_OPTIONS = {
# 'height': 291, # 'height': 291,

40
TWB/tasks.py Normal file
View File

@@ -0,0 +1,40 @@
from datetime import datetime, timedelta, timezone
from SubscribesApp.models import SubscribeForUser
from TWB import settings
from TWB.celery import app
from django.core.mail import send_mail
@app.task
def check_auto_subscribe():
current_time = datetime.now()
subscribes = SubscribeForUser.objects.filter(auto_continue=True)
if subscribes:
for subscribe in subscribes:
if subscribe.paid_period_to_DT and subscribe.paid_period_to_DT <= current_time + timedelta(hours=1):
user_email = subscribe.user.email
subject = 'Подписка продлена!'
message = 'Ваша подписка успешно продлена!'
send_mail(subject, message, settings.EMAIL_HOST_USER, [user_email], fail_silently=False)
else:
print('Нету подписок')
@app.task
def subscription_expiration_check():
current_time = datetime.now()
subscribes = SubscribeForUser.objects.filter(paid_period_to_DT__gte=current_time)
if subscribes:
for subscribe in subscribes:
expiration_date = subscribe.paid_period_to_DT
remaining_days = (expiration_date - current_time).days
if remaining_days <= 7:
message = f'Ваша подписка заканчивается через {remaining_days} дня. Пожалуйста, продлите её.'
user_email = subscribe.user.email
subject = 'Подписка истекает!'
send_mail(subject, message, settings.EMAIL_HOST_USER, [user_email], fail_silently=False)
else:
print('Нету подписок')

22
TWB/tz_middelware.py Normal file
View File

@@ -0,0 +1,22 @@
import zoneinfo
from django.utils import timezone
from django.shortcuts import render
class TimezoneMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
tz = request.COOKIES.get("user_tz")
if tz:
if request.user.is_authenticated:
if not 'user_timezone' in request.user.user_profile.json_data or request.user.user_profile.json_data['user_timezone'] != tz:
request.user.user_profile.json_data['user_timezone'] = tz
request.user.user_profile.save(update_fields=['json_data'])
msg = f'user={str(request.user.id)} tz={str(tz)}'
print(msg)
timezone.activate(zoneinfo.ZoneInfo(tz))
else:
timezone.activate(zoneinfo.ZoneInfo("UTC"))
return self.get_response(request)

View File

@@ -1,4 +1,3 @@
from django.contrib import admin 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
@@ -9,11 +8,13 @@ from AuthApp.views import login_View
handler404 = Page404 handler404 = Page404
urlpatterns = [ urlpatterns = [
# 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('tz_detect/', include('tz_detect.urls')),
path('accounts/signup/', login_View, name='signup'), path('accounts/signup/', login_View, name='signup'),
path('accounts/login/cancelled/', login_View),
path('accounts/', include('allauth.urls')), path('accounts/', include('allauth.urls')),
path('accounts/', include('allauth.socialaccount.urls')), path('accounts/', include('allauth.socialaccount.urls')),
@@ -36,7 +37,9 @@ urlpatterns = [
path('test_404', Page404, name='page_404'), path('test_404', Page404, name='page_404'),
path('', include('PushMessages.urls')) path('', include('PushMessages.urls')),
path('', include('SubscribesApp.urls')),
] ]
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns

8
env.sample Normal file
View File

@@ -0,0 +1,8 @@
EMAIL_HOST_USER=
EMAIL_HOST_PASSWORD=
POSTGRES_DB=
POSTGRES_USER=
CELERY_BROKER_URL=
CELERY_RESULT_BACKEND=

View File

@@ -580,9 +580,9 @@ msgstr ""
#: .\templates\blocks\static_pages_blocks\b_partners.html:18 #: .\templates\blocks\static_pages_blocks\b_partners.html:18
msgid "" msgid ""
"Вы можете разместить объявление о перевозке посылки и перевозчики со всего " "Вы можете разместить объявление о перевозке посылки и перевозчики со всего "
"мира откликнуться на ваше объявление или воспользовавшись поиском на сайте " "мира откликнутся на ваше объявление или воспользовавшись поиском на сайте "
"найти перевозчика, который будет готов взять Вашу посылку и доставить в " "найти перевозчика, который будет готов взять Вашу посылку и доставить в "
"указанное место авто- или авива транспортом." "указанное место наземным или авиатранспортом."
msgstr "" msgstr ""
#: .\templates\blocks\static_pages_blocks\b_about_service.html:22 #: .\templates\blocks\static_pages_blocks\b_about_service.html:22

View File

@@ -2,7 +2,6 @@ Django==4.2.2
django-ckeditor==6.5.1 django-ckeditor==6.5.1
psycopg2-binary==2.9.6 psycopg2-binary==2.9.6
requests requests
Pillow==9.5.0
django-modeltranslation==0.18.10 django-modeltranslation==0.18.10
overpass overpass
geopy geopy
@@ -12,4 +11,7 @@ channels-redis==4.1.0
django-colorfield django-colorfield
django-webpush==0.3.5 django-webpush==0.3.5
django-allauth==0.60.0 django-allauth==0.60.0
pytz==2024.1
celery==5.3.6
djangorestframework==3.14.0
python-decouple==3.8

View File

@@ -116,6 +116,11 @@
} }
@media (max-width: 1180px){ @media (max-width: 1180px){
.input_list.find_route{
left: unset;
width: 70%;
}
.handler_curtain_left{ .handler_curtain_left{
display: block; display: block;
} }
@@ -591,6 +596,7 @@
section.register>form{ section.register>form{
display: block; display: block;
width: unset; width: unset;
margin-right: 10px;
} }
.inputs{ .inputs{
@@ -964,10 +970,10 @@
.left-part-block-enter-message{ .left-part-block-enter-message{
width: 70%; width: calc(70% - 74px);
} }
.right-part-block-enter-message{ .right-part-block-enter-message{
width: 30%; width: 74px;
} }
.container-message_support_chat{ .container-message_support_chat{
width: 70%; width: 70%;
@@ -1628,6 +1634,25 @@
} }
@media (max-width: 800px) {
.marker_messages_mobile{
position: absolute;
top: 0;
right: 0;
border-radius: 100%;
background: #ff0000;
height: 14px;
width: 15px;
}
.marker_messages_mobile.hide{
display: none;
}
.marker_messages_mobile.show{
display: block;
}
}
@media (max-width: 828px){ @media (max-width: 828px){
/*.to_address_point_txt.find_route {*/ /*.to_address_point_txt.find_route {*/
/*width: 54.6%;*/ /*width: 54.6%;*/
@@ -1688,6 +1713,17 @@
} }
@media (max-width: 699px){ @media (max-width: 699px){
.block-chat.support {
/*height: calc(100vh - 190px);*/
/*1. 100svh 2. 45px - header 3. name_ticket 4. just padding */
height: calc(100svh - 45px - 40px - 50px);
}
.block-chat{
/*height: calc(88vh - 50px);*/
/*1. 100svh 2. 45px - header 3. just padding */
height: calc(100svh - 45px - 50px);
}
.block_overlay.show{ .block_overlay.show{
display: block; display: block;
} }
@@ -1730,6 +1766,28 @@
background: #FFF; background: #FFF;
} }
.menu_buttons.right.open .menu_profile{
padding-top: unset;
}
.menu_profile>div{
height: 30px;
margin-top: 3px;
margin-bottom: 8px;
}
#customer>.text_btn_profile, #mover>.text_btn_profile{
top: 8px;
}
/*.text_btn_profile{*/
/* top: 14px;*/
/*}*/
.menu_profile > .subscribe_type_txt{
margin-bottom: 12px;
padding-top: 12px;
}
.menu_profile>div>img.svg{
margin-top: 4px;
}
.info_profile{ .info_profile{
width: 100%; width: 100%;
} }
@@ -1788,6 +1846,8 @@
} }
@media (max-width: 575px){ @media (max-width: 575px){
.phones_carrier{ .phones_carrier{
display: block; display: block;
} }
@@ -1959,7 +2019,7 @@
.container_inp_w_abr { .container_inp_w_abr {
width: 99%; width: 100%;
} }
.another_subscribe{ .another_subscribe{
@@ -1973,6 +2033,10 @@
@media (max-width: 440px){ @media (max-width: 440px){
.card_title_3{
margin: 20px 5px 0 20px;
}
.f-r{ .f-r{
text-align: left; text-align: left;
} }
@@ -2040,6 +2104,13 @@
} }
@media (max-width: 360px){ @media (max-width: 360px){
#customer>.text_btn_profile, #mover>.text_btn_profile{
width: 53%;
}
.loader_chat_f_sw_chats.show { .loader_chat_f_sw_chats.show {
display: block; display: block;
height: 100px; height: 100px;

View File

@@ -575,12 +575,12 @@
} }
.left-part-block-enter-message{ .left-part-block-enter-message{
width: 80%; width: calc(80% - 74px);
float: left; float: left;
} }
.right-part-block-enter-message{ .right-part-block-enter-message{
width: 20%; width: 74px;
float: right; float: right;
padding-top: 11px; padding-top: 11px;
text-align: right; text-align: right;
@@ -1079,10 +1079,11 @@
.input_list.find_route{ .input_list.find_route{
width: calc(100% - 3px); width: 90%;
/*display: block;*/ /*display: block;*/
border-radius: 0 0 10px 10px; border-radius: 0 0 10px 10px;
top: 53px; top: 62px;
left: 9px;
z-index: 10000; z-index: 10000;
} }
@@ -1211,9 +1212,9 @@
margin: 0; margin: 0;
} }
.cont-el-form-search-carrier.last > label{ /*.cont-el-form-search-carrier.last > label{*/
opacity: 0; /* opacity: 0;*/
} /*}*/
.block-filters-find-route { .block-filters-find-route {
@@ -2130,7 +2131,7 @@ a.open_inf_carrier{
.button_profile_header{ .button_profile_header{
height: 50px; height: 50px;
width: 150px; width: 155px;
background: #FF613A; background: #FF613A;
color: #FFF; color: #FFF;
/* Heading 5 */ /* Heading 5 */
@@ -2898,7 +2899,7 @@ a.open_inf_carrier{
} }
.text_in_btn_a_anchor{ .text_in_btn_a_anchor{
padding-top: 20px; padding-top: 17px;
} }
.anchor{ .anchor{

View File

@@ -23,24 +23,28 @@
src: url("/static/fonts/inter/Inter-Regular.ttf") format('truetype'); src: url("/static/fonts/inter/Inter-Regular.ttf") format('truetype');
font-weight: 400; font-weight: 400;
font-style: normal; font-style: normal;
font-display: swap;
} }
@font-face{ @font-face{
font-family: 'Inter'; font-family: 'Inter';
src: url("/static/fonts/inter/Inter-Medium.ttf") format('truetype') ; src: url("/static/fonts/inter/Inter-Medium.ttf") format('truetype') ;
font-weight: 500; font-weight: 500;
font-style: normal; font-style: normal;
font-display: swap;
} }
@font-face{ @font-face{
font-family: 'Inter'; font-family: 'Inter';
src: url("/static/fonts/inter/Inter-SemiBold.ttf") format('truetype') ; src: url("/static/fonts/inter/Inter-SemiBold.ttf") format('truetype') ;
font-weight: 600; font-weight: 600;
font-style: normal; font-style: normal;
font-display: swap;
} }
@font-face{ @font-face{
font-family: 'Inter'; font-family: 'Inter';
src: url("/static/fonts/inter/Inter-Bold.ttf") format('truetype') ; src: url("/static/fonts/inter/Inter-Bold.ttf") format('truetype') ;
font-weight: 700; font-weight: 700;
font-style: normal; font-style: normal;
font-display: swap;
} }
/* Links */ /* Links */
@@ -136,8 +140,15 @@ legend {
} }
html, body{ html, body{
height: 100%; /*height: 100%;*/
scroll-behavior: smooth; scroll-behavior: smooth;
/*boris changed height*/
height: 100vh;
height: -webkit-fill-available;
height: fill-available;
max-height: fill-available;
max-height: -webkit-fill-available;
/* end*/
} }
.wrapper_content { .wrapper_content {
@@ -260,11 +271,15 @@ section.register>h1 {
border-radius: 10px; border-radius: 10px;
border: 1px solid black; border: 1px solid black;
} }
.footer_input_wrap.hide{
display: none;
}
.footer_input_wrap { .footer_input_wrap {
display: flex; display: flex;
color: #FF613A;
} }
.footer_input::placeholder { .footer_input::placeholder {
color: rgba(39, 36, 36, 0.60); color: rgba(39, 36, 36, 0.60);
font-size: 16px; font-size: 16px;
@@ -1736,11 +1751,13 @@ div.departure_arrival>div>input{
.input_list::-webkit-scrollbar { .input_list::-webkit-scrollbar {
width: 7px; width: 10px;
} }
.input_list::-webkit-scrollbar-thumb { .input_list::-webkit-scrollbar-thumb {
background-color: #FF613A; background-color: #FF613A;
border-radius: 20px; border-radius: 20px;
border: 3px solid white;
} }
@@ -2384,7 +2401,7 @@ figure{
.bottom_block_static>#box2 { .bottom_block_static>#box2 {
/* Положение верхнего левого изображения */ /* Положение верхнего левого изображения */
top: 16%; top: 0%;
left: -2%; left: -2%;
transform: scale(-1, 1); transform: scale(-1, 1);
@@ -2402,7 +2419,7 @@ figure{
.bottom_block_static>#box4 { .bottom_block_static>#box4 {
/* Положение верхнего правого изображения */ /* Положение верхнего правого изображения */
top: 18%; top: 9%;
right: -1%; right: -1%;
} }

View File

@@ -3,6 +3,8 @@ function SendLoginForm(el){
event.preventDefault() event.preventDefault()
let form = el.form; let form = el.form;
let formData = new FormData(form); let formData = new FormData(form);
let msr = sessionStorage.getItem('mailingSubscribeRequired')
formData.set('mailingSubscribeRequired',msr)
@@ -18,7 +20,10 @@ function SendLoginForm(el){
data: formData, data: formData,
success: function(data){ success: function(data){
location.href = `/profile/page/dashboard/?mobile=${getInfoAboutUser() === 'mobile'}` location.href = `/profile/page/dashboard/`
window.sessionStorage.removeItem('mailingSubscribeRequired')
window.sessionStorage.removeItem('email')

View File

@@ -19,7 +19,7 @@ function update_chat_html (data,msg_cont) {
function update_list_w_users (data,old_item_tab_user,el_tab) { function update_list_w_users (data,old_item_tab_user,el_tab) {
let list_of_users = document.querySelector(".block-list-of-users") let list_of_users = document.querySelector(".container_block_list_of_users")
if (list_of_users) { if (list_of_users) {
if (data.users_list_html){ if (data.users_list_html){

View File

@@ -69,7 +69,7 @@ function clear_messenger (data) {
let dataset_cont_mes = container_messenger.dataset let dataset_cont_mes = container_messenger.dataset
if (dataset_cont_mes){ if (dataset_cont_mes){
let ticket_id = dataset_cont_mes["ticketId"] let ticket_id = dataset_cont_mes["ticketId"]
if (ticket_id !== ""){s if (ticket_id !== ""){
let ticket = document.querySelector(`[data-cur-receiver-item="${ticket_id}"]`) let ticket = document.querySelector(`[data-cur-receiver-item="${ticket_id}"]`)
if (ticket === null){ if (ticket === null){
document.querySelector(".block-chat").style.display = "none" document.querySelector(".block-chat").style.display = "none"

View File

@@ -39,6 +39,16 @@ function wsReceiveData (e) {
console.log(data) console.log(data)
} else if (data.type === "update_chat") { } else if (data.type === "update_chat") {
let msg_cont = document.querySelector(".container-messages") let msg_cont = document.querySelector(".container-messages")
if (getInfoAboutUser('screen_width') < 800){
if (!window.location.href.includes("chat") && !window.location.href.includes("support")){
let marker_new_messages = document.querySelector(".marker_messages_mobile");
if (marker_new_messages.classList.contains('hide')){
marker_new_messages.classList.add('show')
marker_new_messages.classList.remove('hide')
}
setCokie(365,'twb_new_messages',true)
}
}
update_chat_html(data,msg_cont) update_chat_html(data,msg_cont)
// document.querySelector(".tab_user_messanger.select").scrollIntoView({behavior: "smooth",block:'end',inline:'end'}); // document.querySelector(".tab_user_messanger.select").scrollIntoView({behavior: "smooth",block:'end',inline:'end'});
@@ -59,6 +69,8 @@ function wsReceiveData (e) {
if (user_id) { if (user_id) {
if (ticket_maneger.toString() !== user_id) { if (ticket_maneger.toString() !== user_id) {
clear_messenger() clear_messenger()
} else {
} }
} }
else { else {
@@ -97,14 +109,25 @@ function wsReceiveData (e) {
} }
// } // }
// if // if
if (window.location.href.includes("chat")){
update_list_w_users(data,old_item_tab_user,el_tab) update_list_w_users(data,old_item_tab_user,el_tab)
}
} else if (data.type === "update_support_chat"){ } else if (data.type === "update_support_chat"){
update_support_chat_func(data,msg_cont) update_support_chat_func(data,msg_cont)
} }
if (data.unread_msgs_count > 0){ if (data.unread_msgs_count > 0){
if (getInfoAboutUser('screen_width') < 800){
if (!window.location.href.includes("chat") && !window.location.href.includes("support")){
let marker_new_messages = document.querySelector(".marker_messages_mobile");
if (marker_new_messages.classList.contains('hide')){
marker_new_messages.classList.add('show')
marker_new_messages.classList.remove('hide')
}
setCokie(365,'twb_new_messages',true)
}
}
update_count_unread_messages(data) update_count_unread_messages(data)
} }
if (data.required_beep === true) { if (data.required_beep === true) {

View File

@@ -1,4 +1,5 @@
$(document).ready(function (){ $(document).ready(function (){
hide_or_show_new_messages_marker()
checkStateCookie() checkStateCookie()
}) })
@@ -11,8 +12,64 @@ window.onload = function (){
middleWareJS() middleWareJS()
openOrCloseCurtainSupportChat() openOrCloseCurtainSupportChat()
openOverlayOrClose() openOverlayOrClose()
goToChatIfChat()
// let body = document.querySelector("body")
// const viewPortH = body.getBoundingClientRect().height;
// const windowH = window.innerHeight;
// const browserUiBarsH = viewPortH - windowH;
// body.style.height = `calc(100vh - ${browserUiBarsH}px)`;
// let height = window.innerHeight
// document.querySelector('body').style.maxHeight = height + 'px'
// document.querySelector('body').style.height = height + 'px'
if (window.location.href.includes('profile') && !window.location.href.includes('login') && !window.location.href.includes('registration')){
let user_type = getInfoAboutUser()
if (user_type === 'mobile') {
open_curtain_w_btn_profile()
} else {
if (!window.location.href.includes('profile')){
open_curtain_w_btn_profile()
}
}
if (window.location.href.includes("profile")){
setStandartSettingsToBlockOverlay()
}
// if (window.location.href.includes("profile")){
// selectTabProfileIfHisNotSelected(url)
// }
let chats = document.querySelector(`[data-ajax-url='chats']`)
if (chats){
deleteMarkerMessages()
}
}
}
function hide_or_show_new_messages_marker () {
if (getInfoAboutUser('screen_width') < 800){
if (window.location.href.includes("chat") || window.location.href.includes("support")){
setCokie(365,'twb_new_messages','false')
}
}
} }
// //
function goToChatIfChat () {
if (document.querySelector('.block-chat')){
let scroll_el = document.querySelector('.block-chat')
if (document.querySelector(".name_ticket")){
scroll_el = document.querySelector(".name_ticket")
}
let top = scroll_el.offsetTop
window.scrollTo({top:top})
document.addEventListener('focusout', function(e,scroll_el) {
window.scrollTo(scroll_el, 0)
});
}
}
function middleWareJS(){ function middleWareJS(){
let footer = document.querySelector("footer") let footer = document.querySelector("footer")
@@ -85,7 +142,7 @@ function getTypeOfData (data) {
} }
function getInfoAboutUser (){ function getInfoAboutUser (screen_width){
let user_type = '' let user_type = ''
if (screen.width <= 700){ if (screen.width <= 700){
user_type = 'mobile' user_type = 'mobile'
@@ -94,8 +151,12 @@ function getInfoAboutUser (){
} else if (screen.width > 700 && screen.width <= 1180) { } else if (screen.width > 700 && screen.width <= 1180) {
user_type = 'laptop' user_type = 'laptop'
} }
if (screen_width){
return screen.width
} else {
return user_type return user_type
} }
}
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
let img = document.getElementById('dropbtn_lang') let img = document.getElementById('dropbtn_lang')
@@ -111,17 +172,28 @@ document.addEventListener('DOMContentLoaded', function() {
img.style.backgroundPosition = "center" img.style.backgroundPosition = "center"
// img.style.backgroundSize = '50%' // img.style.backgroundSize = '50%'
} }
let login_email = document.getElementById('login_email_input')
let registration_email = document.getElementById('registration_email_input')
if(login_email){
login_email.value = sessionStorage.getItem('email')
}else if(registration_email){
registration_email.value = sessionStorage.getItem('email')
}
}); });
window.addEventListener('scroll', () => { // window.addEventListener('scroll', () => {
// let headerBG = document.getElementById('header_bg') // // let headerBG = document.getElementById('header_bg')
// // //
// headerBG.style.backgroundColor = 'rgb(248 248 248 / 90%)' // // headerBG.style.backgroundColor = 'rgb(248 248 248 / 90%)'
// headerBG.style.padding = '20px 40px' // // headerBG.style.padding = '20px 40px'
// headerBG.style.paddingBottom = 'padding: 10px 40px 10px 40px' // // headerBG.style.paddingBottom = 'padding: 10px 40px 10px 40px'
// headerBG.style.paddingRight = 'padding: 10px 40px 10px 40px' // // headerBG.style.paddingRight = 'padding: 10px 40px 10px 40px'
// headerBG.style.paddingLeft = 'padding: 10px 40px 10px 40px' // // headerBG.style.paddingLeft = 'padding: 10px 40px 10px 40px'
}) // })
// Действия при изменении URL // Действия при изменении URL
@@ -155,6 +227,23 @@ function checkStateCookie () {
if (!window.document.cookie.includes("allow_cookie=true")){ if (!window.document.cookie.includes("allow_cookie=true")){
document.querySelector(".cookie_block").classList.add("show") document.querySelector(".cookie_block").classList.add("show")
} }
if (window.document.cookie.includes("twb_new_messages=true")){
if (getInfoAboutUser('screen_width') < 800) {
let marker_new_messages = document.querySelector(".marker_messages_mobile");
if (marker_new_messages.classList.contains('hide')) {
marker_new_messages.classList.remove('hide')
marker_new_messages.classList.add('show')
}
}
} else if (window.document.cookie.includes("twb_new_messages=false")){
if (getInfoAboutUser('screen_width') < 800) {
let marker_new_messages = document.querySelector(".marker_messages_mobile");
if (marker_new_messages.classList.contains('show')) {
marker_new_messages.classList.add('hide')
marker_new_messages.classList.remove('show')
}
}
}
} }
function getCsrfCookie () { function getCsrfCookie () {
@@ -169,11 +258,15 @@ function getCsrfCookie () {
return csrf return csrf
} }
function setCokie () { function setCokie (days,name,val) {
let date = new Date(); let date = new Date();
let days = 182; // let days = 182;
date.setTime(+ date + (days * 86400000)); date.setTime(+ date + (days * 86400000));
window.document.cookie = "allow_cookie=true" + "; expires=" + date.toGMTString() + "; path=/"; window.document.cookie = `${name}=${val}` + "; expires=" + date.toGMTString() + "; path=/";
document.querySelector(".cookie_block").classList.remove("show") document.querySelector(".cookie_block").classList.remove("show")
return value; // return value;
}
function getInCookieTime (time) {
return time * 24 * 60 * 60
} }

View File

@@ -2,6 +2,8 @@ function SendRegistrationForm(el){
event.preventDefault() event.preventDefault()
let form = el.form; let form = el.form;
let formData = new FormData(form); let formData = new FormData(form);
let msr = sessionStorage.getItem('mailingSubscribeRequired')
formData.set('mailingSubscribeRequired',msr)
$.ajax({ $.ajax({
headers: { "X-CSRFToken": $('input[name=csrfmiddlewaretoken]').val() }, headers: { "X-CSRFToken": $('input[name=csrfmiddlewaretoken]').val() },
@@ -15,7 +17,9 @@ function SendRegistrationForm(el){
data: formData, data: formData,
success: function(data){ success: function(data){
location.href = `/profile/page/dashboard/?mobile=${getInfoAboutUser() === 'mobile'}` location.href = `/profile/page/dashboard/`
window.sessionStorage.removeItem('mailingSubscribeRequired')
window.sessionStorage.removeItem('email')
}, },
error: function (data, exception){ error: function (data, exception){
document.querySelector(".register").innerHTML = data.responseJSON.html document.querySelector(".register").innerHTML = data.responseJSON.html

View File

@@ -580,6 +580,8 @@ function sendRoute(el, routeID = null){
// document.querySelector(".tab_user_messanger.select").scrollIntoView({behavior: "smooth",block:'nearest',inline:'nearest'}); // document.querySelector(".tab_user_messanger.select").scrollIntoView({behavior: "smooth",block:'nearest',inline:'nearest'});
@@ -795,6 +797,11 @@ function editRoute(id) {
if(data.html){ if(data.html){
let changeTextButton = document.getElementById('registration') let changeTextButton = document.getElementById('registration')
changeTextButton.innerText = 'Сохранить изменения' changeTextButton.innerText = 'Сохранить изменения'
window.scrollTo({
top: 0,
left: 0,
behavior: "smooth"
});
} }
init_departure_DT() init_departure_DT()
@@ -981,6 +988,107 @@ function RequestCommercialOffer (el){
}
function subscribeNewsletter (el){
el.style.background = '#FF613A url("/static/img/svg/loader_white.svg") no-repeat center';
el.style.contentVisibility = 'hidden';
event.preventDefault()
let disable_btn_f = document.getElementById('footer_input_button');
disable_btn_f.setAttribute('disabled', true);
let form = el.form;
let formData = new FormData(form);
let form_name = form.dataset['name']
formData.set('form_name',form_name)
$.ajax({
headers: { "X-CSRFToken": $('input[name=csrfmiddlewaretoken]').val() },
url: '/user_account/mailing_subscribe/',
type: "POST",
// async: true,
cache: false,
processData: false,
contentType: false,
// enctype: 'json',
data: formData,
success: function(data){
// el.style.background = '#FF613A';
el.removeAttribute('style')
if(data.status === 'sended' && data.del_form === true){
document.querySelector('.footer_input_wrap').innerHTML = data.html;
} else if(data.redirect_url){
window.sessionStorage.setItem('email', data.email)
window.sessionStorage.setItem('mailingSubscribeRequired','true')
window.location.replace(data.redirect_url)
}
if(el.id !== 'footer_input_button'){
let insert_text = document.querySelector(".clear_form")
if(insert_text){
$(data.html).insertBefore(insert_text)
}
let insert_text_2 = document.querySelector(".commercial_offer")
if(insert_text_2){
$(data.html).insertBefore(insert_text_2)
}
} else {
let disable_btn_f = document.getElementById('footer_input_button');
if(disable_btn_f){
disable_btn_f.removeAttribute('disabled');
}
let clear_footer_form = document.getElementById('clear_input');
clear_footer_form.reset();
let hide_error_msg = document.getElementById('error_footer').classList.add('hide')
}
},
error: function (data, exception){
// document.querySelector(".login").innerHTML = data.responseJSON.html
if(el.id !== 'footer_input_button'){
let feedback_form = document.querySelector('.feedback_form')
if(feedback_form){
feedback_form.innerHTML = data.responseJSON.html;
// let incorrect_block = document.querySelectorAll('.inputs_l')
}
let commercial_offer = document.querySelector('.commercial_offer')
if(commercial_offer){
commercial_offer.innerHTML = data.responseJSON.html;
}
} else {
let footer_form = document.querySelector('.insert_form').innerHTML = data.responseJSON.html;
// $(data.responseJSON.html).insertBefore(footer_form)
}
// document.querySelector(".info_profile").innerHTML = data.html;
}
});
} }
function hideErrors(el) { function hideErrors(el) {

View File

@@ -84,6 +84,18 @@ function select_tab_profile (el,url,owner_type=null) {
selectTabProfileIfHisNotSelected(url) selectTabProfileIfHisNotSelected(url)
} }
deleteMarkerMessages(el) deleteMarkerMessages(el)
checkStatesAfterTransitionToAnotherTabProfile()
goToChatIfChat()
if (window.location.href.includes("chat") || window.location.href.includes("support")) {
if (getInfoAboutUser('screen_width') < 800) {
let marker_new_messages = document.querySelector(".marker_messages_mobile");
if (marker_new_messages.classList.contains('show')) {
marker_new_messages.classList.remove('show')
marker_new_messages.classList.add('hide')
}
}
}
setCokie(365,'twb_new_messages','false')
}, },
error: function (data){ error: function (data){
console.log(data) console.log(data)
@@ -92,6 +104,28 @@ function select_tab_profile (el,url,owner_type=null) {
}); });
} }
function checkStatesAfterTransitionToAnotherTabProfile () {
// check which page if profile - do
if (window.location.href.includes('profile')){
// if curtain open we need to close, so we'il see content without curtain
if (document.querySelector(".menu_buttons.curtain.right.open")){
open_curtain_w_btn_profile()
}
// if overlay open we need to close, so we'il see content without overlay
if (document.querySelector('.block_overlay.show')){
setStandartSettingsToBlockOverlay()
}
// if page === chat - do or if page === support
if (window.location.href.includes("page/chat/") || window.location.href.includes("page/support/")){
// if curtain with contacts or curtain with clients close we need to open it,
// but if user === not admin, and user in page support we didn't need to do anything
if (document.querySelector(".menu_buttons.curtain.left.close")){
open_curtain_w_contacts()
}
}
}
}
function deleteMarkerMessages (el) { function deleteMarkerMessages (el) {
let marker = document.querySelectorAll(".icon_unread_messages") let marker = document.querySelectorAll(".icon_unread_messages")
if (marker.length > 0) { if (marker.length > 0) {
@@ -101,7 +135,6 @@ function deleteMarkerMessages (el) {
} }
} }
} }
function selectTabProfileIfHisNotSelected (url) { function selectTabProfileIfHisNotSelected (url) {
if (url !== 'new_route_view') { if (url !== 'new_route_view') {
let el_f_select = document.querySelector(`[data-ajax-url=${url}]`) let el_f_select = document.querySelector(`[data-ajax-url=${url}]`)
@@ -446,8 +479,8 @@ async function upload_photo_f_profile (el,files) {
}, },
error: function (data){ error: function (data){
document.querySelector(".avatar_user_profile").innerHTML = data.responseJSON.html; alert(data.responseJSON.error);
el.value = ''
} }
}); });
// } // }
@@ -511,9 +544,9 @@ function selectedUserMessenger (ticket_id=null,user_id=null,el){
url = 'show_chat_w_user/' url = 'show_chat_w_user/'
} }
let user_type = getInfoAboutUser() let user_type = getInfoAboutUser()
if (user_type === 'mobile' || user_type === 'laptop') { // if (user_type === 'mobile' || user_type === 'laptop') {
open_curtain_w_contacts() // open_curtain_w_contacts()
} // }
data['mobile'] = getInfoAboutUser() === 'mobile' || getInfoAboutUser() === 'laptop' data['mobile'] = getInfoAboutUser() === 'mobile' || getInfoAboutUser() === 'laptop'
$.ajax({ $.ajax({
headers: { "X-CSRFToken": $('input[name=csrfmiddlewaretoken]').val() }, headers: { "X-CSRFToken": $('input[name=csrfmiddlewaretoken]').val() },
@@ -533,13 +566,18 @@ function selectedUserMessenger (ticket_id=null,user_id=null,el){
// let left_curtain = document.querySelector('.curtain.left') // let left_curtain = document.querySelector('.curtain.left')
document.querySelector(".info_profile").innerHTML = data.html; document.querySelector(".info_profile").innerHTML = data.html;
document.querySelector(".enter-message-inp").focus() document.querySelector(".enter-message-inp").focus()
goToChatIfChat()
// document.querySelector(".tab_user_messanger.select").scrollIntoView({behavior: "smooth",block:'center',inline: 'start'}); // document.querySelector(".tab_user_messanger.select").scrollIntoView({behavior: "smooth",block:'center',inline: 'start'});
if (document.querySelector(".menu_buttons.curtain.left.open")){ if (document.querySelector(".menu_buttons.curtain.left.open")){
let top = document.querySelector(".tab_user_messanger.select").offsetTop let top = document.querySelector(".tab_user_messanger.select").offsetTop
document.querySelector(".menu_buttons.curtain.left.open").scrollTo({top:top}) document.querySelector(".menu_buttons.curtain.left.open").scrollTo({top:top})
} }
// second time beacause we need to close curtain
// if (user_type === 'mobile' || user_type === 'laptop') {
// open_curtain_w_contacts()
// }
// document.querySelector(".handler_curtain_left").classList.toggle("open") // document.querySelector(".handler_curtain_left").classList.toggle("open")
// document.querySelector(".handler_curtain_left").classList.toggle("close") // document.querySelector(".handler_curtain_left").classList.toggle("close")
// if (getInfoAboutUser() === 'mobile' || getInfoAboutUser() === 'laptop'){ // if (getInfoAboutUser() === 'mobile' || getInfoAboutUser() === 'laptop'){
@@ -559,8 +597,8 @@ function selectedUserMessenger (ticket_id=null,user_id=null,el){
// } // }
// check state
checkStateAfterChooseContact()
}, },
error: function (data){ error: function (data){
@@ -572,6 +610,17 @@ function selectedUserMessenger (ticket_id=null,user_id=null,el){
} }
function checkStateAfterChooseContact () {
if (document.querySelector('.menu_buttons.curtain.left.open')){
open_curtain_w_contacts()
}
if (document.querySelector('.block_overlay.show')){
setStandartSettingsToBlockOverlay()
}
}
function sendMessage(id_ticket=null,sender,receiver,files=null){ function sendMessage(id_ticket=null,sender,receiver,files=null){
// import {sendMessageSocket} from "./chat_sockets"; // import {sendMessageSocket} from "./chat_sockets";
if (!files){ if (!files){
@@ -985,7 +1034,7 @@ function show_header_list () {
// } else if (right){ // } else if (right){
// let right = document.querySelector(".curtain.right") // let right = document.querySelector(".curtain.right")
// open_curtain(null,right,null,'close') // open_curtain(null,right,null,'close')
// } else { // } else {`
// let curtain = getOpenCurtain() // let curtain = getOpenCurtain()
// if (curtain) { // if (curtain) {
// open_curtain(null, null, null, 'close') // open_curtain(null, null, null, 'close')

View File

@@ -6,11 +6,12 @@
<div class="first-column"> <div class="first-column">
<div class="footer_logo"><img class="svg" src="/static/img/svg/LogoWhite.svg"></div> <div class="footer_logo"><img class="svg" src="/static/img/svg/LogoWhite.svg"></div>
<div> <div>
{% if not user.user_profile.mailing_on %}
<div class="footer_text_sub">{% trans "Подпишись и будь в курсе всех событий, а также получай подарки и бонусы от Trip With Bonus" %}</div> <div class="footer_text_sub">{% trans "Подпишись и будь в курсе всех событий, а также получай подарки и бонусы от Trip With Bonus" %}</div>
<div class="insert_form"> <div class="insert_form">
{% include "forms/f_one_field_form.html" %} {% include "forms/f_one_field_form.html" %}
</div> </div>
{% endif %}
</div> </div>

View File

@@ -6,10 +6,13 @@
<div class="wrapper_header_content"> <div class="wrapper_header_content">
<div class="header-first"> <div class="header-first">
<div class="header_logo"> <div class="header_logo">
<a href="/"><img class="svg" src="/static/img/svg/Logo.svg"></a> <a href="{% url 'main' %}">
<img class="svg" src="/static/img/svg/Logo.svg">
</a>
</div> </div>
<div class="header_logo_mobile"> <div class="header_logo_mobile">
<a href="/"><img class="svg" src="/static/img/svg/LogoMobile.svg"></a> {# <a href="/"><img class="svg" src="/static/img/svg/LogoMobile.svg"></a>#}
<a href="{% url 'main' %}"><img class="svg" src="/static/img/svg/LogoMobile.svg"></a>
</div> </div>
<div class="dropdown"> <div class="dropdown">
@@ -76,7 +79,12 @@
</div> </div>
</div> </div>
<div class="button_profile_header_mobile" onclick="open_curtain_w_btn_profile()"> <div class="button_profile_header_mobile" onclick="open_curtain_w_btn_profile()">
<div class="marker_messages_mobile hide"></div>
<img src="/static/img/svg/userMobile.svg" alt=""> <img src="/static/img/svg/userMobile.svg" alt="">
{# <div class="icon_unread_messages" style="position:absolute;right: 5px;top: 0;">#}
{# <div class="cost-messages-in-user-tab-messenger" style="background: #ff0000;">#}
{# </div>#}
{# </div>#}
</div> </div>
{# <div class="menu_profile_btn">#} {# <div class="menu_profile_btn">#}
{# {% if user_subscribe %}<div class="subscribe_type_txt"><span class="f-l">Подписка:</span> <span class="f-r">{{ user_subscribe.subscribe.name }}</span><div class="clear_both"></div></div>{% endif %}#} {# {% if user_subscribe %}<div class="subscribe_type_txt"><span class="f-l">Подписка:</span> <span class="f-r">{{ user_subscribe.subscribe.name }}</span><div class="clear_both"></div></div>{% endif %}#}
@@ -110,6 +118,7 @@
<div class="button_profile_header_mobile" onclick="show_header_list()"> <div class="button_profile_header_mobile" onclick="show_header_list()">
<div class="marker_messages_mobile hide"></div>
<img src="/static/img/svg/userMobile.svg" alt=""> <img src="/static/img/svg/userMobile.svg" alt="">
</div> </div>

View File

@@ -6,7 +6,7 @@
{%trans "Тема запроса" as p_create_ticket %} {%trans "Тема запроса" as p_create_ticket %}
<form class="form-create-ticket" name="create-ticket"> <form class="form-create-ticket" name="create-ticket">
{% if errors.all__ %}<div class="errors_all" style="margin-bottom: 12px;width: 100%;font-size: 16px;">{{ errors.all__ }}</div>{% endif %} {% if form.errors.all__ %}<div class="errors_all" style="margin-bottom: 12px;width: 100%;font-size: 16px;">{{ form.errors.all__ }}</div>{% endif %}
{% csrf_token %} {% csrf_token %}
<div class="container-input-form-create-ticket"> <div class="container-input-form-create-ticket">

View File

@@ -1,5 +1,5 @@
{% load static %} {% load static %}
{% load tz %}
{#{% include "widgets/w_file.html" %}#} {#{% include "widgets/w_file.html" %}#}
{% if not messages and ticket %} {% if not messages and ticket %}
@@ -8,7 +8,9 @@
{% for msg in messages %} {% for msg in messages %}
{% include "widgets/w_message.html" %} {% include "widgets/w_message.html" %}
{% if forloop.first %} {% if forloop.first %}
{% timezone user_tz %}
<span style="display: none" class="date_n_time_last_message" data-modifiedDT="{{ msg.modifiedDT|date:"d.m.Y H:i:s:u" }}"></span> <span style="display: none" class="date_n_time_last_message" data-modifiedDT="{{ msg.modifiedDT|date:"d.m.Y H:i:s:u" }}"></span>
{% endtimezone %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% endif %} {% endif %}

View File

@@ -19,9 +19,9 @@
<div class="text_wrapper anchor about_service" id="scroll_to_wrapper"> <div class="text_wrapper anchor about_service" id="scroll_to_wrapper">
<span>{% translate "Trip With Bonus- это сервис, который соединяет отправителя посылки и перевозчика." %}</span> <span>{% translate "Trip With Bonus это сервис, который соединяет отправителя посылки и перевозчика." %}</span>
<span>{% translate "Вы можете разместить объявление о перевозке посылки и перевозчики со всего мира откликнуться на ваше объявление или воспользовавшись поиском на сайте найти перевозчика, который будет готов взять Вашу посылку и доставить в указанное место авто- или авива транспортом." %}</span> <span>{% translate "Вы можете разместить объявление о перевозке посылки и перевозчики со всего мира откликнутся на ваше объявление или воспользовавшись поиском на сайте найти перевозчика, который будет готов взять Вашу посылку и доставить в указанное место наземным или авиатранспортом." %}</span>
<span>{% translate "Если же Вы часто путешествуете или в разъездах, Вы можете самостоятельно перевозить посылки и при этом получать бонусы и благодарности." %}</span> <span>{% translate "Если же Вы часто путешествуете или в разъездах, Вы можете самостоятельно перевозить посылки и при этом получать бонусы и благодарности." %}</span>

View File

@@ -44,7 +44,7 @@
<span>{% translate "Trip With Bonus- это сервис, который соединяет отправителя посылки и перевозчика." %}</span> <span>{% translate "Trip With Bonus- это сервис, который соединяет отправителя посылки и перевозчика." %}</span>
<span>{% translate "Вы можете разместить объявление о перевозке посылки и перевозчики со всего мира откликнуться на ваше объявление или воспользовавшись поиском на сайте найти перевозчика, который будет готов взять Вашу посылку и доставить в указанное место авто- или авива транспортом." %}</span> <span>{% translate "Вы можете разместить объявление о перевозке посылки и перевозчики со всего мира откликнутся на ваше объявление или воспользовавшись поиском на сайте найти перевозчика, который будет готов взять Вашу посылку и доставить в указанное место наземным или авиатранспортом." %}</span>
<span>{% translate "Если же Вы часто путешествуете или в разъездах, Вы можете самостоятельно перевозить посылки и при этом получать бонусы и благодарности." %}</span> <span>{% translate "Если же Вы часто путешествуете или в разъездах, Вы можете самостоятельно перевозить посылки и при этом получать бонусы и благодарности." %}</span>
@@ -203,7 +203,7 @@
onclick="document.location='{% url 'profile_page' 'my_subscribe' %}'" onclick="document.location='{% url 'profile_page' 'my_subscribe' %}'"
> >
<button id=send_parcel_button">{% translate "Получить" %}</button> <button id=send_parcel_button>{% translate "Получить" %}</button>
</div> </div>
<img id="box1" src="/static/img/png/Box5.png" alt=""> <img id="box1" src="/static/img/png/Box5.png" alt="">

View File

@@ -18,7 +18,7 @@
<div class="text_wrapper"> <div class="text_wrapper">
<span>{% translate "Trip With Bonus- это сервис, который соединяет отправителя посылки и перевозчика." %}</span> <span>{% translate "Trip With Bonus- это сервис, который соединяет отправителя посылки и перевозчика." %}</span>
<span>{% translate "Вы можете разместить объявление о перевозке посылки и перевозчики со всего мира откликнуться на ваше объявление или воспользовавшись поиском на сайте найти перевозчика, который будет готов взять Вашу посылку и доставить в указанное место авто- или авива транспортом." %}</span> <span>{% translate "Вы можете разместить объявление о перевозке посылки и перевозчики со всего мира откликнутся на ваше объявление или воспользовавшись поиском на сайте найти перевозчика, который будет готов взять Вашу посылку и доставить в указанное место наземным или авиатранспортом." %}</span>
<span>{% translate "Если же Вы часто путешествуете или в разъездах, Вы можете самостоятельно перевозить посылки и при этом получать бонусы и благодарности." %}</span> <span>{% translate "Если же Вы часто путешествуете или в разъездах, Вы можете самостоятельно перевозить посылки и при этом получать бонусы и благодарности." %}</span>
</div> </div>

View File

@@ -34,9 +34,13 @@
{% if route_form.initial.from_address_point_txt %}value="{{ route_form.initial.from_address_point_txt }}"{% endif %} {% if route_form.initial.from_address_point_txt %}value="{{ route_form.initial.from_address_point_txt }}"{% endif %}
/> />
<div id="abbreviation_airport_in_search" onclick="focusOnInput(this)" class="abbreviation_airport_in_search {% if route_form.initial.from_address_point_txt %}hide{% endif %}"></div> <div id="abbreviation_airport_in_search" onclick="focusOnInput(this)" class="abbreviation_airport_in_search {% if route_form.initial.from_address_point_txt %}hide{% endif %}"></div>
<div class="input_list find_route" name="from_address_point_txt_list"> <div class="input_list find_route" name="from_address_point_txt_list">
</div> </div>
</div> </div>
</div> </div>
<div class="cont-el-form-search-carrier"> <div class="cont-el-form-search-carrier">
@@ -88,7 +92,7 @@
<div id="displayRegervation"></div> <div id="displayRegervation"></div>
</div> </div>
<div class="cont-el-form-search-carrier last"> <div class="cont-el-form-search-carrier last">
<label>test</label> <label for ="id_cargo_type">{% translate "Тип груза" %}</label>
<select class="custom_select el_form_find_route" name="cargo_type" id="id_cargo_type" {% if route_form.fields.cargo_type.required %} {% endif %}> <select class="custom_select el_form_find_route" name="cargo_type" id="id_cargo_type" {% if route_form.fields.cargo_type.required %} {% endif %}>
<option value="" selected="selected">{% translate "не имеет значения" %}</option> <option value="" selected="selected">{% translate "не имеет значения" %}</option>
{% for item in route_form.fields.cargo_type.choices %} {% for item in route_form.fields.cargo_type.choices %}

View File

@@ -17,7 +17,14 @@
{% endif %} {% endif %}
<div class="inputs_l"> <div class="inputs_l">
<input name="username" type="text" placeholder="{{ p_login }}" {% if form.data.username %} value="{{ form.data.username }}"{% endif %}> <input
name="username"
type="text"
placeholder="{{ p_login }}"
{% if form.data.username %} value="{{ form.data.username }}"{% endif %}
id="login_email_input"
>
{% if form.username and form.errors.username %} {% if form.username and form.errors.username %}
<span>{{ form.errors.username }}</span> <span>{{ form.errors.username }}</span>
{% endif %} {% endif %}

View File

@@ -7,14 +7,20 @@
data-name="msg_from_footer" data-name="msg_from_footer"
{% if form.form_name %}data-name="{{ form.form_name}}"{% endif %} {% if form.form_name %}data-name="{{ form.form_name}}"{% endif %}
> >
<div class="footer_input_wrap"> <div
onclick="event.stopPropagation()"
class="footer_input_wrap">
<input class="footer_input" <input class="footer_input"
name="email" name="email"
type="email" type="email"
{% if user.is_authenticated %}
readonly
value="{{ user.email }}"
{% endif %}
onkeydown = "hideErrors(this)" onkeydown = "hideErrors(this)"
{% if form.data.email %} value="{{ form.data.email }}"{% endif %} {% if form.data.email %} value="{{ form.data.email }}"{% endif %}
placeholder="{% trans "Введите ваш e-mail" %}"> placeholder="{% trans "Введите ваш e-mail" %}">
<button onclick="RequestCommercialOffer(this)" id="footer_input_button"> <button onclick="subscribeNewsletter(this)" id="footer_input_button">
<img class="svg" src="/static/img/svg/CaretCircleRight.svg"> <img class="svg" src="/static/img/svg/CaretCircleRight.svg">
</button> </button>

View File

@@ -47,6 +47,7 @@
onkeydown = "hideErrors(this)" onkeydown = "hideErrors(this)"
type="text" type="text"
placeholder="E-mail" placeholder="E-mail"
id="registration_email_input"
{% if form.data.email %} value="{{ form.data.email }}"{% endif %}> {% if form.data.email %} value="{{ form.data.email }}"{% endif %}>
{% if form.errors and form.errors.email %} {% if form.errors and form.errors.email %}

View File

@@ -0,0 +1,113 @@
{% load i18n %}
<div style="font-family:Calibri,Candara,Segoe,'Segoe UI',Optima,Arial,sans-serif;
padding:10px; background-color: #F8F8F8;"
>
<div style="line-height:1.0em; width: 660px">
<div style="padding:5px; text-align: center;">
<img src="{{ logo }}" alt="{{ project_name }}" style="margin:0;padding:0;">
</div>
<p style="font-weight:700; font-size:25px; text-align:center;
padding:0; line-height:1em; text-transform: uppercase; color: #ff613a;
margin: auto; max-width: 90%;
">
{{ message_title|safe }}
</p>
<div style="line-height:1.0em; font-size:18px; margin: 5px 30px;
box-shadow: -1px 4px 10px 0 rgba(198, 199, 203, 0.20), 0 -1px 10px 0 rgba(198, 199, 203, 0.20);
padding: 30px; border-radius: 10px; background-color: #FFF;">
<p style="font-weight: 600;">{% translate "Здравствуйте" %}{% if user.first_name %}, {{ user.first_name }}{% endif %}!</p>
<p>{% translate "Мы рады приветствовать вас в Trip With Bonus! Спасибо, за регистрацию на нашем сайте" %}.</p>
<p>
{% translate "Ваш аккаунт успешно создан." %}<br>
{% translate "Ваш логин" %}: <b>{{ user.email }}</b><br>
{% translate "Ваш пароль" %}: <b>{{ pass }}</b><br>
</p>
<div>
{% translate "Теперь вы можете воспользоваться всеми преимуществами нашего сервиса. Вот несколько полезных функций, которые вы можете исследовать:<br>" %}
<ul>
<li>{% translate "На главной странице нашего сайта Вы можете указать критерии поиска перевозчика посылки или отправителя и напрямую связаться с исполнителем." %}</li>
<li>{% translate "Также в личном кабинете пользователя Вы можете разместить объявление о перевозке посылки или о необходимости отправить посылку. Перевозчики и отправители со всего мира найдут Вас!" %}</li>
</ul>
</div>
<p>
{% blocktrans %}
Чтобы начать, просто перейдите на <a href="https://tripwb.com">сайт</a> и используйте свои учетные данные для входа.
{% endblocktrans %}
</p>
<p>
{% blocktrans %}
Если у вас возникнут вопросы или вам потребуется помощь, наша служба поддержки всегда готова помочь. Свяжитесь с нами по адресу <a href="mailto:support@tripwb.com">support@tripwb.com</a>
{% endblocktrans %}
</p>
<p>{% translate "Спасибо за то, что вы с нами!" %}</p>
<p>
{% blocktrans %}
С уважением,<br>
Команда Trip With Bonus.<br>
{% endblocktrans %}
</p>
</div>
{% for button in message_buttons %}
<div style="text-align:center;font-weight: 700;">
<a href="{{ button.url }}">
<div style="display:inline-block;text-align:center;font-size:18px;padding:5px 10px;margin:5px;border-radius:2px;background-color:#61aeb6;color:#fff;text-decoration:none;line-height:1.0em;cursor:pointer">
{{ button.caption }}
</div>
</a>
</div>
{% endfor %}
<div style="text-align:center;width: 660px;line-height:1.1em">
<div style="margin: 40px 10px 10px;">
<hr>
{# <nobr><b>Адрес кафе:</b> Минск, ул. Будславская, 2</nobr>#}
{# <br>#}
{# <nobr><b>График работы:</b> пн-вс 12:00 - 24:00</nobr>#}
{# <br>#}
{# <nobr><b>Телефоны кафе:</b> +375 44 77 321 77</nobr>#}
</div>
</div>
<div style="text-align: center;margin-top:5px">
{# <a href="https://baldenini.by/event/dostavka-edy" style="text-decoration: none;">#}
{# <div style="color: #311A12;#}
{# padding: 10px;#}
{# margin: 5px 10px 0 10px;#}
{# border: 2px solid #311A12;#}
{# border-radius: 5px;#}
{# font-size: 20px;#}
{# display: inline-block;#}
{# font-weight: 700;#}
{# text-transform: uppercase;">О ДОСТАВКЕ#}
{# </div>#}
{# </a>#}
{# <a href="https://baldenini.by/page/baldenini-cafe-o-nas" style="text-decoration: none;">#}
{# <div style="color: #311A12;#}
{# padding: 10px;#}
{# margin: 5px 10px 0 10px;#}
{# border: 2px solid #311A12;#}
{# border-radius: 5px;#}
{# font-size: 20px;#}
{# display: inline-block;#}
{# font-weight: 700;#}
{# text-transform: uppercase;">О BALDENINI CAFE#}
{# </div>#}
{# </a>#}
</div>
</div>
</div>

View File

@@ -58,7 +58,7 @@
<h2 id="title_static">{% translate "О сервисе Trip With Bonus" %}</h2> <h2 id="title_static">{% translate "О сервисе Trip With Bonus" %}</h2>
<span id="sub_title_static"> <span id="sub_title_static">
<p> <p>
{% translate "TWB - это сервис, созданный для того, чтобы отправитель и перевозчик нашли друг-друга!" %} {% translate "TWB это сервис, созданный для того, чтобы отправитель и перевозчик нашли друг-друга!" %}
{% translate "Наш сервис предлагает вам прямые контакты, а не является посредником!" %} {% translate "Наш сервис предлагает вам прямые контакты, а не является посредником!" %}
</p> </p>
</span> </span>

View File

@@ -6,7 +6,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-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,height=device-height">
<meta name="vapid-key" content="{{ vapid_key }}"> <meta name="vapid-key" content="{{ vapid_key }}">
@@ -24,11 +24,16 @@
<script src="{% static "js/global_js.js" %}"></script> <script src="{% static "js/global_js.js" %}"></script>
<script src="{% static "js/chat_socket_start.js" %}"></script> <script src="{% static "js/chat_socket_start.js" %}"></script>
{% if user and not user.is_anonymous %} {% if user and not user.is_anonymous %}
{% include "connect_ws_js.html" %}
<script src='{% static "js/chat_sockets.js" %}'></script> <script src='{% static "js/chat_sockets.js" %}'></script>
<script> <script>
{#var user_id = {{ user.id }}#} {#var user_id = {{ user.id }}#}
{% if prod %}
ws_url = `wss://{% get_ws_address %}/ws/socket-server/?user_id={{ user.id }}`; ws_url = `wss://{% get_ws_address %}/ws/socket-server/?user_id={{ user.id }}`;
{% else %}
ws_url = `ws://{% get_ws_address %}/ws/socket-server/?user_id={{ user.id }}`;
{% endif %}
var chatSocket; var chatSocket;
init_ws() init_ws()
const beep = new Audio('/static/sounds/beep_2.mp3') const beep = new Audio('/static/sounds/beep_2.mp3')
@@ -67,7 +72,7 @@
<div class="txt_cookie">Сайт использует файлы cookie. Просматривая этот сайт, Вы соглашаетесь <div class="txt_cookie">Сайт использует файлы cookie. Просматривая этот сайт, Вы соглашаетесь
<a class="a_cookie" href="#">с условиями использования cookie-файлов</a> <a class="a_cookie" href="#">с условиями использования cookie-файлов</a>
</div> </div>
<button class="cookie_btn" onclick="setCokie()">Понятно</button> <button class="cookie_btn" onclick="setCokie(182,'allow_cookie','true')">Понятно</button>
</div> </div>
</div> </div>
@@ -130,6 +135,14 @@
{% include 'blocks/b_footer.html' %} {% include 'blocks/b_footer.html' %}
<script>
let tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (!tz) {
tz = "UTC"
}
document.cookie = "user_tz=" + tz + ";path=/";
</script>
</body>
</body> </body>

View File

@@ -11,7 +11,9 @@
</div> </div>
{% if item.unread_msgs_count %} {% if item.unread_msgs_count %}
<div class="right-part-tab-user"> <div class="right-part-tab-user">
<div class="cost-messages-in-user-tab-messenger"><span>{{ item.unread_msgs_count }}</span></div> <div class="cost-messages-in-user-tab-messenger">
{# <span>{{ item.unread_msgs_count }}</span>#}
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>

View File

@@ -11,7 +11,9 @@
</div> </div>
{% if item.unread_msgs_count %} {% if item.unread_msgs_count %}
<div class="right-part-tab-user"> <div class="right-part-tab-user">
<div class="cost-messages-in-user-tab-messenger"><span>{{ item.unread_msgs_count }}</span></div> <div class="cost-messages-in-user-tab-messenger">
{# <span>{{ item.unread_msgs_count }}</span>#}
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>

View File

@@ -1,5 +1,6 @@
{% load static %} {% load static %}
{% load tt_chat %} {% load tt_chat %}
{% load tz %}
<div style="width: 100%;"> <div style="width: 100%;">
<div class="container-message_support_chat {% get_msg_side user ticket msg %}"> <div class="container-message_support_chat {% get_msg_side user ticket msg %}">
@@ -20,7 +21,9 @@
</div> </div>
</div> </div>
<div class="data_send_message {% get_msg_side user ticket msg %}"> <div class="data_send_message {% get_msg_side user ticket msg %}">
{% timezone user_tz %}
<span>{% if msg %}{{ msg.modifiedDT }}{% else %}{{ ticket.modifiedDT }}{% endif %}</span> <span>{% if msg %}{{ msg.modifiedDT }}{% else %}{{ ticket.modifiedDT }}{% endif %}</span>
{% endtimezone %}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,7 @@
{% load static %} {% load static %}
{% load tt_chat %} {% load tt_chat %}
{% load tz %}
<div style="width: 100%;"> <div style="width: 100%;">
<div class="container-message_support_chat {% get_msg_side user ticket msg %}"> <div class="container-message_support_chat {% get_msg_side user ticket msg %}">
@@ -34,12 +36,17 @@
{% endif %} {% endif %}
</div> </div>
<div class="data_send_message {% get_msg_side user ticket msg %}"> <div class="data_send_message {% get_msg_side user ticket msg %}">
<span>{% if msg %}{{ msg.modifiedDT }}{% else %}{{ ticket.modifiedDT }}{% endif %}</span> {% timezone user_tz %}
<span>
{% if msg %}{{ msg.modifiedDT|localtime }}{% else %}{{ ticket.modifiedDT|localtime }}{% endif %}
</span>
{% endtimezone %}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{#{% tz_detect %}#}
{#<div class="container-message_support_chat{% if msg.sender == ticket.manager %} left{% else %} right{% endif %}">#} {#<div class="container-message_support_chat{% if msg.sender == ticket.manager %} left{% else %} right{% endif %}">#}
{# <div class="block_avatar_message">#} {# <div class="block_avatar_message">#}

View File

@@ -1,5 +1,8 @@
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}
{% load tz %}
<div class="container-message-req-sprt" onclick="openTicket({{ ticket.id }})"> <div class="container-message-req-sprt" onclick="openTicket({{ ticket.id }})">
<div class="message-sprt-inf"> <div class="message-sprt-inf">
<div> <div>
@@ -10,8 +13,9 @@
{# <img>#} {# <img>#}
<span id="modified_date"> <span id="modified_date">
{# 10.02.2023#} {# 10.02.2023#}
{% timezone user_tz %}
{{ ticket.modifiedDT|date:"d.m.Y" }} {{ ticket.modifiedDT|date:"d.m.Y" }}
{% endtimezone %}
</span> </span>
</div> </div>