Compare commits

52 Commits

Author SHA1 Message Date
SDE
7c5ebdcfbf 0.5.28 hide support button 2024-08-03 16:18:37 +03:00
SDE
7560354677 0.5.27 check translate for support 2024-07-25 20:04:59 +03:00
SDE
2dddcab2f2 0.5.26 docs admin add actions for assign version to docs list 2024-07-20 13:42:46 +03:00
SDE
3a4f9e5606 0.5.25 change settings for files 2024-07-19 11:57:43 +03:00
SDE
35f03282af 0.5.24 change settings 2024-07-19 04:21:44 +03:00
SDE
42b9925e60 0.5.23 fix pdf font 2024-07-19 01:32:12 +03:00
SDE
772db778b7 0.5.23 fix get_options_by_opt_types 2024-07-19 01:28:50 +03:00
SDE
1583da5816 0.5.22 fix get_options_by_opt_types 2024-07-19 01:26:24 +03:00
SDE
8e12c7e515 0.5.21 fix get_options_by_opt_types 2024-07-19 01:24:18 +03:00
SDE
be06cb0ef9 0.5.21 fix CKEDITOR_RESTRICT_BY_USER 2024-07-19 01:11:23 +03:00
SDE
4053d17981 0.5.20 fix encodings 2024-07-19 01:03:31 +03:00
SBD
7a95c5c3ef documentation page 2024-07-18 14:18:42 +03:00
SBD
c573d29eb1 documentation page 2024-07-18 14:03:05 +03:00
SBD
f2c3ffe87b documentation page 2024-07-18 13:46:19 +03:00
SBD
a28ebd1958 Merge remote-tracking branch 'origin/main' 2024-07-18 13:39:09 +03:00
SBD
97330ad8e5 documentation page 2024-07-18 13:37:41 +03:00
SDE
2a900c2726 0.5.19 fix next \ prev doc 2024-07-18 13:33:46 +03:00
SDE
fb6676c468 0.5.18 fix next \ prev doc 2024-07-18 13:30:29 +03:00
SDE
2e01e3eeb3 0.5.17 fix docs not allow 2024-07-18 13:04:00 +03:00
SDE
f6f1eefa82 0.5.16 add migration 2024-07-18 12:52:24 +03:00
SDE
442405735d 0.5.15 add migration 2024-07-18 12:46:39 +03:00
SDE
845518b3ef 0.5.14 pdf articles export 2024-07-17 01:50:03 +03:00
SDE
f11a3f0463 0.5.13 pdf articles export 2024-07-16 17:35:33 +03:00
SBD
b132b9e087 documentation page 2024-07-16 14:26:20 +03:00
SBD
1df287c122 documentation page 2024-07-16 13:28:14 +03:00
SBD
309bec8d77 documentation page 2024-07-16 13:16:56 +03:00
SBD
0bfae14abc documentation page 2024-07-16 13:00:01 +03:00
SBD
724e3c6342 documentation page 2024-07-15 17:26:25 +03:00
SBD
131d9dd9b1 documentation page 2024-07-15 16:20:23 +03:00
SBD
4faeb12156 documentation page 2024-07-15 16:17:47 +03:00
SBD
73ce9c0ce3 documentation page 2024-07-15 15:52:25 +03:00
SBD
e03fe21db3 documentation page 2024-07-15 15:38:29 +03:00
SBD
3b4e83a4e2 documentation page 2024-07-15 15:34:43 +03:00
SBD
2d0f98d36c documentation page 2024-07-15 15:26:44 +03:00
SDE
7d971710b5 0.5.12 get_tree_arts fix 2024-07-15 15:25:44 +03:00
SBD
9fa8403e95 documentation page 2024-07-15 15:13:51 +03:00
SBD
03b8f760dc documentation page 2024-07-15 14:53:08 +03:00
SBD
cd77473d5e documentation page 2024-07-15 14:50:36 +03:00
SBD
082e3107e6 documentation page 2024-07-15 14:21:54 +03:00
SBD
8f01426ea6 Merge remote-tracking branch 'origin/main' 2024-07-15 14:21:06 +03:00
SBD
3668d7a549 documentation page 2024-07-15 14:20:53 +03:00
SDE
83d50657ef 0.5.11 documentation file storage 2024-07-15 02:22:53 +03:00
SBD
5f207aed36 documentation page 2024-07-14 18:21:27 +03:00
SBD
b7ba22a56a documentation page 2024-07-14 18:10:09 +03:00
SBD
288c41800f documentation page 2024-07-14 18:09:31 +03:00
SBD
52478534fd documentation page 2024-07-14 17:23:04 +03:00
SBD
e04fef3ca4 documentation page 2024-07-14 17:15:13 +03:00
SDE
cd3be918e3 0.5.10 documentation insert video, file storage 2024-07-14 17:12:05 +03:00
SDE
7e9fb581c3 0.5.10 documentation insert video, file storage 2024-07-14 17:05:05 +03:00
SBD
391908c9ae documentation page 2024-07-14 16:42:20 +03:00
SDE
15938e1fc8 Merge remote-tracking branch 'origin/main' 2024-07-14 14:48:32 +03:00
SDE
65a06dff8e 0.5.9 documentation prev and next article navigation 2024-07-14 14:48:22 +03:00
42 changed files with 1324 additions and 168 deletions

View File

@@ -124,8 +124,10 @@ def init_formfield_for_dbfield(class_model, self, db_field, request, **kwargs):
formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'}) formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'})
if db_field.name in ('lexems',): if db_field.name in ('lexems',):
formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'}) formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'})
# if db_field.name == 'answer': if db_field.name == 'answer':
# formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'}) formfield.widget = admin.widgets.AdminTextareaWidget(attrs={'style': 'width: 80%'})
# if db_field.name in ['file']:
# formfield.widget = admin.widgets.AdminTextInputWidget(attrs={'style': 'width: 80%'})
if db_field.name in ['question', 'FAQ_title']: if db_field.name in ['question', 'FAQ_title']:
formfield.widget = admin.widgets.AdminTextInputWidget(attrs={'style': 'width: 80%'}) formfield.widget = admin.widgets.AdminTextInputWidget(attrs={'style': 'width: 80%'})
@@ -266,6 +268,20 @@ class Admin_BaseIconTabularModel(admin.TabularInline):
class Admin_BaseIconModel(admin.ModelAdmin): class Admin_BaseIconModel(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
# ckeditor + youtube фикс
for field in form.changed_data:
if 'RichTextUploading' in str(form.fields[field]):
val = getattr(obj, field, None)
if val and type(val) == str:
val = val.replace(' sandbox=""', '')
setattr(obj, field, val)
# setattr(form.instance, field, val)
# form.cleaned_data[field] = form.cleaned_data[field].replace(' sandbox=""', '')
# form.data[field] = form.data[field].replace(' sandbox=""', '')
super().save_model(request, obj, form, change)
def description_exists(self, obj): def description_exists(self, obj):
if obj.description: if obj.description:

View File

@@ -148,6 +148,11 @@ class BaseModelViewPage(BaseModel):
class Meta: class Meta:
abstract = True abstract = True
def save(self, not_change_modifiedDT=False, *args, **kwargs):
if not not_change_modifiedDT:
self.modifiedDT = datetime.now()
super().save(*args, **kwargs)
def get_title(self): def get_title(self):
if self.seo_title: if self.seo_title:
return self.seo_title return self.seo_title

View File

@@ -96,27 +96,27 @@ def sortByLength(inputStr):
return len(inputStr) return len(inputStr)
def add_domain(request, url, add_lang=False): # def add_domain(request, url, add_lang=False):
domain = get_domain_by_request(request) # domain = get_domain_by_request(request)
if add_lang: # if add_lang:
cur_lang = get_cur_lang_by_request(request) # cur_lang = get_cur_lang_by_request(request)
return '{0}/{1}/{2}'.format(domain, cur_lang, url) # return '{0}/{1}/{2}'.format(domain, cur_lang, url)
else: # else:
return '{0}{1}'.format(domain, url) # return '{0}{1}'.format(domain, url)
#
#
def get_domain_by_request(request): # def get_domain_by_request(request):
from project_sets import domain # from pAerBim.project_sets import domain
if request.query_params and 'domain' in request.query_params: # if request.query_params and 'domain' in request.query_params:
return request.query_params['domain'] # return request.query_params['domain']
return domain # return domain
#
#
def get_cur_lang_by_request(request): # def get_cur_lang_by_request(request):
from project_sets import lang # from project_sets import lang
if request.query_params and 'cur_lang' in request.query_params: # if request.query_params and 'cur_lang' in request.query_params:
return request.query_params['cur_lang'] # return request.query_params['cur_lang']
return lang # return lang
def get_img_type_by_request(request): def get_img_type_by_request(request):

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2010 wkhtmltopdf authors
*
* This file is part of wkhtmltopdf.
*
* wkhtmltopdf is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* wkhtmltopdf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with wkhtmltopdf. If not, see <http: *www.gnu.org/licenses/>.
*/
#ifndef __WKHTMLTOPDF_DLLBEGIN__
#define __WKHTMLTOPDF_DLLBEGIN__
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_DLL
#define DLL_PUBLIC __declspec(dllexport)
#else
#define DLL_PUBLIC __declspec(dllimport)
#endif
#define DLL_LOCAL
#else
#if __GNUC__ >= 4
#define DLL_PUBLIC __attribute__ ((visibility("default")))
#define DLL_LOCAL __attribute__ ((visibility("hidden")))
#else
#define DLL_PUBLIC
#define DLL_LOCAL
#endif
#endif
#if defined _WIN32
#define CALLTYPE __stdcall
#else
#define CALLTYPE
#endif
#ifdef __cplusplus
#define CAPI(type) extern "C" DLL_PUBLIC type CALLTYPE
#else
#define CAPI(type) DLL_PUBLIC type CALLTYPE
#endif
#endif /*__WKHTMLTOPDF_DLLBEGIN__*/

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2010 wkhtmltopdf authors
*
* This file is part of wkhtmltopdf.
*
* wkhtmltopdf is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* wkhtmltopdf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with wkhtmltopdf. If not, see <http: *www.gnu.org/licenses/>.
*/
#ifdef __WKHTMLTOPDF_DLLBEGIN__
#undef __WKHTMLTOPDF_DLLBEGIN__
#undef DLL_PUBLIC
#undef DLL_LOCAL
#undef CAPI
#undef CALLTYPE
#endif /*__WKHTMLTOPDF_DLLBEGIN__*/

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2010 wkhtmltopdf authors
*
* This file is part of wkhtmltopdf.
*
* wkhtmltopdf is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* wkhtmltopdf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with wkhtmltopdf. If not, see <http: *www.gnu.org/licenses/>.
*/
#ifndef __IMAGE_H__
#define __IMAGE_H__
#include <wkhtmltox/dllbegin.inc>
struct wkhtmltoimage_global_settings;
typedef struct wkhtmltoimage_global_settings wkhtmltoimage_global_settings;
struct wkhtmltoimage_converter;
typedef struct wkhtmltoimage_converter wkhtmltoimage_converter;
typedef void (*wkhtmltoimage_str_callback)(wkhtmltoimage_converter * converter, const char * str);
typedef void (*wkhtmltoimage_int_callback)(wkhtmltoimage_converter * converter, const int val);
typedef void (*wkhtmltoimage_void_callback)(wkhtmltoimage_converter * converter);
CAPI(int) wkhtmltoimage_init(int use_graphics);
CAPI(int) wkhtmltoimage_deinit();
CAPI(int) wkhtmltoimage_extended_qt();
CAPI(const char *)wkhtmltoimage_version();
CAPI(wkhtmltoimage_global_settings *) wkhtmltoimage_create_global_settings();
CAPI(int) wkhtmltoimage_set_global_setting(wkhtmltoimage_global_settings * settings, const char * name, const char * value);
CAPI(int) wkhtmltoimage_get_global_setting(wkhtmltoimage_global_settings * settings, const char * name, char * value, int vs);
CAPI(wkhtmltoimage_converter *) wkhtmltoimage_create_converter(wkhtmltoimage_global_settings * settings, const char * data);
CAPI(void) wkhtmltoimage_destroy_converter(wkhtmltoimage_converter * converter);
CAPI(void) wkhtmltoimage_set_warning_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_str_callback cb);
CAPI(void) wkhtmltoimage_set_error_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_str_callback cb);
CAPI(void) wkhtmltoimage_set_phase_changed_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_void_callback cb);
CAPI(void) wkhtmltoimage_set_progress_changed_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_int_callback cb);
CAPI(void) wkhtmltoimage_set_finished_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_int_callback cb);
CAPI(int) wkhtmltoimage_convert(wkhtmltoimage_converter * converter);
/* CAPI(void) wkhtmltoimage_begin_conversion(wkhtmltoimage_converter * converter); */
/* CAPI(void) wkhtmltoimage_cancel(wkhtmltoimage_converter * converter); */
CAPI(int) wkhtmltoimage_current_phase(wkhtmltoimage_converter * converter);
CAPI(int) wkhtmltoimage_phase_count(wkhtmltoimage_converter * converter);
CAPI(const char *) wkhtmltoimage_phase_description(wkhtmltoimage_converter * converter, int phase);
CAPI(const char *) wkhtmltoimage_progress_string(wkhtmltoimage_converter * converter);
CAPI(int) wkhtmltoimage_http_error_code(wkhtmltoimage_converter * converter);
CAPI(long) wkhtmltoimage_get_output(wkhtmltoimage_converter * converter, const unsigned char **);
#include <wkhtmltox/dllend.inc>
#endif /*__IMAGE_H__*/

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2010 wkhtmltopdf authors
*
* This file is part of wkhtmltopdf.
*
* wkhtmltopdf is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* wkhtmltopdf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with wkhtmltopdf. If not, see <http: *www.gnu.org/licenses/>.
*/
#ifndef __PDF_H__
#define __PDF_H__
#include <wkhtmltox/dllbegin.inc>
struct wkhtmltopdf_global_settings;
typedef struct wkhtmltopdf_global_settings wkhtmltopdf_global_settings;
struct wkhtmltopdf_object_settings;
typedef struct wkhtmltopdf_object_settings wkhtmltopdf_object_settings;
struct wkhtmltopdf_converter;
typedef struct wkhtmltopdf_converter wkhtmltopdf_converter;
typedef void (*wkhtmltopdf_str_callback)(wkhtmltopdf_converter * converter, const char * str);
typedef void (*wkhtmltopdf_int_callback)(wkhtmltopdf_converter * converter, const int val);
typedef void (*wkhtmltopdf_void_callback)(wkhtmltopdf_converter * converter);
CAPI(int) wkhtmltopdf_init(int use_graphics);
CAPI(int) wkhtmltopdf_deinit();
CAPI(int) wkhtmltopdf_extended_qt();
CAPI(const char *) wkhtmltopdf_version();
CAPI(wkhtmltopdf_global_settings *) wkhtmltopdf_create_global_settings();
CAPI(void) wkhtmltopdf_destroy_global_settings(wkhtmltopdf_global_settings *);
CAPI(wkhtmltopdf_object_settings *) wkhtmltopdf_create_object_settings();
CAPI(void) wkhtmltopdf_destroy_object_settings(wkhtmltopdf_object_settings *);
CAPI(int) wkhtmltopdf_set_global_setting(wkhtmltopdf_global_settings * settings, const char * name, const char * value);
CAPI(int) wkhtmltopdf_get_global_setting(wkhtmltopdf_global_settings * settings, const char * name, char * value, int vs);
CAPI(int) wkhtmltopdf_set_object_setting(wkhtmltopdf_object_settings * settings, const char * name, const char * value);
CAPI(int) wkhtmltopdf_get_object_setting(wkhtmltopdf_object_settings * settings, const char * name, char * value, int vs);
CAPI(wkhtmltopdf_converter *) wkhtmltopdf_create_converter(wkhtmltopdf_global_settings * settings);
CAPI(void) wkhtmltopdf_destroy_converter(wkhtmltopdf_converter * converter);
CAPI(void) wkhtmltopdf_set_warning_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_str_callback cb);
CAPI(void) wkhtmltopdf_set_error_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_str_callback cb);
CAPI(void) wkhtmltopdf_set_phase_changed_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_void_callback cb);
CAPI(void) wkhtmltopdf_set_progress_changed_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_int_callback cb);
CAPI(void) wkhtmltopdf_set_finished_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_int_callback cb);
/* CAPI(void) wkhtmltopdf_begin_conversion(wkhtmltopdf_converter * converter); */
/* CAPI(void) wkhtmltopdf_cancel(wkhtmltopdf_converter * converter); */
CAPI(int) wkhtmltopdf_convert(wkhtmltopdf_converter * converter);
CAPI(void) wkhtmltopdf_add_object(
wkhtmltopdf_converter * converter, wkhtmltopdf_object_settings * setting, const char * data);
CAPI(int) wkhtmltopdf_current_phase(wkhtmltopdf_converter * converter);
CAPI(int) wkhtmltopdf_phase_count(wkhtmltopdf_converter * converter);
CAPI(const char *) wkhtmltopdf_phase_description(wkhtmltopdf_converter * converter, int phase);
CAPI(const char *) wkhtmltopdf_progress_string(wkhtmltopdf_converter * converter);
CAPI(int) wkhtmltopdf_http_error_code(wkhtmltopdf_converter * converter);
CAPI(long) wkhtmltopdf_get_output(wkhtmltopdf_converter * converter, const unsigned char **);
#include <wkhtmltox/dllend.inc>
#endif /*__PDF_H__*/

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,54 @@
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
* vi:set ts=4 sts=4 sw=4 noet :
*
* Copyright 2010-2020 wkhtmltopdf authors
*
* This file is part of wkhtmltopdf.
*
* wkhtmltopdf is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* wkhtmltopdf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with wkhtmltopdf. If not, see <http: *www.gnu.org/licenses/>.
*/
#ifndef __WKHTMLTOPDF_DLLBEGIN__
#define __WKHTMLTOPDF_DLLBEGIN__
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_DLL
#define DLL_PUBLIC __declspec(dllexport)
#else
#define DLL_PUBLIC __declspec(dllimport)
#endif
#define DLL_LOCAL
#else
#if __GNUC__ >= 4
#define DLL_PUBLIC __attribute__ ((visibility("default")))
#define DLL_LOCAL __attribute__ ((visibility("hidden")))
#else
#define DLL_PUBLIC
#define DLL_LOCAL
#endif
#endif
#if defined _WIN32
#define CALLTYPE __stdcall
#else
#define CALLTYPE
#endif
#ifdef __cplusplus
#define CAPI(type) extern "C" DLL_PUBLIC type CALLTYPE
#else
#define CAPI(type) DLL_PUBLIC type CALLTYPE
#endif
#endif /*__WKHTMLTOPDF_DLLBEGIN__*/

View File

@@ -0,0 +1,30 @@
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
* vi:set ts=4 sts=4 sw=4 noet :
*
* Copyright 2010-2020 wkhtmltopdf authors
*
* This file is part of wkhtmltopdf.
*
* wkhtmltopdf is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* wkhtmltopdf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with wkhtmltopdf. If not, see <http: *www.gnu.org/licenses/>.
*/
#ifdef __WKHTMLTOPDF_DLLBEGIN__
#undef __WKHTMLTOPDF_DLLBEGIN__
#undef DLL_PUBLIC
#undef DLL_LOCAL
#undef CAPI
#undef CALLTYPE
#endif /*__WKHTMLTOPDF_DLLBEGIN__*/

View File

@@ -0,0 +1,76 @@
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
* vi:set ts=4 sts=4 sw=4 noet :
*
* Copyright 2010-2020 wkhtmltopdf authors
*
* This file is part of wkhtmltopdf.
*
* wkhtmltopdf is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* wkhtmltopdf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with wkhtmltopdf. If not, see <http: *www.gnu.org/licenses/>.
*/
#ifndef __IMAGE_H__
#define __IMAGE_H__
#ifdef BUILDING_WKHTMLTOX
#include "dllbegin.inc"
#else
#include <wkhtmltox/dllbegin.inc>
#endif
struct wkhtmltoimage_global_settings;
typedef struct wkhtmltoimage_global_settings wkhtmltoimage_global_settings;
struct wkhtmltoimage_converter;
typedef struct wkhtmltoimage_converter wkhtmltoimage_converter;
typedef void (*wkhtmltoimage_str_callback)(wkhtmltoimage_converter * converter, const char * str);
typedef void (*wkhtmltoimage_int_callback)(wkhtmltoimage_converter * converter, const int val);
typedef void (*wkhtmltoimage_void_callback)(wkhtmltoimage_converter * converter);
CAPI(int) wkhtmltoimage_init(int use_graphics);
CAPI(int) wkhtmltoimage_deinit();
CAPI(int) wkhtmltoimage_extended_qt();
CAPI(const char *)wkhtmltoimage_version();
CAPI(wkhtmltoimage_global_settings *) wkhtmltoimage_create_global_settings();
CAPI(int) wkhtmltoimage_set_global_setting(wkhtmltoimage_global_settings * settings, const char * name, const char * value);
CAPI(int) wkhtmltoimage_get_global_setting(wkhtmltoimage_global_settings * settings, const char * name, char * value, int vs);
CAPI(wkhtmltoimage_converter *) wkhtmltoimage_create_converter(wkhtmltoimage_global_settings * settings, const char * data);
CAPI(void) wkhtmltoimage_destroy_converter(wkhtmltoimage_converter * converter);
CAPI(void) wkhtmltoimage_set_warning_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_str_callback cb);
CAPI(void) wkhtmltoimage_set_error_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_str_callback cb);
CAPI(void) wkhtmltoimage_set_phase_changed_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_void_callback cb);
CAPI(void) wkhtmltoimage_set_progress_changed_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_int_callback cb);
CAPI(void) wkhtmltoimage_set_finished_callback(wkhtmltoimage_converter * converter, wkhtmltoimage_int_callback cb);
CAPI(int) wkhtmltoimage_convert(wkhtmltoimage_converter * converter);
/* CAPI(void) wkhtmltoimage_begin_conversion(wkhtmltoimage_converter * converter); */
/* CAPI(void) wkhtmltoimage_cancel(wkhtmltoimage_converter * converter); */
CAPI(int) wkhtmltoimage_current_phase(wkhtmltoimage_converter * converter);
CAPI(int) wkhtmltoimage_phase_count(wkhtmltoimage_converter * converter);
CAPI(const char *) wkhtmltoimage_phase_description(wkhtmltoimage_converter * converter, int phase);
CAPI(const char *) wkhtmltoimage_progress_string(wkhtmltoimage_converter * converter);
CAPI(int) wkhtmltoimage_http_error_code(wkhtmltoimage_converter * converter);
CAPI(long) wkhtmltoimage_get_output(wkhtmltoimage_converter * converter, const unsigned char **);
#ifdef BUILDING_WKHTMLTOX
#include "dllend.inc"
#else
#include <wkhtmltox/dllend.inc>
#endif
#endif /*__IMAGE_H__*/

View File

@@ -0,0 +1,88 @@
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
* vi:set ts=4 sts=4 sw=4 noet :
*
* Copyright 2010-2020 wkhtmltopdf authors
*
* This file is part of wkhtmltopdf.
*
* wkhtmltopdf is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* wkhtmltopdf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with wkhtmltopdf. If not, see <http: *www.gnu.org/licenses/>.
*/
#ifndef __PDF_H__
#define __PDF_H__
#ifdef BUILDING_WKHTMLTOX
#include "dllbegin.inc"
#else
#include <wkhtmltox/dllbegin.inc>
#endif
struct wkhtmltopdf_global_settings;
typedef struct wkhtmltopdf_global_settings wkhtmltopdf_global_settings;
struct wkhtmltopdf_object_settings;
typedef struct wkhtmltopdf_object_settings wkhtmltopdf_object_settings;
struct wkhtmltopdf_converter;
typedef struct wkhtmltopdf_converter wkhtmltopdf_converter;
typedef void (*wkhtmltopdf_str_callback)(wkhtmltopdf_converter * converter, const char * str);
typedef void (*wkhtmltopdf_int_callback)(wkhtmltopdf_converter * converter, const int val);
typedef void (*wkhtmltopdf_void_callback)(wkhtmltopdf_converter * converter);
CAPI(int) wkhtmltopdf_init(int use_graphics);
CAPI(int) wkhtmltopdf_deinit();
CAPI(int) wkhtmltopdf_extended_qt();
CAPI(const char *) wkhtmltopdf_version();
CAPI(wkhtmltopdf_global_settings *) wkhtmltopdf_create_global_settings();
CAPI(void) wkhtmltopdf_destroy_global_settings(wkhtmltopdf_global_settings *);
CAPI(wkhtmltopdf_object_settings *) wkhtmltopdf_create_object_settings();
CAPI(void) wkhtmltopdf_destroy_object_settings(wkhtmltopdf_object_settings *);
CAPI(int) wkhtmltopdf_set_global_setting(wkhtmltopdf_global_settings * settings, const char * name, const char * value);
CAPI(int) wkhtmltopdf_get_global_setting(wkhtmltopdf_global_settings * settings, const char * name, char * value, int vs);
CAPI(int) wkhtmltopdf_set_object_setting(wkhtmltopdf_object_settings * settings, const char * name, const char * value);
CAPI(int) wkhtmltopdf_get_object_setting(wkhtmltopdf_object_settings * settings, const char * name, char * value, int vs);
CAPI(wkhtmltopdf_converter *) wkhtmltopdf_create_converter(wkhtmltopdf_global_settings * settings);
CAPI(void) wkhtmltopdf_destroy_converter(wkhtmltopdf_converter * converter);
CAPI(void) wkhtmltopdf_set_warning_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_str_callback cb);
CAPI(void) wkhtmltopdf_set_error_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_str_callback cb);
CAPI(void) wkhtmltopdf_set_phase_changed_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_void_callback cb);
CAPI(void) wkhtmltopdf_set_progress_changed_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_int_callback cb);
CAPI(void) wkhtmltopdf_set_finished_callback(wkhtmltopdf_converter * converter, wkhtmltopdf_int_callback cb);
/* CAPI(void) wkhtmltopdf_begin_conversion(wkhtmltopdf_converter * converter); */
/* CAPI(void) wkhtmltopdf_cancel(wkhtmltopdf_converter * converter); */
CAPI(int) wkhtmltopdf_convert(wkhtmltopdf_converter * converter);
CAPI(void) wkhtmltopdf_add_object(
wkhtmltopdf_converter * converter, wkhtmltopdf_object_settings * setting, const char * data);
CAPI(int) wkhtmltopdf_current_phase(wkhtmltopdf_converter * converter);
CAPI(int) wkhtmltopdf_phase_count(wkhtmltopdf_converter * converter);
CAPI(const char *) wkhtmltopdf_phase_description(wkhtmltopdf_converter * converter, int phase);
CAPI(const char *) wkhtmltopdf_progress_string(wkhtmltopdf_converter * converter);
CAPI(int) wkhtmltopdf_http_error_code(wkhtmltopdf_converter * converter);
CAPI(long) wkhtmltopdf_get_output(wkhtmltopdf_converter * converter, const unsigned char **);
#ifdef BUILDING_WKHTMLTOX
#include "dllend.inc"
#else
#include <wkhtmltox/dllend.inc>
#endif
#endif /*__PDF_H__*/

View File

@@ -7,6 +7,7 @@ from django.utils.translation import gettext as _
from django import forms from django import forms
from django.utils.text import slugify from django.utils.text import slugify
from django.db.models import Min from django.db.models import Min
from django.contrib import messages
class DocArtForm(forms.ModelForm): class DocArtForm(forms.ModelForm):
@@ -19,6 +20,26 @@ class DocArtForm(forms.ModelForm):
self.fields['parent'].queryset = DocArt.objects.exclude(id__exact=self.instance.id) self.fields['parent'].queryset = DocArt.objects.exclude(id__exact=self.instance.id)
def make_assign_versions_action(version):
def assign_to_version(modeladmin, request, queryset):
for art in queryset:
if version not in art.versions.all():
art.versions.add(version) # Method on Order model
messages.info(request, f"Статье {art} назначена версия {version.name}")
assign_to_version.short_description = _(f"Назначить версию {version.name}")
# We need a different '__name__' for each action - Django
# uses this as a key in the drop-down box.
assign_to_version.__name__ = _(f"Назначить версию {version.name}")
return assign_to_version
class Admin_DocArt(SuperModelAdmin, Admin_Trans_BaseModelViewPage): class Admin_DocArt(SuperModelAdmin, Admin_Trans_BaseModelViewPage):
form = DocArtForm form = DocArtForm
@@ -93,6 +114,20 @@ class Admin_DocArt(SuperModelAdmin, Admin_Trans_BaseModelViewPage):
# inlines = [Admin_StackedInline_Block] # inlines = [Admin_StackedInline_Block]
actions = ["create_copy_arts"] actions = ["create_copy_arts"]
def get_actions(self, request):
actions = super(Admin_DocArt, self).get_actions(request)
versions = DocVersion.objects.filter(enable=True)
for version in versions:
action = make_assign_versions_action(version)
actions[action.__name__] = (action,
action.__name__,
action.short_description)
return actions
@admin.action(description=_("Создать копии выбранных статей")) @admin.action(description=_("Создать копии выбранных статей"))
def create_copy_arts(self, request, queryset): def create_copy_arts(self, request, queryset):
from BaseModels.functions import create_url from BaseModels.functions import create_url

View File

@@ -2,7 +2,7 @@ from django.db import models
from BaseModels.base_models import BaseModelViewPage, BaseModel from BaseModels.base_models import BaseModelViewPage, BaseModel
from ckeditor_uploader.fields import RichTextUploadingField from ckeditor_uploader.fields import RichTextUploadingField
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from datetime import datetime
class DocVersion(BaseModel): class DocVersion(BaseModel):
url = models.TextField( url = models.TextField(
@@ -43,11 +43,22 @@ class DocArt(BaseModelViewPage):
related_name='rel_docArts_for_version' related_name='rel_docArts_for_version'
) )
def get_last_child(self): # def save(self, not_change_modifiedDT=False, *args, **kwargs):
return self.rel_childArts_for_docArt.filter(enable=True).order_by('-order').first() # if not not_change_modifiedDT:
# self.modifiedDT = datetime.now()
# super().save(*args, **kwargs)
def get_first_child(self): def get_last_child(self, version):
return self.rel_childArts_for_docArt.filter(enable=True).order_by('order').first() return self.rel_childArts_for_docArt.filter(
versions=version,
enable=True
).order_by('-order').first()
def get_first_child(self, version):
return self.rel_childArts_for_docArt.filter(
versions=version,
enable=True
).order_by('order').first()
def get_last_version(self): def get_last_version(self):
return self.versions.all().order_by('-order').first() return self.versions.all().order_by('-order').first()
@@ -60,16 +71,21 @@ class DocArt(BaseModelViewPage):
if not version: if not version:
version = self.get_last_version() version = self.get_last_version()
art = DocArt.objects.filter( kwargs = {
enable=True, 'enable': True,
versions=version, 'versions': version,
order__lt=self.order, 'parent': self.parent
parent=self.parent }
).order_by('-order').first() if self.order:
kwargs['order__lt'] = self.order
art = DocArt.objects.exclude(
id=self.id
).filter(**kwargs).order_by('-order').first()
if art: if art:
while art.get_last_child(): while art.get_last_child(version=version):
art = art.get_last_child() art = art.get_last_child(version=version)
if not art and self.parent: if not art and self.parent:
art = self.parent art = self.parent
@@ -81,14 +97,20 @@ class DocArt(BaseModelViewPage):
if not version: if not version:
version = self.get_last_version() version = self.get_last_version()
art = self.get_first_child() art = self.get_first_child(version=version)
if not art: if not art:
art = DocArt.objects.filter(
enable=True, kwargs = {
versions=version, 'enable': True,
order__gt=self.order, 'versions': version,
parent=self.parent 'parent': self.parent
).order_by('order').first() }
if self.order:
kwargs['order__gt'] = self.order
art = DocArt.objects.exclude(
id=self.id
).filter(**kwargs).order_by('order').first()
if not art and self.parent: if not art and self.parent:
art = DocArt.objects.filter( art = DocArt.objects.filter(

View File

@@ -1,4 +1,5 @@
import json import json
import os
from django.http import HttpResponse, Http404, FileResponse, HttpResponseRedirect from django.http import HttpResponse, Http404, FileResponse, HttpResponseRedirect
from django.template import loader, RequestContext from django.template import loader, RequestContext
@@ -9,15 +10,18 @@ from GeneralApp.funcs import get_inter_http_respose
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.urls import reverse from django.urls import reverse
from collections import OrderedDict from collections import OrderedDict
from django.template.loader import render_to_string
from urllib.parse import unquote
def get_tree_arts(art, arts, sel_arts_ids): def get_tree_arts(art, arts, sel_arts_ids):
docs_tree = OrderedDict() docs_tree = OrderedDict()
docs_tree.update({ docs_tree.update({
art_item.name: { art_item.id: {
'url': art_item.url, 'url': art_item.url,
'id': art_item.id, 'name': art_item.name,
# 'id': art_item.id,
'children': get_tree_arts(art_item, arts, sel_arts_ids), 'children': get_tree_arts(art_item, arts, sel_arts_ids),
'active': art_item.id in sel_arts_ids 'active': art_item.id in sel_arts_ids
} for art_item in arts.filter(parent=art) } for art_item in arts.filter(parent=art)
@@ -25,22 +29,74 @@ def get_tree_arts(art, arts, sel_arts_ids):
return docs_tree return docs_tree
# def get_tree_arts(art, arts):
#
# docs_tree = OrderedDict()
# docs_tree.update({ def _response_pdf(path):
# art['name']: {
# 'url': art['url'], filePDF = open(path, 'rb')
# 'id': art['id'],
# 'children': get_tree_arts(art, DocArt.objects.filter(parent=art)), content = filePDF.read()
# } for art in arts.filter(parent=None) # content = str(content)
# }) filePDF.close()
# return docs_tree
response = HttpResponse(content, content_type='application/pdf')
response['Content-Disposition'] = 'filename="{fn}"'.format(fn=os.path.basename(path))
return response
def pdf_render(request, template, context, file_name):
from BaseModels.functions import url_translit
from GeneralApp.funcs_options import get_options_by_opt_types
filename = url_translit(file_name)
html = render_to_string(template, context, request)
sets = get_options_by_opt_types(['domain'], only_vals=True, w_prefix=True)
if settings.DEBUG:
sets['domain'] = 'http://127.0.0.1:8019'
while 'src="/' in html:
html = html.replace('src="/', f'src="{sets["domain"]}/')
# html = unquote(html)
f = open(f'{settings.PDF_FOLDER}/{filename}.html', 'w')
f.write(html)
f.close()
os.system(
'{wkhtmltopdf} '
# '--margin-top 20mm '
# '--encoding windows-1250 '
'--enable-local-file-access '
'--load-error-handling ignore '
'--enable-internal-links '
'--keep-relative-links '
'--print-media-type '
'--encoding UTF-8 '
# '--default-header '
# '--minimum-font-size 20mm '
'{pdf_folder}/{file_name}.html '
'{pdf_folder}/{file_name}.pdf'.format(
wkhtmltopdf=settings.WKHTML_TO_PDF, pdf_folder=settings.PDF_FOLDER, file_name=filename)
)
path = settings.PDF_FOLDER + '/' + filename + '.pdf'
# os.system(u'{wkhtmltopdf} {print_folder}/order{filename}.html {print_folder}/order{filename}.pdf'.format(wkhtmltopdf=settings.WKHTML_TO_PDF, print_folder=settings.PRINT_FOLDER))
return _response_pdf(path)
def DocsView(request, version=None, art_url=None): def DocsView(request, version=None, art_url=None):
if art_url and version: if art_url and version:
generate_pdf = False
if request.GET and 'pdf' in request.GET and request.GET['pdf'] == 'true':
generate_pdf = True
kwargs = { kwargs = {
'enable': True, 'enable': True,
'url': art_url, 'url': art_url,
@@ -83,10 +139,19 @@ def DocsView(request, version=None, art_url=None):
'allow_versions': versions, 'allow_versions': versions,
'breadcrumbs': breadcrumbs, 'breadcrumbs': breadcrumbs,
'prev_article': art.get_prev_article(version=vers_obj), 'prev_article': art.get_prev_article(version=vers_obj),
'next_article': art.get_next_article(version=vers_obj) 'next_article': art.get_next_article(version=vers_obj),
'pdf_render': generate_pdf
} }
t = loader.get_template('pages/p_documentation.html')
return get_inter_http_respose(t, Dict, request) if not generate_pdf:
tpl = 'pages/p_documentation.html'
t = loader.get_template(tpl)
return get_inter_http_respose(t, Dict, request)
else:
tpl = 'blocks/b_documentation_article.html'
# tpl = 'pages/p_documentation.html'
return pdf_render(request, tpl, Dict, art.name)
except DocArt.DoesNotExist: except DocArt.DoesNotExist:
raise Http404 raise Http404
@@ -110,11 +175,11 @@ def DocsView(request, version=None, art_url=None):
versions=None versions=None
).filter( ).filter(
enable=True, parent=None enable=True, parent=None
).order_by('-versions__order', 'order').first() ).order_by('-versions__order', '-versions__name', 'order').first()
if art: if art:
url = reverse( url = reverse(
'docs_art_page', 'docs_art_page',
kwargs={'version': art.versions.order_by('order').first().url, 'art_url': art.url} kwargs={'version': art.versions.order_by('-order').first().url, 'art_url': art.url}
) )
return HttpResponseRedirect(url) return HttpResponseRedirect(url)

View File

@@ -1,6 +1,10 @@
import copy
from django import forms
from django.contrib import admin
from sets.admin import * from sets.admin import *
from .models import * from .models import *
from django.contrib import admin
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
# from nested_inline.admin import NestedStackedInline, NestedTabularInline, NestedModelAdmin, NestedInline # from nested_inline.admin import NestedStackedInline, NestedTabularInline, NestedModelAdmin, NestedInline
from super_inlines.admin import SuperInlineModelAdmin, SuperModelAdmin from super_inlines.admin import SuperInlineModelAdmin, SuperModelAdmin
@@ -22,6 +26,50 @@ admin.site.register(LogEntry, LogEntryAdmin)
class Admin_FileUnit(Admin_Trans_BaseModelViewPage):
def fn(self, obj):
return obj.file.filename
fn.short_description = 'Файл'
def fn_full_path(self, obj):
from urllib.parse import unquote_plus
res = unquote_plus(obj.file.url, encoding="utf-8")
return res
fn_full_path.short_description = 'Линк для использования в HTML'
fieldsets = [
(None, {
'classes': [],
'fields': [
# ('name',),
('file',),
# 'image'
'order'
]
})
]
list_display = [
# 'image_thumb',
'id',
'fn',
'fn_full_path',
# 'title',
'order', 'modifiedDT', 'createDT'
]
list_display_links = ['id']
list_editable = ['order']
list_filter = ['modifiedDT', 'createDT']
search_fields = ['file']
admin.site.register(FileUnit, Admin_FileUnit)
class Admin_Inline_WidgetForBlock(SuperInlineModelAdmin, Admin_Trans_BaseIconStackedInline): class Admin_Inline_WidgetForBlock(SuperInlineModelAdmin, Admin_Trans_BaseIconStackedInline):
def formfield_for_dbfield(self, db_field, request, **kwargs): def formfield_for_dbfield(self, db_field, request, **kwargs):
@@ -40,6 +88,7 @@ class Admin_Inline_WidgetForBlock(SuperInlineModelAdmin, Admin_Trans_BaseIconSta
# 'title', # 'title',
'name', 'description', 'text', 'name', 'description', 'text',
'picture', 'picture',
# 'image'
), ),
'video_url', 'video_url',
('bg_color', ), ('bg_color', ),
@@ -84,6 +133,77 @@ class Admin_StackedInline_Block(Admin_Trans_GenericBaseIconStackedInline, SuperI
class Admin_PageAddingBlocksTemplate(Admin_BaseIconModel):
from ServicesApp.admin import Admin_StackedInline_BlockPluginPresentation
from SlidesApp.admin import Admin_StackedInline_Slide
fieldsets = [
(None, {
'classes': ['wide'],
'fields': ('name',
# 'url',
# 'title',
# 'description', 'text',
# 'picture',
# 'order',
)
}),
# ('SEO', {
# 'classes': ['wide', 'collapse'],
# 'fields': (
# 'seo_title', 'seo_description', 'seo_keywords', 'seo_text',
# )
# }),
]
def get_list_display(self, request):
if request.user.is_superuser:
# self.list_display.append()
d_list = copy.copy(self.list_display)
d_list.append('name_plural')
return d_list
return self.list_display
def get_changelist_instance(self, request):
if request.user.is_superuser:
self.list_editable.append('name_plural')
return super(Admin_PageAddingBlocksTemplate, self).get_changelist_instance(request)
list_display = [
# 'image_thumb',
'id',
'name',
'enable',
# 'url',
# 'title',
# 'order',
'modifiedDT', 'createDT'
]
list_display_links = ['id', 'name']
list_editable = ['enable']
list_filter = ['modifiedDT', 'createDT']
search_fields = ['name']
# filter_horizontal = ['options']
inlines = [
Admin_StackedInline_Slide,
Admin_StackedInline_BlockPluginPresentation,
Admin_StackedInline_Block,
# AdminStacked_FAQitem,
]
def has_delete_permission(self, request, obj=None):
if request.user.is_superuser:
return True
if not obj or obj.name_plural in ['documentation', 'contacts']:
return False
admin.site.register(PageAddingBlocksTemplate, Admin_PageAddingBlocksTemplate)
class Admin_StaticPage(SuperModelAdmin, Admin_Trans_BaseModelViewPage): class Admin_StaticPage(SuperModelAdmin, Admin_Trans_BaseModelViewPage):

View File

@@ -40,11 +40,15 @@ def get_inter_Dict(user, context_Dict):
feedback_form.initial = {'form_name': form_name} feedback_form.initial = {'form_name': form_name}
Dict.update({'feedback_form': feedback_form}) Dict.update({'feedback_form': feedback_form})
from DocsApp.models import DocArt
arts_exists = DocArt.objects.filter(enable=True).exists()
Dict.update({ Dict.update({
'sections': sections, 'sections': sections,
'logo': get_logo_url(), 'logo': get_logo_url(),
'hide_form_field_description': hide_form_field_description, 'hide_form_field_description': hide_form_field_description,
'footer_contacts': get_footer_contacts(), 'footer_contacts': get_footer_contacts(),
'allow_documentation': arts_exists,
}) })
# 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)

View File

@@ -1,6 +1,6 @@
from .models import * from .models import *
def get_options_by_opt_types(opt_types, only_vals=False): def get_options_by_opt_types(opt_types, only_vals=False, w_prefix=False):
if type(opt_types) == str: if type(opt_types) == str:
kwargs = {'opt_type': opt_types} kwargs = {'opt_type': opt_types}
elif type(opt_types) == dict: elif type(opt_types) == dict:
@@ -10,8 +10,15 @@ def get_options_by_opt_types(opt_types, only_vals=False):
opts = Option.objects.filter(**kwargs) opts = Option.objects.filter(**kwargs)
if opts and only_vals: if opts and only_vals:
opts = opts.values('opt_type', 'value') opts = opts.values('opt_type', 'value', 'prefix')
opts = {item['opt_type']: item['value'] for item in opts} res_Dict = {}
for item in opts:
val = item['value']
if w_prefix and item['prefix']:
val = item['prefix'] + val
res_Dict.update({item['opt_type']: val})
return res_Dict
return opts return opts
def get_first_option_value_by_opt_type(opt_type): def get_first_option_value_by_opt_type(opt_type):

View File

@@ -0,0 +1,66 @@
# Generated by Django 4.2.7 on 2024-07-14 13:22
import datetime
from django.db import migrations, models
import filebrowser.fields
class Migration(migrations.Migration):
dependencies = [
('GeneralApp', '0025_alter_office_work_time_from_and_more'),
]
operations = [
migrations.CreateModel(
name='FileUnit',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')),
('name_ru', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')),
('name_en', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')),
('name_plural', models.TextField(blank=True, null=True, verbose_name='Название (множественное число)')),
('order', models.IntegerField(blank=True, null=True, verbose_name='Очередность отображения')),
('createDT', models.DateTimeField(auto_now_add=True, verbose_name='Дата и время создания')),
('modifiedDT', models.DateTimeField(blank=True, null=True, verbose_name='Дата и время последнего изменения')),
('enable', models.BooleanField(db_index=True, default=True, verbose_name='Включено')),
('json_data', models.JSONField(blank=True, default=dict, verbose_name='Дополнительные данные')),
('file', filebrowser.fields.FileBrowseField(max_length=250, verbose_name='Файл')),
('file_ru', filebrowser.fields.FileBrowseField(max_length=250, null=True, verbose_name='Файл')),
('file_en', filebrowser.fields.FileBrowseField(max_length=250, null=True, verbose_name='Файл')),
],
options={
'abstract': False,
},
),
migrations.AlterField(
model_name='office',
name='work_time_from',
field=models.TimeField(default=datetime.datetime(2024, 7, 14, 9, 0), verbose_name='Время работы с'),
),
migrations.AlterField(
model_name='office',
name='work_time_from_en',
field=models.TimeField(default=datetime.datetime(2024, 7, 14, 9, 0), null=True, verbose_name='Время работы с'),
),
migrations.AlterField(
model_name='office',
name='work_time_from_ru',
field=models.TimeField(default=datetime.datetime(2024, 7, 14, 9, 0), null=True, verbose_name='Время работы с'),
),
migrations.AlterField(
model_name='office',
name='work_time_to',
field=models.TimeField(default=datetime.datetime(2024, 7, 14, 18, 0), verbose_name='Время работы до'),
),
migrations.AlterField(
model_name='office',
name='work_time_to_en',
field=models.TimeField(default=datetime.datetime(2024, 7, 14, 18, 0), null=True, verbose_name='Время работы до'),
),
migrations.AlterField(
model_name='office',
name='work_time_to_ru',
field=models.TimeField(default=datetime.datetime(2024, 7, 14, 18, 0), null=True, verbose_name='Время работы до'),
),
]

View File

@@ -0,0 +1,65 @@
# Generated by Django 4.2.7 on 2024-07-15 17:00
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('GeneralApp', '0026_fileunit_alter_office_work_time_from_and_more'),
]
operations = [
migrations.CreateModel(
name='PageAddingBlocksTemplate',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')),
('name_plural', models.TextField(blank=True, null=True, verbose_name='Название (множественное число)')),
('order', models.IntegerField(blank=True, null=True, verbose_name='Очередность отображения')),
('createDT', models.DateTimeField(auto_now_add=True, verbose_name='Дата и время создания')),
('modifiedDT', models.DateTimeField(blank=True, null=True, verbose_name='Дата и время последнего изменения')),
('enable', models.BooleanField(db_index=True, default=True, verbose_name='Включено')),
('json_data', models.JSONField(blank=True, default=dict, verbose_name='Дополнительные данные')),
],
options={
'verbose_name': 'Шаблон настройки дополнительных блоков на странице',
'verbose_name_plural': 'Шаблоны настройки дополнительных блоков на странице',
},
),
migrations.AlterModelOptions(
name='fileunit',
options={'verbose_name': 'Файл', 'verbose_name_plural': 'Файлы'},
),
migrations.AlterField(
model_name='office',
name='work_time_from',
field=models.TimeField(default=datetime.datetime(2024, 7, 15, 9, 0), verbose_name='Время работы с'),
),
migrations.AlterField(
model_name='office',
name='work_time_from_en',
field=models.TimeField(default=datetime.datetime(2024, 7, 15, 9, 0), null=True, verbose_name='Время работы с'),
),
migrations.AlterField(
model_name='office',
name='work_time_from_ru',
field=models.TimeField(default=datetime.datetime(2024, 7, 15, 9, 0), null=True, verbose_name='Время работы с'),
),
migrations.AlterField(
model_name='office',
name='work_time_to',
field=models.TimeField(default=datetime.datetime(2024, 7, 15, 18, 0), verbose_name='Время работы до'),
),
migrations.AlterField(
model_name='office',
name='work_time_to_en',
field=models.TimeField(default=datetime.datetime(2024, 7, 15, 18, 0), null=True, verbose_name='Время работы до'),
),
migrations.AlterField(
model_name='office',
name='work_time_to_ru',
field=models.TimeField(default=datetime.datetime(2024, 7, 15, 18, 0), null=True, verbose_name='Время работы до'),
),
]

View File

@@ -1,3 +1,4 @@
from django.core.files.storage import FileSystemStorage
from django.db import models from django.db import models
from BaseModels.base_models import * from BaseModels.base_models import *
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@@ -8,6 +9,27 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.fields import GenericRelation
from colorfield.fields import ColorField from colorfield.fields import ColorField
from filebrowser.fields import FileBrowseField
from filebrowser.base import FileObject
class PageAddingBlocksTemplate(BaseModel):
class Meta:
verbose_name = _('Шаблон настройки дополнительных блоков на странице')
verbose_name_plural = _('Шаблоны настройки дополнительных блоков на странице')
class FileUnit(BaseModel):
file = FileBrowseField(verbose_name=_('Файл'), max_length=250, directory="files/")
def __str__(self):
if self.file:
return self.file.filename
else:
return str(self.id)
class Meta:
verbose_name = _('Файл')
verbose_name_plural = _('Файлы')
class StaticPage(BaseModelViewPage): class StaticPage(BaseModelViewPage):
promo_header = models.BooleanField(verbose_name='Промо-хэдер', default=False) promo_header = models.BooleanField(verbose_name='Промо-хэдер', default=False)
@@ -120,6 +142,11 @@ class WidgetForBlock(BaseModel):
validators=[validate_file_extension] validators=[validate_file_extension]
) )
def image(self):
if self.picture:
return FileObject(self.picture.path)
return None
class Meta: class Meta:
verbose_name = _('Виджет в блоке') verbose_name = _('Виджет в блоке')

View File

@@ -2,6 +2,12 @@ from modeltranslation.translator import translator, TranslationOptions
from .models import * from .models import *
class FileUnit_TranslationOptions(TranslationOptions):
fields = (
'name', 'file'
)
translator.register(FileUnit, FileUnit_TranslationOptions)
class StaticPage_TranslationOptions(TranslationOptions): class StaticPage_TranslationOptions(TranslationOptions):
fields = ( fields = (
'name', 'description', 'text', 'title', 'FAQ_title', 'seo_title', 'seo_description', 'seo_text' 'name', 'description', 'text', 'title', 'FAQ_title', 'seo_title', 'seo_description', 'seo_text'

View File

@@ -29,17 +29,24 @@ DEBUG = True
ALLOWED_HOSTS = ['*'] ALLOWED_HOSTS = ['*']
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
CSRF_TRUSTED_ORIGINS = ['https://aerbim.com', 'http://127.0.0.1:8019/'] CSRF_TRUSTED_ORIGINS = ['https://aerbim.com', 'http://127.0.0.1:8019/', 'https://www.youtube.com/']
X_FRAME_OPTIONS = 'SAMEORIGIN'
# Application definition # Application definition
FILEBROWSER_SHOW_IN_DASHBOARD = False
LIST_PER_PAGE = 100
INSTALLED_APPS = [ INSTALLED_APPS = [
'colorfield', 'colorfield',
'modeltranslation',
"admin_interface",
'super_inlines', 'super_inlines',
# 'grappelli',
'filebrowser',
"admin_interface",
'modeltranslation',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
@@ -72,7 +79,7 @@ MIDDLEWARE = [
# 'AuthApp.middleware.ResponseInterceptionMiddleware', # 'AuthApp.middleware.ResponseInterceptionMiddleware',
] ]
X_FRAME_OPTIONS = 'SAMEORIGIN'
ROOT_URLCONF = 'pAerBim.urls' ROOT_URLCONF = 'pAerBim.urls'
@@ -157,7 +164,9 @@ USE_TZ = False
# https://docs.djangoproject.com/en/4.2/howto/static-files/ # https://docs.djangoproject.com/en/4.2/howto/static-files/
MEDIA_URL = '/media/' MEDIA_URL = '/media/'
MEDIA_ROOT = 'media/' # MEDIA_ROOT = 'media/'
import os
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_URL = '/static/' STATIC_URL = '/static/'
STATIC_ROOT = '/' STATIC_ROOT = '/'
@@ -191,6 +200,10 @@ LANG_INFO = dict(django.conf.locale.LANG_INFO.items()) #+ EXTRA_LANG_INFO.items(
django.conf.locale.LANG_INFO = LANG_INFO django.conf.locale.LANG_INFO = LANG_INFO
from filebrowser.sites import site
site.directory = ""
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
@@ -201,7 +214,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
CKEDITOR_BASEPATH = "/static/ckeditor/ckeditor/" CKEDITOR_BASEPATH = "/static/ckeditor/ckeditor/"
CKEDITOR_UPLOAD_PATH = "uploads/" CKEDITOR_UPLOAD_PATH = "uploads/"
CKEDITOR_RESTRICT_BY_DATE = False CKEDITOR_RESTRICT_BY_DATE = False
CKEDITOR_RESTRICT_BY_USER = True CKEDITOR_RESTRICT_BY_USER = False
CKEDITOR_BROWSE_SHOW_DIRS = True CKEDITOR_BROWSE_SHOW_DIRS = True
CKEDITOR_IMAGE_BACKEND = "pillow" CKEDITOR_IMAGE_BACKEND = "pillow"
@@ -220,8 +233,12 @@ CKEDITOR_CONFIGS = {
'toolbar': 'Custom', 'toolbar': 'Custom',
'forcePasteAsPlainText': True, 'forcePasteAsPlainText': True,
'allowedContent': True, 'allowedContent': True,
'extraAllowedContent': 'iframe[*]',
# 'disallowedContent': 'img{width,height};img[width,height]', # 'disallowedContent': 'img{width,height};img[width,height]',
# 'extraPlugins': 'image2', 'extraPlugins': ','.join([
'codesnippet',
# 'youtube'
]),
'enterMode': 2, 'enterMode': 2,
'basicEntities' : False, 'basicEntities' : False,
@@ -250,11 +267,19 @@ CKEDITOR_CONFIGS = {
'/', '/',
{'name': 'links', 'items': ['Link', 'Unlink', 'Anchor', '-', 'Blockquote' ]}, {'name': 'links', 'items': ['Link', 'Unlink', 'Anchor', '-', 'Blockquote' ]},
{'name': 'insert', {'name': 'insert',
'items': ['Image', 'Update', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak', 'Iframe']}, 'items': ['Image', 'Youtube', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak', 'Iframe']
},
# {
# 'name': 'youtube',
# 'items': ['Youtube',]
# }
], ],
} }
} }
PDF_FOLDER = 'media/pdf'
WKHTML_TO_PDF = 'BaseModels\wkhtmltopdf\{0}\wkhtmltopdf'.format(u'bin')
try: try:
import db_local_sets import db_local_sets

View File

@@ -3,6 +3,16 @@ from django.contrib import admin
from django.urls import path, include from django.urls import path, include
from django.conf.urls.static import static from django.conf.urls.static import static
from django.conf import settings from django.conf import settings
from filebrowser.sites import site
# from django.core.files.storage import DefaultStorage
# from filebrowser.sites import FileBrowserSite
#
# site = FileBrowserSite(name="filebrowser", storage=DefaultStorage())
# customsite = FileBrowserSite(name='custom_filebrowser', storage=DefaultStorage())
# customsite.directory = "uploads/"
urlpatterns = [ urlpatterns = [
path('ckeditor/', include('ckeditor_uploader.urls')), path('ckeditor/', include('ckeditor_uploader.urls')),
@@ -14,6 +24,9 @@ urlpatterns = [
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns
urlpatterns += i18n_patterns( urlpatterns += i18n_patterns(
path('admin/filebrowser/', site.urls),
# path('grappelli/', include('grappelli.urls')),
path('admin/', admin.site.urls), path('admin/', admin.site.urls),

View File

@@ -6,3 +6,5 @@ django-modeltranslation==0.18.11
Pillow==10.1.0 Pillow==10.1.0
psycopg2-binary==2.9.9 psycopg2-binary==2.9.9
django-super-inlines django-super-inlines
# django-filebrowser-4.0.3
django-filebrowser-no-grappelli==4.0.2

View File

@@ -1656,6 +1656,8 @@ body.n_scroll{
font-size: 14px; font-size: 14px;
color: #7A8185FF; color: #7A8185FF;
cursor: pointer; cursor: pointer;
display: block;
text-decoration: unset;
} }
.way_bread_crumb.last{ .way_bread_crumb.last{
@@ -1688,7 +1690,7 @@ body.n_scroll{
.documentation_version{ .documentation_version{
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 40px; margin-bottom: 30px;
} }
.documentation_version_switcher{ .documentation_version_switcher{
@@ -1730,6 +1732,7 @@ body.n_scroll{
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-decoration: unset;
} }
.one_item_documentation_switcher_content_part:hover{ .one_item_documentation_switcher_content_part:hover{
@@ -1744,7 +1747,7 @@ body.n_scroll{
.tree_documentation_container{ .tree_documentation_container{
width: 100%; width: 100%;
height: calc(100vh - 300px);
overflow-y: auto; overflow-y: auto;
} }
.tree_documentation_container.hide_scroll::-webkit-scrollbar{ .tree_documentation_container.hide_scroll::-webkit-scrollbar{
@@ -1796,6 +1799,7 @@ body.n_scroll{
display: flex; display: flex;
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;
align-items: flex-start;
} }
@@ -1812,9 +1816,9 @@ body.n_scroll{
} }
.tree_documentation_arrow_img{ .tree_documentation_arrow_img{
width: 12px; width: 7px;
height: 7px; height: 12px;
padding: 9px 6px; padding: 6px 9px;
} }
.tree_documentation_container_first_level_txt{ .tree_documentation_container_first_level_txt{
@@ -1822,12 +1826,18 @@ body.n_scroll{
font-weight: 700; font-weight: 700;
color: #000000; color: #000000;
margin-left: 3px; margin-left: 3px;
display: block;
text-decoration: unset;
line-height: 25px;
} }
.tree_documentation_container_second_level_txt{ .tree_documentation_container_second_level_txt{
font-size: 16px; font-size: 16px;
font-weight: 400; font-weight: 400;
color: #000000; color: #000000;
margin-left: 3px; margin-left: 3px;
display: block;
text-decoration: unset;
line-height: 24px;
} }
.tree_documentation_container_first_level_txt.chose{ .tree_documentation_container_first_level_txt.chose{
color: #0C54A0FF; color: #0C54A0FF;
@@ -1857,7 +1867,7 @@ body.n_scroll{
} }
.elements_third_level_content_part_tree{ .elements_third_level_content_part_tree{
margin-left: 50px; margin-left: 40px;
} }
.element_third_level_content_part_tree{ .element_third_level_content_part_tree{
@@ -1867,6 +1877,8 @@ body.n_scroll{
font-weight: 400; font-weight: 400;
margin: 5px 0; margin: 5px 0;
cursor: pointer; cursor: pointer;
display: block;
text-decoration: unset;
} }
.element_third_level_content_part_tree.chose{ .element_third_level_content_part_tree.chose{
@@ -1896,6 +1908,7 @@ body.n_scroll{
.content_part_tree_els h1{ .content_part_tree_els h1{
font-size: 40px; font-size: 40px;
margin-top: 0!important;
} }
.name_article_tree{ .name_article_tree{
@@ -1947,6 +1960,8 @@ body.n_scroll{
font-weight: 400; font-weight: 400;
color: #7A8185FF; color: #7A8185FF;
border-bottom: 1px solid #7A8185FF; border-bottom: 1px solid #7A8185FF;
display: block;
text-decoration: unset;
} }
.control_content_part_tree_el.right .txt_control_content_part_tree_el{ .control_content_part_tree_el.right .txt_control_content_part_tree_el{
margin-right: 7px; margin-right: 7px;
@@ -1991,6 +2006,12 @@ body.n_scroll{
align-items: center; align-items: center;
justify-content: right; justify-content: right;
width: 100%; width: 100%;
float: right;
position: sticky;
top: 61px;
background: #FFFFFF;
padding: 22px 22px;
z-index: 1000;
} }
.container_open_doc_curtain_txt{ .container_open_doc_curtain_txt{
@@ -2011,3 +2032,17 @@ body.n_scroll{
height: 10px; height: 10px;
display: block; display: block;
} }
.btn_download_in_pdf{
padding: 18px 90px;
background: #0C54A0;
color: #FFFFFF;
font-size: 16px;
font-weight: 600;
text-decoration: unset;
border-radius: 5px;
display: block;
margin-top: 20px;
width: fit-content;
text-transform: uppercase;
}

View File

@@ -6,7 +6,25 @@
} }
@media(max-width: 1150px){
.flex_container_buttons_3d_security_designer{
display: block;
}
.flex_container_buttons_3d_security_designer .btn_download_plugin {
width: 100%;
margin-right: 0;
}
.flex_container_buttons_3d_security_designer .btn_inf_about_plugin {
width: 100%;
margin-top: 20px;
margin-left: 0;
}
}
@media (max-width: 1024px) { @media (max-width: 1024px) {
.one_item_documentation_switcher_content_part{
font-size: 12px;
}
.cur_documentation_version{ .cur_documentation_version{
font-size: 12px; font-size: 12px;
} }
@@ -50,7 +68,7 @@
} }
.tree_documentation_container { .tree_documentation_container {
width: unset; width: unset;
height: 100vh; height: calc(100vh - 172px);
overflow-y: auto; overflow-y: auto;
padding: 0 15px; padding: 0 15px;
@@ -61,6 +79,7 @@
} }
.breadcrumbs_documentation_block{ .breadcrumbs_documentation_block{
margin-top: 90px; margin-top: 90px;
margin-bottom: 2px;
} }
.container_img_card_contacts{ .container_img_card_contacts{
height: 250px; height: 250px;

View File

@@ -16,6 +16,7 @@ $(document).ready(function (){
setInfInCurtainDocumentationMobile() setInfInCurtainDocumentationMobile()
setButtonOpenMobileDocCurtain() setButtonOpenMobileDocCurtain()
} }
windowScrollDocPage()
}) })
function setButtonOpenMobileDocCurtain () { function setButtonOpenMobileDocCurtain () {
@@ -55,7 +56,7 @@ function setButtonOpenMobileDocCurtain () {
$picture.appendChild($img) $picture.appendChild($img)
$($cont).insertBefore($content) $($cont).insertAfter($(".breadcrumbs_documentation_block"))
} }
function setInfInCurtainDocumentationMobile () { function setInfInCurtainDocumentationMobile () {
@@ -98,6 +99,7 @@ function setInfInCurtainDocumentationMobile () {
} }
function openDocCurtainMobile () { function openDocCurtainMobile () {
$("body").css({'overflow':'hidden'})
let $curtain = $(".left_curtain_documentation") let $curtain = $(".left_curtain_documentation")
let $block_overlay = $(".block_overlay") let $block_overlay = $(".block_overlay")
$curtain.css({left:0}) $curtain.css({left:0})
@@ -107,6 +109,7 @@ function openDocCurtainMobile () {
} }
function closeDocCurtainMobile () { function closeDocCurtainMobile () {
$("body").css({'overflow':'unset'})
let $curtain = $(".left_curtain_documentation") let $curtain = $(".left_curtain_documentation")
let $block_overlay = $(".block_overlay") let $block_overlay = $(".block_overlay")
$curtain.css({left:'-320px'}) $curtain.css({left:'-320px'})
@@ -507,22 +510,28 @@ function transitToDocumentation() {
window.location.href = window.location.origin + '/' + getLang() + '/docs/3dsd/' window.location.href = window.location.origin + '/' + getLang() + '/docs/3dsd/'
} }
function openVersionSwitcher(el){ let switcherWorking = false
let $parent = el.closest(".documentation_version_switcher")
let $content_part = $parent.querySelector(".documentation_switcher_content_part")
let $arrow = $parent.querySelector(".documentation_switcher_arrow_picture")
$content_part.classList.toggle("hidden")
if ($arrow.style.rotate === '0deg' || $arrow.style.rotate === '') {
$($arrow).animate({rotate: '180deg'},200)
let height = $content_part.offsetHeight
$content_part.style.bottom = '-' + height + "px"
$parent.style.borderBottom = '1px solid #fff'
} else {
$($arrow).animate({rotate: '0deg'},200)
$parent.style.borderBottom = '1px solid #CCCED1FF'
}
$("body")[0].setAttribute("onclick",'closeVersionSwitcherOnBody()') function openVersionSwitcher(el){
if (!switcherWorking){
switcherWorking = true
let $parent = el.closest(".documentation_version_switcher")
let $content_part = $parent.querySelector(".documentation_switcher_content_part")
let $arrow = $parent.querySelector(".documentation_switcher_arrow_picture")
$content_part.classList.toggle("hidden")
if ($arrow.style.rotate === '0deg' || $arrow.style.rotate === '') {
$($arrow).css({rotate: '180deg'})
let height = $content_part.offsetHeight
$content_part.style.bottom = '-' + height + "px"
$parent.style.borderBottom = '1px solid #fff'
$("body")[0].setAttribute("onclick",'closeVersionSwitcherOnBody()')
} else {
$($arrow).css({rotate: '0deg'})
$parent.style.borderBottom = '1px solid #CCCED1FF'
$("body")[0].setAttribute("onclick",'')
}
switcherWorking = false
}
} }
function closeVersionSwitcherOnBody () { function closeVersionSwitcherOnBody () {
@@ -532,9 +541,19 @@ function closeVersionSwitcherOnBody () {
$version_switcher_container_content.addClass("hidden") $version_switcher_container_content.addClass("hidden")
$(".documentation_version_switcher").css({borderBottom: '1px solid #CCCED1FF'}) $(".documentation_version_switcher").css({borderBottom: '1px solid #CCCED1FF'})
if ($arrow.style.rotate !== '180deg'){ if ($arrow.style.rotate !== '180deg'){
$($arrow).animate({rotate: '180deg'},200) $($arrow).css({rotate: '180deg'})
} else { } else {
$($arrow).animate({rotate: '0deg'},200) $($arrow).css({rotate: '0deg'})
}
if ($('.documentation_switcher_arrow_picture')[1]){
let arrow1 = $('.documentation_switcher_arrow_picture')[1]
if (arrow1.style.rotate !== '180deg'){
$(arrow1).css({rotate: '180deg'})
} else {
$(arrow1).css({rotate: '0deg'})
}
} }
$("body")[0].setAttribute("onclick",'') $("body")[0].setAttribute("onclick",'')
} }
@@ -578,13 +597,75 @@ function showContentPartTree (el) {
let $arrow = $parent.querySelector(".tree_documentation_arrow_img") let $arrow = $parent.querySelector(".tree_documentation_arrow_img")
$content_part.classList.toggle("hidden") $content_part.classList.toggle("hidden")
if ($arrow.style.rotate === '0deg' || $arrow.style.rotate === ''){ if ($arrow.style.rotate === '0deg' || $arrow.style.rotate === ''){
$($arrow).animate({rotate: '180deg'}) $($arrow).css({rotate: '90deg'})
} else { } else {
$($arrow).animate({rotate: '0deg'}) $($arrow).css({rotate: '0deg'})
}
let scroll = $(window)[0].scrollY
if ($(".left_curtain_documentation")[1]) {
$($(".left_curtain_documentation")[1]).find(".tree_documentation_container").css({height: 'fit-content'})
maxScroll = scroll + $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[1].offsetHeight - 172
$($(".left_curtain_documentation")[1]).find(".tree_documentation_container").css({height: 'calc(100vh - 300px)'})
} }
} }
let waitingTop = null let waitingTop = null
let maxScroll = null let maxScroll = null
function windowScrollDocPage (){
if (getInfoAboutUser()[0] !== 'laptop' && getInfoAboutUser()[0] !== 'mobile'){
if (window.location.href.includes("docs")){
let $curtain = $(".left_curtain_documentation")
let scroll = $(window)[0].scrollY
if (scroll === 0){
waitingTop = $(".left_curtain_documentation")[0].getBoundingClientRect().top - 172
$(".left_curtain_documentation").find(".tree_documentation_container").css({height: 'fit-content'})
maxScroll = $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172
if (scroll !== 0){
maxScroll = scroll + $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172
}
$(".left_curtain_documentation").find(".tree_documentation_container").css({height: 'calc(100vh - 300px)'})
}
let $new_curtain = $($curtain[1])
if (scroll < maxScroll || !maxScroll){
if (!$curtain[1] && waitingTop){
$new_curtain = $curtain.clone()
$new_curtain.insertAfter($curtain)
let $new_curtain_tree = $new_curtain.find(".tree_documentation_container")
$new_curtain_tree.css({height: 'calc(100vh - 245px);'})
}
if (scroll >= waitingTop && waitingTop){
$new_curtain.css({position:'fixed',top: 166,bottom:"unset"})
$($curtain[0]).css({opacity:0})
$($curtain[0]).find(".tree_documentation_container").css({display:'none'})
} else if (scroll < waitingTop && waitingTop) {
$curtain.find(".tree_documentation_container")[0].innerHTML = $new_curtain.find(".tree_documentation_container")[0].innerHTML
$new_curtain.remove()
$($curtain[0]).css({opacity:1})
$($curtain[0]).find(".tree_documentation_container").css({display:'block'})
} else if (!waitingTop){
waitingTop = $(".left_curtain_documentation")[0].getBoundingClientRect().top - 172
$(".left_curtain_documentation").find(".tree_documentation_container").css({height: 'fit-content'})
maxScroll = $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172
if (scroll !== 0){
maxScroll = scroll + $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172
}
$(".left_curtain_documentation").find(".tree_documentation_container").css({height: 'calc(100vh - 300px)'})
}
} else {
if (!$curtain[1]){
$new_curtain = $curtain.clone()
$new_curtain.insertAfter($curtain)
let $new_curtain_tree = $new_curtain.find(".tree_documentation_container")
$new_curtain_tree.css({height: 'calc(100vh - 245px);'})
}
$new_curtain.find(".tree_documentation_container").css({height:'fit-content'})
$new_curtain.css({position:'absolute',bottom: 0,top: 'unset'})
$($curtain[0]).css({opacity:0})
}
}
}
}
$(window).scroll(function (){ $(window).scroll(function (){
if (getInfoAboutUser()[0] !== 'laptop' && getInfoAboutUser()[0] !== 'mobile'){ if (getInfoAboutUser()[0] !== 'laptop' && getInfoAboutUser()[0] !== 'mobile'){
if (window.location.href.includes("docs")){ if (window.location.href.includes("docs")){
@@ -592,29 +673,48 @@ $(window).scroll(function (){
let scroll = $(window)[0].scrollY let scroll = $(window)[0].scrollY
if (scroll === 0){ if (scroll === 0){
waitingTop = $(".left_curtain_documentation")[0].getBoundingClientRect().top - 172 waitingTop = $(".left_curtain_documentation")[0].getBoundingClientRect().top - 172
$(".left_curtain_documentation").find(".tree_documentation_container").css({height: 'fit-content'})
maxScroll = $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172 maxScroll = $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172
if (scroll !== 0){
maxScroll = scroll + $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172
}
$(".left_curtain_documentation").find(".tree_documentation_container").css({height: 'calc(100vh - 300px)'})
} }
let $new_curtain = $($curtain[1]) let $new_curtain = $($curtain[1])
if (scroll < maxScroll || !maxScroll){ if (scroll < maxScroll || !maxScroll){
if (!$curtain[1] && waitingTop){ if (!$curtain[1] && waitingTop){
$new_curtain = $curtain.clone() $new_curtain = $curtain.clone()
$new_curtain.insertAfter($curtain) $new_curtain.insertAfter($curtain)
let $new_curtain_tree = $new_curtain.find(".tree_documentation_container")
$new_curtain_tree.css({height: 'calc(100vh - 245px);'})
} }
if (scroll >= waitingTop && waitingTop){ if (scroll >= waitingTop && waitingTop){
$new_curtain.css({position:'fixed',top: 166,bottom:"unset"}) $new_curtain.css({position:'fixed',top: 166,bottom:"unset"})
$($curtain[0]).css({opacity:0}) $($curtain[0]).css({opacity:0})
$($curtain[0]).find(".tree_documentation_container").css({display:'none'})
} else if (scroll < waitingTop && waitingTop) { } else if (scroll < waitingTop && waitingTop) {
$curtain.find(".tree_documentation_container")[0].innerHTML = $new_curtain.find(".tree_documentation_container")[0].innerHTML
$new_curtain.remove() $new_curtain.remove()
$($curtain[0]).css({opacity:1}) $($curtain[0]).css({opacity:1})
$($curtain[0]).find(".tree_documentation_container").css({display:'block'})
} else if (!waitingTop){ } else if (!waitingTop){
waitingTop = $(".left_curtain_documentation")[0].getBoundingClientRect().top - 172 waitingTop = $(".left_curtain_documentation")[0].getBoundingClientRect().top - 172
$(".left_curtain_documentation").find(".tree_documentation_container").css({height: 'fit-content'})
maxScroll = $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172 maxScroll = $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172
if (scroll !== 0){
maxScroll = scroll + $(".documentation_block")[0].getBoundingClientRect().bottom - $(".left_curtain_documentation")[0].offsetHeight - 172
}
$(".left_curtain_documentation").find(".tree_documentation_container").css({height: 'calc(100vh - 300px)'})
} }
} else { } else {
if (!$curtain[1]){ if (!$curtain[1]){
$new_curtain = $curtain.clone() $new_curtain = $curtain.clone()
$new_curtain.insertAfter($curtain) $new_curtain.insertAfter($curtain)
let $new_curtain_tree = $new_curtain.find(".tree_documentation_container")
$new_curtain_tree.css({height: 'calc(100vh - 245px);'})
} }
$new_curtain.find(".tree_documentation_container").css({height:'fit-content'})
$new_curtain.css({position:'absolute',bottom: 0,top: 'unset'}) $new_curtain.css({position:'absolute',bottom: 0,top: 'unset'})
$($curtain[0]).css({opacity:0}) $($curtain[0]).css({opacity:0})
} }

View File

@@ -0,0 +1,3 @@
<svg width="7" height="12" viewBox="0 0 7 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.53362 6.53082L1.06056 12.0028L-4.63675e-08 10.942L4.94258 6.00043L-3.60497e-07 1.05882L1.06056 -0.00193982L6.53362 5.47005C6.67431 5.61071 6.75335 5.8015 6.75335 6.00043C6.75335 6.19937 6.67431 6.39016 6.53362 6.53082Z" fill="#0C54A0"/>
</svg>

After

Width:  |  Height:  |  Size: 390 B

View File

@@ -30,6 +30,7 @@
</div> </div>
<div class="container_els_curtain"> <div class="container_els_curtain">
{# <a class="txt_curtain_el standart_txt">{% translate "Поддержка" %}</a>#} {# <a class="txt_curtain_el standart_txt">{% translate "Поддержка" %}</a>#}
{# <a href="{% url 'docs_main' %}" class="txt_curtain_el standart_txt">{% translate "Поддержка" %}</a>#}
<a href="{% url 'contacts' %}" class="txt_curtain_el standart_txt">{% translate "Контакты" %}</a> <a href="{% url 'contacts' %}" class="txt_curtain_el standart_txt">{% translate "Контакты" %}</a>
</div> </div>

View File

@@ -0,0 +1,56 @@
{% load static %}
{% load i18n %}
{% if pdf_render %}
<HEAD>
{# <meta charset="windows-1251">#}
<meta charset="UTF-8">
{% include 'head_includes/fonts_include.html' %}
<style>
* {
font-family: -apple-system, 'Roboto', sans-serif;
}
</style>
</HEAD>
{% endif %}
<div class="content_part_tree_els">
{# <div class="name_article_tree">#}
{# #}
{# </div>#}
{# <div class="description_article_tree">#}
{# {{ cur_article.text }}#}
{# </div>#}
{{ cur_article.text|safe }}
{% if not pdf_render %}
<div class="controls_content_part_tree_els">
<div class="control_content_part_tree_el left">
{% if prev_article %}
<picture class="arrow_control_content_part_tree_el_picture">
<source srcset="{% static "images/arrow_control_part_tree_el.svg" %}">
<img class="arrow_control_content_part_tree_el_img" src="{% static "images/arrow_control_part_tree_el.svg" %}" alt="">
</picture>
<div class="txt_control_content_part_tree_el" data-url="{% url 'docs_art_page' cur_version.url prev_article.url %}" onclick="changeCurArticle(this)">
{% trans "Предыдущий" %}
</div>
{% endif %}
</div>
<div class="control_content_part_tree_el right">
{% if next_article %}
<div class="txt_control_content_part_tree_el" data-url="{% url 'docs_art_page' cur_version.url next_article.url %}" onclick="changeCurArticle(this)">
{% trans "Следующий" %}
</div>
<picture class="arrow_control_content_part_tree_el_picture">
<source srcset="{% static "images/arrow_control_part_tree_el.svg" %}">
<img class="arrow_control_content_part_tree_el_img" src="{% static "images/arrow_control_part_tree_el.svg" %}" alt="">
</picture>
{% endif %}
</div>
</div>
<a class="btn_download_in_pdf" target="_blank" href="?pdf=true">{% trans "Скачать в PDF" %}</a>
{% endif %}
</div>

View File

@@ -10,6 +10,9 @@
</a> </a>
<div class="right_part_header"> <div class="right_part_header">
{# <a class="standart_txt text_header pointer">Поддержка</a>#} {# <a class="standart_txt text_header pointer">Поддержка</a>#}
{% if allow_documentation %}
{# <a href="{% url 'docs_main' %}" class="standart_txt text_header last_left pointer">{% trans "Поддержка" %}</a>#}
{% endif %}
<a href="{% url 'contacts' %}" class="standart_txt text_header last_left pointer">{% translate "Контакты" %}</a> <a href="{% url 'contacts' %}" class="standart_txt text_header last_left pointer">{% translate "Контакты" %}</a>
<div class="splitter_text_header"></div> <div class="splitter_text_header"></div>
<div class="language_select close"> <div class="language_select close">

View File

@@ -0,0 +1,30 @@
{% load i18n fb_versions %}
<input id="{{ final_attrs.id }}" type="text" class="vFileBrowseField{% if final_attrs.class %} {{ final_attrs.class }}{% endif %}" style="width: 80%;" name="{{ final_attrs.name }}" value="{{ value.path }}" {% for k, v in final_attrs.data_attrs.items %}{{k}}="{{v}}" {% endfor %}/>
<a href="#" onclick="FileBrowser.show(this.parentNode.getElementsByTagName('input')[0].id, '{{ url }}?pop=1{% if final_attrs.directory %}&amp;dir={{ final_attrs.directory|urlencode|urlencode }}{% endif %}{% if final_attrs.format %}&amp;filter={{ final_attrs.format }}{% endif %}');" class="fb_show">
<img src="{{ final_attrs.search_icon }}" style="margin: 5px 0 0 10px;" alt="{% trans "Change" %}" />
</a>
{% if value.filetype == "Image" and value.exists %}
{% version value.path final_attrs.ADMIN_THUMBNAIL as thumbnail_version %}
{% if thumbnail_version %}
<p class="preview" id="preview_{{ final_attrs.id }}">
<a href="{{ value.url }}" target="_blank" id="previewlink_{{ final_attrs.id }}">
<img id="previewimage_{{ final_attrs.id }}" src="{{ thumbnail_version.url }}" class="preview" />
</a>
</p>
{% else %}
<p class="preview" id="preview_{{ final_attrs.id }}" style="display: none;">
<a href="javascript://" target="_self" id="previewlink_{{ final_attrs.id }}">
<img id="previewimage_{{ final_attrs.id }}" class="preview" src="" />
</a>
</p>
{% endif %}
{% else %}
<p class="preview" id="preview_{{ final_attrs.id }}" style="display: none;">
<a href="javascript://" target="_self" id="previewlink_{{ final_attrs.id }}">
<img id="previewimage_{{ final_attrs.id }}" class="preview" src="" />
</a>
</p>
{% endif %}
{% if value and not value.exists %}
<ul class="errorlist"><li>{% trans "File not found" %}</li></ul>
{% endif %}

View File

@@ -4,7 +4,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
{# <link href="https://fonts.googleapis.com/css2?family=Verdana&display=swap" rel="stylesheet">#} {# <link href="https://fonts.googleapis.com/css2?family=Verdana&display=swap" rel="stylesheet">#}
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet"> <link rel="preload" href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" as="font" type="font/woff2" crossorigin>
{# <link rel="stylesheet" href="{% static "fonts/fonts.css" %}">#} {# <link rel="stylesheet" href="{% static "fonts/fonts.css" %}">#}
{#<link rel="stylesheet" href="{% static "fonts/Raleway-Black.ttf" %}">#} {#<link rel="stylesheet" href="{% static "fonts/Raleway-Black.ttf" %}">#}

View File

@@ -25,9 +25,9 @@
{# Документация для версии 1#} {# Документация для версии 1#}
{# </div>#} {# </div>#}
{% for name,url in breadcrumbs.items %} {% for name,url in breadcrumbs.items %}
<div class="way_bread_crumb{% if forloop.last %} last{% endif %}" {% if not forloop.last %}data-url="{{ url }}"{% endif %} onclick="breadCrumbGo(this)"> <a class="way_bread_crumb{% if forloop.last %} last{% endif %}" {% if not forloop.last %}href="{{ url }}"{% endif %}>
{{ name }} {{ name }}
</div> </a>
{% if not forloop.last %} {% if not forloop.last %}
<picture class="breadcrumb_arrow_picture"> <picture class="breadcrumb_arrow_picture">
<source srcset="{% static "images/breadcrumb_arrow.svg" %}"> <source srcset="{% static "images/breadcrumb_arrow.svg" %}">
@@ -59,63 +59,54 @@
<div class="documentation_switcher_content_part hidden"> <div class="documentation_switcher_content_part hidden">
{% for item in allow_versions %} {% for item in allow_versions %}
<div class="one_item_documentation_switcher_content_part" data-url="{% url 'docs_version_page' item.url %}" data-title="{{ item.name }}" onclick="chooseVersionComplete(this)"> <a class="one_item_documentation_switcher_content_part" href="{% url 'docs_version_page' item.url %}" data-title="{{ item.name }}">
{{ item.name }} {{ item.name }}
</div> </a>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
</div> </div>
<div class="tree_documentation_container"> <div class="tree_documentation_container">
{% for name, obj in doc_tree.items %} {% for id, obj in doc_tree.items %}
<div class="tree_documentation_container_first_level"> <div class="tree_documentation_container_first_level">
<div class="tree_documentation_container_first_line"> <div class="tree_documentation_container_first_line">
{% if obj.children %} {% if obj.children %}
<picture class="tree_documentation_arrow_picture" onclick="showContentPartTree(this)"> <picture class="tree_documentation_arrow_picture" onclick="showContentPartTree(this)" {% if obj.active %}style="rotate: 90deg;"{% endif %}>
<source srcset="{% static "images/arrow_for_documentation_switcher.svg" %}"> <source srcset="{% static "images/arrow_for_doc_tree.svg" %}">
<img class="tree_documentation_arrow_img" src="{% static "images/arrow_for_documentation_switcher.svg" %}" alt=""> <img class="tree_documentation_arrow_img" src="{% static "images/arrow_for_doc_tree.svg" %}" alt="">
</picture> </picture>
{% endif %} {% endif %}
<div class="tree_documentation_container_first_level_txt {% if not obj.children %}margin {% endif %}{% if cur_article.url == obj.url %}chose{% endif %}" onclick="choseItemTreeDocumentation(this)" data-url="{% url 'docs_art_page' cur_version.url obj.url %}"> <a class="tree_documentation_container_first_level_txt {% if not obj.children %}margin {% endif %}{% if cur_article.url == obj.url %}chose{% endif %}" href="{% url 'docs_art_page' cur_version.url obj.url %}">
{{ name }} {{ obj.name }}
</div> </a>
</div> </div>
{% if obj.children %} {% if obj.children %}
<div class="content_part_tree_documentation_container {% if not obj.active %}hidden{% endif %}"> <div class="content_part_tree_documentation_container {% if not obj.active %}hidden{% endif %}">
{% for name, obj in obj.children.items %} {% for id, obj in obj.children.items %}
<div class="tree_documentation_container_second_level"> <div class="tree_documentation_container_second_level">
<div class="tree_documentation_container_first_line"> <div class="tree_documentation_container_first_line">
{% if obj.children %} {% if obj.children %}
<picture class="tree_documentation_arrow_picture" onclick="showContentPartTree(this)"> <picture class="tree_documentation_arrow_picture" onclick="showContentPartTree(this)" {% if obj.active %}style="rotate: 90deg;"{% endif %}>
<source srcset="{% static "images/arrow_for_documentation_switcher.svg" %}"> <source srcset="{% static "images/arrow_for_doc_tree.svg" %}">
<img class="tree_documentation_arrow_img" src="{% static "images/arrow_for_documentation_switcher.svg" %}" alt=""> <img class="tree_documentation_arrow_img" src="{% static "images/arrow_for_doc_tree.svg" %}" alt="">
</picture> </picture>
{% endif %} {% endif %}
<div class="tree_documentation_container_second_level_txt {% if not obj.children %}margin {% endif %}{% if cur_article.url == obj.url %}chose{% endif %}" data-url="{% url 'docs_art_page' cur_version.url obj.url %}" onclick="choseItemTreeDocumentation(this)"> <a class="tree_documentation_container_second_level_txt {% if not obj.children %}margin {% endif %}{% if cur_article.url == obj.url %}chose{% endif %}" href="{% url 'docs_art_page' cur_version.url obj.url %}">
{{ name }} {{ obj.name }}
</div> </a>
</div> </div>
{% if obj.children %} {% if obj.children %}
{% for name,obj in obj.children.items %} <div class="content_part_tree_documentation_container min_padding {% if not obj.active %}hidden{% endif %}">
<div class="content_part_tree_documentation_container min_padding hidden"> <div class="elements_third_level_content_part_tree">
<div class="elements_third_level_content_part_tree"> {% for id,obj in obj.children.items %}
<div class="element_third_level_content_part_tree {% if cur_article.url == obj.url %}chose{% endif %}" onclick="choseItemTreeDocumentation(this)" data-url="{% url 'docs_art_page' cur_version.url obj.url %}"> <a class="element_third_level_content_part_tree {% if cur_article.url == obj.url %}chose{% endif %}" href="{% url 'docs_art_page' cur_version.url obj.url %}">
{{ name }} {{ obj.name }}
</div> </a>
<div class="element_third_level_content_part_tree {% if cur_article.url == obj.url %}chose{% endif %}" onclick="choseItemTreeDocumentation(this)" data-url="{% url 'docs_art_page' cur_version.url obj.url %}"> {% endfor %}
{{ name }}
</div>
<div class="element_third_level_content_part_tree {% if cur_article.url == obj.url %}chose{% endif %}" onclick="choseItemTreeDocumentation(this)" data-url="{% url 'docs_art_page' cur_version.url obj.url %}">
{{ name }}
</div>
<div class="element_third_level_content_part_tree {% if cur_article.url == obj.url %}chose{% endif %}" onclick="choseItemTreeDocumentation(this)" data-url="{% url 'docs_art_page' cur_version.url obj.url %}">
{{ name }}
</div>
</div>
</div> </div>
{% endfor %} </div>
{% endif %} {% endif %}
</div> </div>
@@ -126,35 +117,7 @@
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
<div class="content_part_tree_els"> {% include "blocks/b_documentation_article.html" %}
{# <div class="name_article_tree">#}
{# #}
{# </div>#}
{# <div class="description_article_tree">#}
{# {{ cur_article.text }}#}
{# </div>#}
{{ cur_article.text|safe }}
<div class="controls_content_part_tree_els">
<div class="control_content_part_tree_el left">
<picture class="arrow_control_content_part_tree_el_picture">
<source srcset="{% static "images/arrow_control_part_tree_el.svg" %}">
<img class="arrow_control_content_part_tree_el_img" src="{% static "images/arrow_control_part_tree_el.svg" %}" alt="">
</picture>
<div class="txt_control_content_part_tree_el" data-url="{% url 'docs_art_page' cur_version.url prev_article.url %}" onclick="changeCurArticle(this)">
{% trans "Предыдущий" %}
</div>
</div>
<div class="control_content_part_tree_el right">
<div class="txt_control_content_part_tree_el" data-url="{% url 'docs_art_page' cur_version.url next_article.url %}" onclick="changeCurArticle(this)">
{% trans "Следующий" %}
</div>
<picture class="arrow_control_content_part_tree_el_picture">
<source srcset="{% static "images/arrow_control_part_tree_el.svg" %}">
<img class="arrow_control_content_part_tree_el_img" src="{% static "images/arrow_control_part_tree_el.svg" %}" alt="">
</picture>
</div>
</div>
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}