Compare commits

...

72 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
SBD
ef6aa3793c documentation page 2024-07-14 14:44:46 +03:00
SBD
6339858f42 change article 2024-07-13 02:04:05 +03:00
SDE
9d20b1c8fe 0.5.9 documentation prev and next article navigation 2024-07-12 21:23:42 +03:00
SBD
c9d591fa40 scroll doc page 2024-07-12 19:32:49 +03:00
SBD
b5086cbd40 documentation page 2024-07-12 17:41:43 +03:00
SBD
e586293ae0 tree 2024-07-11 19:17:29 +03:00
SDE
a36401af3e 0.5.8 documentation breadcrumbs 2024-07-11 18:56:48 +03:00
SDE
d83fb3c74a 0.5.7 documentation versions selector 2024-07-11 18:40:51 +03:00
SDE
b160fb7256 0.5.6 documentation 2024-07-11 18:37:29 +03:00
SBD
37d61847ae tree 2024-07-11 18:16:19 +03:00
SBD
ee09e0e907 tree 2024-07-11 17:34:08 +03:00
SDE
579094ac18 0.5.5 documentation 2024-07-11 16:58:58 +03:00
SDE
b576e4f224 0.5.4 documentation 2024-07-11 16:16:57 +03:00
SBD
aafa989501 fix documentation scroll 2024-07-11 15:14:51 +03:00
SDE
1aeb83d571 0.5.3 documentation 2024-07-11 15:06:06 +03:00
SDE
5272d7503f 0.5.2 documentation 2024-07-11 13:28:25 +03:00
SBD
66f721d5bf fix documentation scroll 2024-07-11 00:16:14 +03:00
SBD
36508a6605 documentation page 2024-07-10 18:03:18 +03:00
SDE
4d78fa8e54 Merge remote-tracking branch 'origin/main' 2024-07-10 14:51:31 +03:00
SDE
e80331c978 0.5.1 documentation 2024-07-10 14:51:24 +03:00
56 changed files with 2714 additions and 50 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):
@@ -346,6 +346,23 @@ def translit(locallangstring):
return ''.join(translitstring) return ''.join(translitstring)
def create_url(data, model):
url = None
objs = True
i = 0
while objs:
url = url_translit(data['name'])
if i > 0:
url += f'_{str(i)}'
objs = model.objects.filter(url=url)
i += 1
return url
def slugify_text(str_text): def slugify_text(str_text):
utf8_code = False utf8_code = False
try: try:

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

@@ -1,3 +1,196 @@
from django.contrib import admin from django.contrib import admin
from sets.admin import *
from .models import *
from BaseModels.admin_utils import Admin_BaseIconModel
from super_inlines.admin import SuperInlineModelAdmin, SuperModelAdmin
from django.utils.translation import gettext as _
from django import forms
from django.utils.text import slugify
from django.db.models import Min
from django.contrib import messages
# Register your models here.
class DocArtForm(forms.ModelForm):
class Meta:
model = DocArt
fields = '__all__'
def __init__(self, *args, **kwargs):
super(DocArtForm, self).__init__(*args, **kwargs)
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):
form = DocArtForm
def show_versions(self, obj):
versions = obj.versions.filter(enable=True).values_list('name', flat=True)
if versions:
return ' - '.join(versions)
return '-'
show_versions.short_description = _('Версии')
def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.annotate(
min_version_order=Min('versions__order'),
max_version_name=Min('versions__name'),
).order_by('min_version_order', 'max_version_name', 'order').distinct()
return queryset
fieldsets = [
(None, {
'classes': ['wide'],
'fields': (
'name', 'url',
'enable',
'parent',
'versions',
'order',
# 'title',
# 'description',
'text',
# 'picture',
)
}),
# ('SEO', {
# 'classes': ['wide', 'collapse'],
# 'fields': (
# 'seo_title', 'seo_description', 'seo_keywords', 'seo_text',
# )
# }),
]
list_display = [
'id', 'enable',
'name', 'url',
'show_versions',
# 'versions',
'parent',
'order', 'modifiedDT', 'createDT'
]
# ordering = [
# # 'versions',
# 'order', 'name']
prepopulated_fields = {"url": ("name_en",)}
list_display_links = ['id', 'name']
list_editable = ['enable', 'order']
filter_horizontal = ['versions']
list_filter = [
'versions',
'modifiedDT', 'createDT',
]
search_fields = ['name', 'title']
# filter_horizontal = ['options']
# inlines = [Admin_StackedInline_Block]
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=_("Создать копии выбранных статей"))
def create_copy_arts(self, request, queryset):
from BaseModels.functions import create_url
for obj in queryset:
obj.name += '-копия'
obj.parent = None
obj.url = create_url({'name': obj.name}, DocArt)
obj.pk = None
obj.save()
self.message_user(
request,
_('Копии успешно созданы')
)
admin.site.register(DocArt, Admin_DocArt)
class Admin_DocVersion(Admin_BaseIconModel):
fieldsets = [
(None, {
'classes': ['wide'],
'fields': (
'name', 'url', 'enable', 'order',
)
}),
# ('SEO', {
# 'classes': ['wide', 'collapse'],
# 'fields': (
# 'seo_title', 'seo_description', 'seo_keywords', 'seo_text',
# )
# }),
]
list_display = [
'id', 'enable',
'name', 'url',
# 'title',
'order', 'modifiedDT', 'createDT'
]
# ordering = ['section', 'parent_service', 'order']
# prepopulated_fields = {"url": ("name",)}
list_display_links = ['id', 'name']
list_editable = ['enable', 'order']
list_filter = [
# 'section', 'parent_service',
'modifiedDT', 'createDT',
]
search_fields = ['name']
# filter_horizontal = ['options']
# inlines = [Admin_StackedInline_Block]
admin.site.register(DocVersion, Admin_DocVersion)

0
DocsApp/funcs.py Normal file
View File

View File

@@ -0,0 +1,65 @@
# Generated by Django 4.2.7 on 2024-07-10 16:02
import BaseModels.base_models
import ckeditor_uploader.fields
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='DocVersion',
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='Дополнительные данные')),
('url', models.TextField(help_text='можно изменить адрес страницы (!!! ВНИМАНИЕ !!! поисковые системы потеряют страницу и найдут лишь спустя неделю...месяц)', unique=True, verbose_name='URL привязанной страницы')),
],
options={
'verbose_name': 'Версия документации',
'verbose_name_plural': 'Версии документации',
},
),
migrations.CreateModel(
name='DocArt',
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='Дополнительные данные')),
('url', models.TextField(help_text='можно изменить адрес страницы (!!! ВНИМАНИЕ !!! поисковые системы потеряют страницу и найдут лишь спустя неделю...месяц)', unique=True, verbose_name='URL привязанной страницы')),
('title', models.TextField(blank=True, null=True, verbose_name='Заголовок')),
('description', ckeditor_uploader.fields.RichTextUploadingField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание')),
('picture', models.FileField(blank=True, null=True, upload_to='uploads/', validators=[BaseModels.base_models.validate_file_extension], verbose_name='Картинка')),
('visible', models.BooleanField(default=True, verbose_name='Отображать')),
('seo_title', models.CharField(blank=True, max_length=250, null=True, verbose_name='Title (80 знаков)')),
('seo_description', models.CharField(blank=True, max_length=250, null=True, verbose_name='Description (150 знаков)')),
('seo_keywords', models.CharField(blank=True, max_length=250, null=True, verbose_name='Keywords (200 знаков)')),
('seo_text', ckeditor_uploader.fields.RichTextUploadingField(blank=True, null=True, verbose_name='Текст SEO статьи')),
('FAQ_title', models.CharField(blank=True, max_length=250, null=True, verbose_name='FAQ Заголовок')),
('text', ckeditor_uploader.fields.RichTextUploadingField(blank=True, null=True, verbose_name='Статья')),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='DocsApp.docart', verbose_name='Родитель')),
('versions', models.ManyToManyField(blank=True, to='DocsApp.docversion', verbose_name='Подключенные версии')),
],
options={
'verbose_name': 'Статья документации',
'verbose_name_plural': 'Статьи документации',
},
),
]

View File

@@ -0,0 +1,59 @@
# Generated by Django 4.2.7 on 2024-07-10 16:12
import ckeditor_uploader.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('DocsApp', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='docart',
name='description_en',
field=ckeditor_uploader.fields.RichTextUploadingField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание'),
),
migrations.AddField(
model_name='docart',
name='description_ru',
field=ckeditor_uploader.fields.RichTextUploadingField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание'),
),
migrations.AddField(
model_name='docart',
name='name_en',
field=models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название'),
),
migrations.AddField(
model_name='docart',
name='name_ru',
field=models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название'),
),
migrations.AddField(
model_name='docart',
name='text_en',
field=ckeditor_uploader.fields.RichTextUploadingField(blank=True, null=True, verbose_name='Полное описание'),
),
migrations.AddField(
model_name='docart',
name='text_ru',
field=ckeditor_uploader.fields.RichTextUploadingField(blank=True, null=True, verbose_name='Полное описание'),
),
migrations.AddField(
model_name='docart',
name='title_en',
field=models.TextField(blank=True, null=True, verbose_name='Заголовок'),
),
migrations.AddField(
model_name='docart',
name='title_ru',
field=models.TextField(blank=True, null=True, verbose_name='Заголовок'),
),
migrations.AlterField(
model_name='docart',
name='text',
field=ckeditor_uploader.fields.RichTextUploadingField(blank=True, null=True, verbose_name='Полное описание'),
),
]

View File

@@ -0,0 +1,24 @@
# Generated by Django 4.2.7 on 2024-07-10 17:56
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('DocsApp', '0002_docart_description_en_docart_description_ru_and_more'),
]
operations = [
migrations.AlterField(
model_name='docart',
name='parent',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rel_childArts_for_docArt', to='DocsApp.docart', verbose_name='Родитель'),
),
migrations.AlterField(
model_name='docart',
name='versions',
field=models.ManyToManyField(blank=True, related_name='rel_docArts_for_version', to='DocsApp.docversion', verbose_name='Подключенные версии'),
),
]

View File

@@ -1,3 +1,154 @@
from django.db import models from django.db import models
from BaseModels.base_models import BaseModelViewPage, BaseModel
from ckeditor_uploader.fields import RichTextUploadingField
from django.utils.translation import gettext_lazy as _
from datetime import datetime
# Create your models here. class DocVersion(BaseModel):
url = models.TextField(
verbose_name=_('URL привязанной страницы'), unique=True,
help_text=_('можно изменить адрес страницы (!!! ВНИМАНИЕ !!! поисковые системы потеряют страницу и найдут лишь спустя неделю...месяц)')
)
def get_article(self, art_url=None):
art = None
if art_url:
try:
art = self.rel_docArts_for_version.get(enable=True, url=art_url)
except DocArt.DoesNotExist:
art = None
if not art:
art = self.rel_docArts_for_version.filter(
enable=True, parent=None
).order_by('order').first()
return art
class Meta:
verbose_name = _('Версия документации')
verbose_name_plural = _('Версии документации')
ordering = ['order', 'name']
class DocArt(BaseModelViewPage):
parent = models.ForeignKey(
'DocArt', verbose_name=_('Родитель'),
null=True, blank=True,
on_delete=models.SET_NULL,
related_name='rel_childArts_for_docArt'
)
versions = models.ManyToManyField(
DocVersion, verbose_name=_('Подключенные версии'), blank=True,
related_name='rel_docArts_for_version'
)
# def save(self, not_change_modifiedDT=False, *args, **kwargs):
# if not not_change_modifiedDT:
# self.modifiedDT = datetime.now()
# super().save(*args, **kwargs)
def get_last_child(self, version):
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):
return self.versions.all().order_by('-order').first()
def get_children(self, version):
return self.rel_childArts_for_docArt.filter(enable=True)
def get_prev_article(self, version=None):
if not version:
version = self.get_last_version()
kwargs = {
'enable': True,
'versions': version,
'parent': self.parent
}
if self.order:
kwargs['order__lt'] = self.order
art = DocArt.objects.exclude(
id=self.id
).filter(**kwargs).order_by('-order').first()
if art:
while art.get_last_child(version=version):
art = art.get_last_child(version=version)
if not art and self.parent:
art = self.parent
return art
def get_next_article(self, version=None):
if not version:
version = self.get_last_version()
art = self.get_first_child(version=version)
if not art:
kwargs = {
'enable': True,
'versions': version,
'parent': self.parent
}
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:
art = DocArt.objects.filter(
enable=True,
versions=version,
order__gt=self.parent.order,
parent=self.parent.parent
).order_by('order').first()
return art
def get_parents_path(self, version_obj=None):
res = []
res_ids = []
res.append(self)
res_ids.append(self.id)
obj = self
while obj.parent:
res.insert(0, obj.parent)
res_ids.insert(0, obj.parent.id)
obj = obj.parent
return res, res_ids
def __str__(self):
if self.name:
s = self.name
else:
s = str(self.id)
if self.versions.count():
s += ' - v' + str(' - '.join(item.name for item in self.versions.filter(enable=True)))
return s
class Meta:
verbose_name = _('Статья документации')
verbose_name_plural = _('Статьи документации')
# ordering = ['order', 'name']

19
DocsApp/translation.py Normal file
View File

@@ -0,0 +1,19 @@
from modeltranslation.translator import translator, TranslationOptions
from .models import *
class DocArt_TranslationOptions(TranslationOptions):
fields = (
'name', 'description', 'text', 'title'
)
translator.register(DocArt, DocArt_TranslationOptions)
# class DocVersion_TranslationOptions(TranslationOptions):
# fields = (
# 'name', 'description', 'text', 'title', 'FAQ_title', 'seo_title', 'seo_description', 'seo_text'
# )
# translator.register(DocVersion, DocVersion_TranslationOptions)

View File

@@ -5,5 +5,7 @@ from django.conf import settings
from .views import * from .views import *
urlpatterns = [ urlpatterns = [
path('documentation/', DocsView, name='docs_main'), path('docs/3dsd/', DocsView, name='docs_main'),
path('docs/3dsd/v<str:version>/', DocsView, name='docs_version_page'),
path('docs/3dsd/v<str:version>/<str:art_url>/', DocsView, name='docs_art_page'),
] ]

View File

@@ -1,17 +1,191 @@
import json import json
import os
from django.http import HttpResponse, Http404, FileResponse from django.http import HttpResponse, Http404, FileResponse, HttpResponseRedirect
from django.template import loader, RequestContext from django.template import loader, RequestContext
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from .models import * from .models import *
from django.conf import settings from django.conf import settings
from GeneralApp.funcs import get_inter_http_respose 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 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):
docs_tree = OrderedDict()
docs_tree.update({
art_item.id: {
'url': art_item.url,
'name': art_item.name,
# 'id': art_item.id,
'children': get_tree_arts(art_item, arts, sel_arts_ids),
'active': art_item.id in sel_arts_ids
} for art_item in arts.filter(parent=art)
})
return docs_tree
def DocsView(request):
Dict = {}
t = loader.get_template('pages/p_documentation.html')
return get_inter_http_respose(t, Dict, request) def _response_pdf(path):
filePDF = open(path, 'rb')
content = filePDF.read()
# content = str(content)
filePDF.close()
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):
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 = {
'enable': True,
'url': art_url,
'versions__url': version,
}
try:
art = DocArt.objects.get(**kwargs)
try:
vers_obj = DocVersion.objects.get(enable=True, url=version)
except DocVersion.DoesNotExist:
raise Http404
active_arts, active_arts_ids = art.get_parents_path()
arts = DocArt.objects.filter(enable=True, versions=vers_obj).order_by('order')
doc_tree = get_tree_arts(None, arts, active_arts_ids)
versions = DocVersion.objects.exclude(
rel_docArts_for_version=None
).filter(
enable=True,
).order_by('order', 'name')
breadcrumbs = OrderedDict({
'Документация и техническая поддержка': reverse('docs_main'),
f'Документация для версии {version}': reverse(
'docs_version_page', kwargs={'version': version}),
})
breadcrumbs.update({
item.name: reverse(
'docs_art_page', kwargs={'version': version, 'art_url': item.url}
) for item in active_arts
})
Dict = {
'cur_article': art,
'cur_version': vers_obj,
'doc_tree': doc_tree,
'allow_versions': versions,
'breadcrumbs': breadcrumbs,
'prev_article': art.get_prev_article(version=vers_obj),
'next_article': art.get_next_article(version=vers_obj),
'pdf_render': generate_pdf
}
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:
raise Http404
if version:
try:
vers_obj = DocVersion.objects.get(enable=True, url=version)
if vers_obj:
art = vers_obj.get_article()
if art:
url = reverse(
'docs_art_page',
kwargs={'version': version, 'art_url': art.url}
)
return HttpResponseRedirect(url)
except DocVersion.DoesNotExist:
raise Http404
art = DocArt.objects.exclude(
versions=None
).filter(
enable=True, parent=None
).order_by('-versions__order', '-versions__name', 'order').first()
if art:
url = reverse(
'docs_art_page',
kwargs={'version': art.versions.order_by('-order').first().url, 'art_url': art.url}
)
return HttpResponseRedirect(url)
if not art:
raise Http404

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,44 @@
# Generated by Django 4.2.7 on 2024-07-10 16:02
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('GeneralApp', '0024_block_bg_video_url_en_block_bg_video_url_ru_and_more'),
]
operations = [
migrations.AlterField(
model_name='office',
name='work_time_from',
field=models.TimeField(default=datetime.datetime(2024, 7, 10, 9, 0), verbose_name='Время работы с'),
),
migrations.AlterField(
model_name='office',
name='work_time_from_en',
field=models.TimeField(default=datetime.datetime(2024, 7, 10, 9, 0), null=True, verbose_name='Время работы с'),
),
migrations.AlterField(
model_name='office',
name='work_time_from_ru',
field=models.TimeField(default=datetime.datetime(2024, 7, 10, 9, 0), null=True, verbose_name='Время работы с'),
),
migrations.AlterField(
model_name='office',
name='work_time_to',
field=models.TimeField(default=datetime.datetime(2024, 7, 10, 18, 0), verbose_name='Время работы до'),
),
migrations.AlterField(
model_name='office',
name='work_time_to_en',
field=models.TimeField(default=datetime.datetime(2024, 7, 10, 18, 0), null=True, verbose_name='Время работы до'),
),
migrations.AlterField(
model_name='office',
name='work_time_to_ru',
field=models.TimeField(default=datetime.datetime(2024, 7, 10, 18, 0), null=True, verbose_name='Время работы до'),
),
]

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

@@ -25,20 +25,28 @@ SECRET_KEY = 'django-insecure-0lk552&eia*_v5q$c8((o4=0d6x_t4%y-*x9p=n05nydiu)s9-
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
# ALLOWED_HOSTS = []
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'] 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',
@@ -56,6 +64,7 @@ INSTALLED_APPS = [
'ServicesApp', 'ServicesApp',
'SlidesApp', 'SlidesApp',
'PortfolioApp', 'PortfolioApp',
'DocsApp',
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@@ -70,6 +79,8 @@ MIDDLEWARE = [
# 'AuthApp.middleware.ResponseInterceptionMiddleware', # 'AuthApp.middleware.ResponseInterceptionMiddleware',
] ]
ROOT_URLCONF = 'pAerBim.urls' ROOT_URLCONF = 'pAerBim.urls'
TEMPLATES = [ TEMPLATES = [
@@ -153,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 = '/'
@@ -187,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
@@ -197,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"
@@ -208,6 +225,7 @@ CKEDITOR_JQUERY_URL = 'https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery
CKEDITOR_CONFIGS = { CKEDITOR_CONFIGS = {
'default': { 'default': {
'versionCheck': False,
'height': 291, 'height': 291,
'width': '70vw', 'width': '70vw',
'filebrowserWindowHeight': 600, 'filebrowserWindowHeight': 600,
@@ -215,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,
@@ -245,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', '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

@@ -1,8 +1,10 @@
Django==4.2.7 Django==4.2.7
django-admin-interface==0.26.1 django-admin-interface==0.26.1
django-ckeditor==6.7.0 django-ckeditor==6.7.1
django-colorfield==0.10.1 django-colorfield==0.10.1
django-modeltranslation==0.18.11 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

@@ -1624,4 +1624,425 @@ body.n_scroll{
width: 47.5%; width: 47.5%;
margin-left: 2.5%; margin-left: 2.5%;
margin-top: 0; margin-top: 0;
}
.breadcrumbs_documentation_block{
width: 100%;
margin: 30px 0 50px 0;
}
.breadcrumbs_documentation{
display: flex;
width: 100%;
align-items: center;
flex-wrap: wrap;
}
.breadcrumb_arrow_picture{
margin: 0 8px;
height: 16px;
width: 16px;
display: block;
}
.breadcrumb_arrow_img{
width: 6px;
height: 10px;
padding: 2px 5px;
display: block;
}
.way_bread_crumb{
font-size: 14px;
color: #7A8185FF;
cursor: pointer;
display: block;
text-decoration: unset;
}
.way_bread_crumb.last{
color: #000000;
}
.documentation_switcher_arrow_picture{
width: 12px;
height: 7px;
display: block;
}
.documentation_switcher_arrow_img{
width: 12px;
height: 7px;
display: block;
}
.cur_documentation_version{
font-size: 16px;
font-weight: 500;
color: #0C54A0FF;
}
.documentation_version_txt{
font-size: 20px;
font-weight: 700;
color: #10212BFF;
}
.documentation_version{
display: flex;
align-items: center;
margin-bottom: 30px;
}
.documentation_version_switcher{
width: 70px;
border: 1px solid #CCCED1FF;
border-radius: 2px;
margin-left: 16px;
position: relative;
}
.first_line_documentation_version_switcher{
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px 10px 6px 17px;
}
.documentation_switcher_content_part{
width: 100%;
position: absolute;
bottom: -31px;
border: 1px solid #CCCED1FF;
border-top: 0;
left: -1px;
background: #FFFFFF;
}
.documentation_switcher_content_part.hidden{
display: none;
}
.one_item_documentation_switcher_content_part{
background: none;
font-size: 16px;
font-weight: 400;
color: #0C54A0FF;
transition: 200ms;
padding: 6px 10px 6px 10px;
display: flex;
align-items: center;
justify-content: center;
text-decoration: unset;
}
.one_item_documentation_switcher_content_part:hover{
background: #0C54A0FF;
color: #FFFFFF;
}
.left_curtain_documentation{
width: 373px;
height: fit-content;
}
.tree_documentation_container{
width: 100%;
height: calc(100vh - 300px);
overflow-y: auto;
}
.tree_documentation_container.hide_scroll::-webkit-scrollbar{
display: none;
}
.tree_documentation_container.hide_scroll{
overflow-y: hidden;
}
.tree_documentation_container.hidden_scrollbar::-webkit-scrollbar {
opacity: 0;
display: none;
}
.tree_documentation_container::-webkit-scrollbar-thumb {
background-color: #CCCED1FF;
border-radius: 5px;
width: 6px;
display: block;
border: 1px solid #EDEDEDFF;
transition: 200ms all;
}
.tree_documentation_container::-webkit-scrollbar {
background-color: #EDEDEDFF;
width: 8px;
display: block;
padding-left: 15px;
transition: 500ms all;
opacity: 100%;
border-radius: 5px;
}
/*.tree_documentation_container::-webkit-scrollbar:hover .tree_documentation_container::-webkit-scrollbar-thumb {*/
/* background-color: #0C54A0FF;*/
/*}*/
.tree_documentation_container:hover::-webkit-scrollbar-thumb:hover {
background-color: #0C54A0FF;
}
.tree_documentation_container_first_level{
width: 100%;
margin: 10px 0;
}
.tree_documentation_container_first_line{
display: flex;
width: 100%;
cursor: pointer;
align-items: flex-start;
}
.tree_documentation_arrow_picture{
width: 24px;
height: 24px;
display: block;
background: none;
transition: 200ms all;
border-radius: 2px;
}
.tree_documentation_arrow_picture:hover{
background: #E0E8EFFF;
}
.tree_documentation_arrow_img{
width: 7px;
height: 12px;
padding: 6px 9px;
}
.tree_documentation_container_first_level_txt{
font-size: 16px;
font-weight: 700;
color: #000000;
margin-left: 3px;
display: block;
text-decoration: unset;
line-height: 25px;
}
.tree_documentation_container_second_level_txt{
font-size: 16px;
font-weight: 400;
color: #000000;
margin-left: 3px;
display: block;
text-decoration: unset;
line-height: 24px;
}
.tree_documentation_container_first_level_txt.chose{
color: #0C54A0FF;
}
.tree_documentation_container_second_level_txt.chose{
color: #0C54A0FF;
}
.tree_documentation_container_first_level_txt.margin{
margin-left: 24px;
}
.tree_documentation_container_second_level_txt.margin{
margin-left: 24px;
}
.content_part_tree_documentation_container{
width: 100%;
margin-top: 10px;
margin-bottom: 10px;
}
.content_part_tree_documentation_container.hidden{
display: none;
}
.tree_documentation_container_second_level{
margin: 10px 0 10px 20px;
}
.elements_third_level_content_part_tree{
margin-left: 40px;
}
.element_third_level_content_part_tree{
width: 100%;
color: #7A8185FF;
font-size: 14px;
font-weight: 400;
margin: 5px 0;
cursor: pointer;
display: block;
text-decoration: unset;
}
.element_third_level_content_part_tree.chose{
color: #0C54A0FF;
}
.content_part_tree_documentation_container.min_padding{
margin-top: 5px;
}
.flex_container_tree_and_content{
display: flex;
width: 100%;
position: relative;
}
.content_part_tree_els{
width: calc(100% - 453px);
margin-left: 80px;
font-size: 16px;
}
.content_part_tree_els img{
max-width: 100%;
object-fit: contain;
}
.content_part_tree_els h1{
font-size: 40px;
margin-top: 0!important;
}
.name_article_tree{
font-size: 40px;
font-weight: 700;
margin-bottom: 30px;
}
.description_article_tree{
font-size: 16px;
font-weight: 400;
margin-bottom: 40px;
}
.controls_content_part_tree_els{
display: flex;
justify-content: space-between;
margin-top: 40px;
}
.control_content_part_tree_el{
display: flex;
align-items: center;
width: fit-content;
cursor: pointer;
}
.arrow_control_content_part_tree_el_img{
width: 11px;
height: 9px;
display: block;
}
.arrow_control_content_part_tree_el_picture{
width: 11px;
height: 9px;
display: block;
}
.control_content_part_tree_el.right .arrow_control_content_part_tree_el_img{
rotate: 180deg;
}
.control_content_part_tree_el.left .arrow_control_content_part_tree_el_img{
rotate: 0;
}
.txt_control_content_part_tree_el{
font-size: 14px;
font-weight: 400;
color: #7A8185FF;
border-bottom: 1px solid #7A8185FF;
display: block;
text-decoration: unset;
}
.control_content_part_tree_el.right .txt_control_content_part_tree_el{
margin-right: 7px;
}
.control_content_part_tree_el.left .txt_control_content_part_tree_el{
margin-left: 7px;
}
.documentation_block{
margin-bottom: 100px;
}
.container_top_txt_curtain_documentation{
display: flex;
height: 55px;
align-items: center;
justify-content: space-between;
padding: 0 15px;
border-bottom: 1px solid #CCCED1FF;
}
.top_txt_curtain_documentation{
font-size: 16px;
font-weight: 600;
color: #7A8185FF;
}
.top_picture_curtain_documentation{
width: 24px;
height: 24px;
display: block;
}
.top_img_curtain_documentation{
width: 24px;
height: 24px;
display: block;
}
.container_open_doc_curtain{
display: flex;
align-items: center;
justify-content: right;
width: 100%;
float: right;
position: sticky;
top: 61px;
background: #FFFFFF;
padding: 22px 22px;
z-index: 1000;
}
.container_open_doc_curtain_txt{
font-size: 14px;
font-weight: 400;
color: #0C54A0FF;
margin-right: 4px;
border-bottom: 1px solid #0C54A0FF;
}
.container_open_doc_curtain_picture{
width: 10px;
height: 10px;
display: block;
}
.container_open_doc_curtain_img{
width: 10px;
height: 10px;
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,81 @@
} }
@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{
font-size: 12px;
}
.left_curtain_documentation{
width: 320px;
height: 100vh;
}
.tree_documentation_container_first_level_txt{
margin-bottom: 0;
font-size: 14px;
}
.tree_documentation_container_second_level_txt{
margin-left: 0;
font-size: 14px;
}
.tree_documentation_container_first_level_txt.margin{
margin-left: 24px;
}
.tree_documentation_container_second_level_txt.margin{
margin-left: 24px;
}
.left_curtain_documentation{
position: fixed;
left: -320px;
/* opacity: 0; */
height: 100vh;
top: 0;
background: #fff;
z-index: 10000;
padding: 0 0 27px 0;
}
.documentation_version{
padding: 0 15px;
margin-top: 20px;
}
.block_overlay{
top: 0;
}
.flex_container_tree_and_content{
display: block;
}
.tree_documentation_container {
width: unset;
height: calc(100vh - 172px);
overflow-y: auto;
padding: 0 15px;
}
.content_part_tree_els{
width: 100%;
margin-left: 0;
}
.breadcrumbs_documentation_block{
margin-top: 90px;
margin-bottom: 2px;
}
.container_img_card_contacts{ .container_img_card_contacts{
height: 250px; height: 250px;
} }
@@ -297,6 +371,12 @@
} }
@media (max-width: 800px) { @media (max-width: 800px) {
.content_part_tree_els h1{
font-size: 36px;
}
.name_article_tree{
font-size: 36px;
}
.how_dev_container_widgets { .how_dev_container_widgets {
width: 100%; width: 100%;
display: flex; display: flex;
@@ -488,7 +568,7 @@
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.footer_els_container{ .footer_els_container{
width: 100%; width: 100%;
} }
@@ -586,8 +666,17 @@
} }
@media (max-width: 380px) { @media (max-width: 380px) {
.content_part_tree_els h1{
font-size: 26px;
}
.descript_process_container{ .descript_process_container{
margin-bottom: 15px; margin-bottom: 15px;
} }
.breadcrumbs_documentation_block{
display: none;
}
.name_article_tree{
font-size: 26px;
}
} }

View File

@@ -12,7 +12,111 @@ $(document).ready(function (){
resize_iframe() resize_iframe()
} }
} }
if (getInfoAboutUser()[0] === 'laptop' || getInfoAboutUser()[0] === 'mobile'){
setInfInCurtainDocumentationMobile()
setButtonOpenMobileDocCurtain()
}
windowScrollDocPage()
}) })
function setButtonOpenMobileDocCurtain () {
let $content = $('.content_part_tree_els')
let $cont = document.createElement("div")
let $txt = document.createElement("div")
let $picture = document.createElement("picture")
let $source = document.createElement("source")
let $img = document.createElement("img")
$cont.classList.add("container_open_doc_curtain")
$txt.innerHTML = context_txt_translated
$txt.setAttribute("onclick",'openDocCurtainMobile()')
$txt.classList.add("container_open_doc_curtain_txt")
$picture.classList.add("container_open_doc_curtain_picture")
$source.srcset = '/static/images/arrow_open_documentation_curtain.svg'
$img.classList.add("container_open_doc_curtain_img")
$img.src = '/static/images/arrow_open_documentation_curtain.svg'
$cont.appendChild($txt)
$cont.appendChild($picture)
$picture.appendChild($source)
$picture.appendChild($img)
$($cont).insertAfter($(".breadcrumbs_documentation_block"))
}
function setInfInCurtainDocumentationMobile () {
let $doc_vers = $(".documentation_version")
let $container = document.createElement("div")
let $txt = document.createElement("div")
let $picture = document.createElement("picture")
let $source = document.createElement("source")
let $img = document.createElement("img")
$container.classList.add("container_top_txt_curtain_documentation")
$picture.classList.add("top_picture_curtain_documentation")
$txt.innerHTML = context_txt_translated
$txt.classList.add("top_txt_curtain_documentation")
$source.srcset = '/static/images/cross.svg'
$img.src = '/static/images/cross.svg'
$container.appendChild($txt)
$container.appendChild($picture)
$picture.appendChild($source)
$picture.setAttribute("onclick","closeDocCurtainMobile()")
$picture.appendChild($img)
$($container).insertBefore($doc_vers)
}
function openDocCurtainMobile () {
$("body").css({'overflow':'hidden'})
let $curtain = $(".left_curtain_documentation")
let $block_overlay = $(".block_overlay")
$curtain.css({left:0})
$block_overlay.removeClass("hide")
$block_overlay.addClass("show")
$block_overlay.css({zIndex:10000})
}
function closeDocCurtainMobile () {
$("body").css({'overflow':'unset'})
let $curtain = $(".left_curtain_documentation")
let $block_overlay = $(".block_overlay")
$curtain.css({left:'-320px'})
$block_overlay.addClass("hide")
$block_overlay.removeClass("show")
$block_overlay.css({zIndex:101})
}
autoplayInterval = null autoplayInterval = null
function resize_iframe () { function resize_iframe () {
@@ -30,7 +134,7 @@ function getInfoAboutUser (){
if (screen.width <= 800){ if (screen.width <= 800){
user_type = 'mobile' user_type = 'mobile'
} else if (screen.width > 1024) { } else if (screen.width > 1024) {
user_type = 'desktop' user_type = 'desktop'
} else if (screen.width >= 800 && screen.width <= 1024) { } else if (screen.width >= 800 && screen.width <= 1024) {
user_type = 'laptop' user_type = 'laptop'
} }
@@ -400,4 +504,246 @@ function redirectToDownloadPlugin () {
// } else { // } else {
window.location.href = `${window.location.origin}/${lang}/section/3d-security-designer/#feedback_form` window.location.href = `${window.location.origin}/${lang}/section/3d-security-designer/#feedback_form`
// } // }
}
function transitToDocumentation() {
window.location.href = window.location.origin + '/' + getLang() + '/docs/3dsd/'
}
let switcherWorking = false
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 () {
if (!event.srcElement.closest(".documentation_version_switcher")){
let $version_switcher_container_content = $(".documentation_switcher_content_part")
let $arrow = document.querySelector(".documentation_switcher_arrow_picture")
$version_switcher_container_content.addClass("hidden")
$(".documentation_version_switcher").css({borderBottom: '1px solid #CCCED1FF'})
if ($arrow.style.rotate !== '180deg'){
$($arrow).css({rotate: '180deg'})
} else {
$($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",'')
}
}
function choseItemTreeDocumentation (el){
let $tree = el.closest(".tree_documentation_container")
let $allChosingElementsTreeThirdLevel = $($tree).find(".element_third_level_content_part_tree")
let $allChosingElementsTreeSecondLevel = $($tree).find(".tree_documentation_container_second_level_txt")
let $allChosingElementsTreeFirstLevel = $($tree).find(".tree_documentation_container_first_level_txt")
$allChosingElementsTreeThirdLevel.each(function (){
if (el !== this){
this.classList.remove("chose")
}
})
$allChosingElementsTreeSecondLevel.each(function (){
if (el !== this){
this.classList.remove("chose")
}
})
$allChosingElementsTreeFirstLevel.each(function (){
if (el !== this){
this.classList.remove("chose")
}
})
el.classList.add("chose")
let url = window.location.origin + el.dataset['url']
window.location.href = url
}
function showContentPartTree (el) {
let $parent = el.parentNode
let $content_part = $parent.querySelector(".content_part_tree_documentation_container")
if (!$content_part){
$parent = $parent.parentNode
$content_part = $parent.querySelector(".content_part_tree_documentation_container")
}
let $arrow = $parent.querySelector(".tree_documentation_arrow_img")
$content_part.classList.toggle("hidden")
if ($arrow.style.rotate === '0deg' || $arrow.style.rotate === ''){
$($arrow).css({rotate: '90deg'})
} else {
$($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 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 (){
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})
}
}
}
})
function chooseVersionComplete (el) {
let url = el.dataset['url']
let title = el.dataset['title']
let $parent = el.closest(".documentation_version")
let $cur_selected = $parent.querySelector(".cur_documentation_version")
let $cont = el.closest(".documentation_switcher_content_part")
let $cont_parent = $cont.closest(".documentation_version_switcher")
$cont_parent.style.borderBottom = '1px solid #CCCED1FF'
$cont.classList.add("hidden")
$cur_selected.innerHTML = title
window.location.href = window.location.origin + url
}
function breadCrumbGo (el){
if (el.dataset){
let url = el.dataset['url']
window.location.href = window.location.origin + url
}
}
function changeCurArticle (el){
let url = el.dataset['url']
window.location.href = window.location.origin + url
} }

View File

@@ -0,0 +1,3 @@
<svg width="13" height="11" viewBox="0 0 13 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.27778 10L1 5.5M1 5.5L5.27778 1M1 5.5L12 5.5" stroke="#7A8185" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 226 B

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

@@ -0,0 +1,3 @@
<svg width="12" height="7" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.46906 6.53399L-0.00292987 1.06092L1.05783 0.000366396L5.99944 4.94295L10.9411 0.000368242L12.0018 1.06092L6.52983 6.53399C6.38917 6.67468 6.19838 6.75371 5.99944 6.75371C5.8005 6.75371 5.60972 6.67468 5.46906 6.53399Z" fill="#0C54A0"/>
</svg>

After

Width:  |  Height:  |  Size: 389 B

View File

@@ -0,0 +1,3 @@
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.0036 6.98053L10.0036 1C10.0036 0.447716 9.55591 0 9.00363 0H3.02253L3.02253 1.5L7.44305 1.5L0 8.94236L1.06061 10.0031L8.50363 2.56074L8.50363 6.98053H10.0036Z" fill="#0C54A0"/>
</svg>

After

Width:  |  Height:  |  Size: 333 B

View File

@@ -0,0 +1,3 @@
<svg width="6" height="10" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.93627 5.00041L0.469727 1.53048L1.53091 0.470337L5.527 4.47034C5.81955 4.76317 5.81955 5.23765 5.527 5.53048L1.5309 9.53048L0.469727 8.47034L3.93627 5.00041Z" fill="#7A8185"/>
</svg>

After

Width:  |  Height:  |  Size: 288 B

4
static/images/cross.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 6L6 18" stroke="#10212B" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 6L18 18" stroke="#10212B" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 277 B

View File

@@ -40,7 +40,7 @@
</button> </button>
{% endif %} {% endif %}
{% if block.but2_title or block.but2_icon %} {% if block.but2_title or block.but2_icon %}
<button class="btn_inf_about_plugin pointer"> <button class="btn_inf_about_plugin pointer" onclick="transitToDocumentation()">
<div class="container_content_btn_download"> <div class="container_content_btn_download">
{% if block.but2_icon %} {% if block.but2_icon %}
<div class="left_part_btn"> <div class="left_part_btn">

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

@@ -1,2 +1,123 @@
{% extends 'tb_base.html' %}
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}
{% block CONTENT %}
{% include "blocks/b_sections_buttons.html" %}
<div class="breadcrumbs_documentation_block">
<div class="cut-width">
<div class="breadcrumbs_documentation">
{# <div class="way_bread_crumb">#}
{# Документация и техническая поддержка#}
{# </div>#}
{# <picture class="breadcrumb_arrow_picture">#}
{# <source srcset="{% static "images/breadcrumb_arrow.svg" %}">#}
{# <img class="breadcrumb_arrow_img" src="{% static "images/breadcrumb_arrow.svg" %}" alt="">#}
{# </picture>#}
{# <div class="way_bread_crumb">#}
{# Документация для версии 1#}
{# </div>#}
{# <picture class="breadcrumb_arrow_picture">#}
{# <source srcset="{% static "images/breadcrumb_arrow.svg" %}">#}
{# <img class="breadcrumb_arrow_img" src="{% static "images/breadcrumb_arrow.svg" %}" alt="">#}
{# </picture>#}
{# <div class="way_bread_crumb last">#}
{# Документация для версии 1#}
{# </div>#}
{% for name,url in breadcrumbs.items %}
<a class="way_bread_crumb{% if forloop.last %} last{% endif %}" {% if not forloop.last %}href="{{ url }}"{% endif %}>
{{ name }}
</a>
{% if not forloop.last %}
<picture class="breadcrumb_arrow_picture">
<source srcset="{% static "images/breadcrumb_arrow.svg" %}">
<img class="breadcrumb_arrow_img" src="{% static "images/breadcrumb_arrow.svg" %}" alt="">
</picture>
{% endif %}
{% endfor %}
</div>
</div>
</div>
<div class="documentation_block">
<div class="cut-width flex_container_tree_and_content">
<div class="left_curtain_documentation">
<div class="documentation_version">
<div class="documentation_version_txt">
{% trans "Документация для версии" %}
</div>
<div class="documentation_version_switcher">
<div class="first_line_documentation_version_switcher" onclick="openVersionSwitcher(this)">
<div class="cur_documentation_version">
{{ cur_version.name }}
</div>
<picture class="documentation_switcher_arrow_picture">
<source srcset="{% static "images/arrow_for_documentation_switcher.svg" %}">
<img class="documentation_switcher_arrow_img" src="{% static "images/arrow_for_documentation_switcher.svg" %}" alt="">
</picture>
</div>
<div class="documentation_switcher_content_part hidden">
{% for item in allow_versions %}
<a class="one_item_documentation_switcher_content_part" href="{% url 'docs_version_page' item.url %}" data-title="{{ item.name }}">
{{ item.name }}
</a>
{% endfor %}
</div>
</div>
</div>
<div class="tree_documentation_container">
{% for id, obj in doc_tree.items %}
<div class="tree_documentation_container_first_level">
<div class="tree_documentation_container_first_line">
{% if obj.children %}
<picture class="tree_documentation_arrow_picture" onclick="showContentPartTree(this)" {% if obj.active %}style="rotate: 90deg;"{% endif %}>
<source srcset="{% static "images/arrow_for_doc_tree.svg" %}">
<img class="tree_documentation_arrow_img" src="{% static "images/arrow_for_doc_tree.svg" %}" alt="">
</picture>
{% endif %}
<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 %}">
{{ obj.name }}
</a>
</div>
{% if obj.children %}
<div class="content_part_tree_documentation_container {% if not obj.active %}hidden{% endif %}">
{% for id, obj in obj.children.items %}
<div class="tree_documentation_container_second_level">
<div class="tree_documentation_container_first_line">
{% if obj.children %}
<picture class="tree_documentation_arrow_picture" onclick="showContentPartTree(this)" {% if obj.active %}style="rotate: 90deg;"{% endif %}>
<source srcset="{% static "images/arrow_for_doc_tree.svg" %}">
<img class="tree_documentation_arrow_img" src="{% static "images/arrow_for_doc_tree.svg" %}" alt="">
</picture>
{% endif %}
<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 %}">
{{ obj.name }}
</a>
</div>
{% if obj.children %}
<div class="content_part_tree_documentation_container min_padding {% if not obj.active %}hidden{% endif %}">
<div class="elements_third_level_content_part_tree">
{% for id,obj in obj.children.items %}
<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 %}">
{{ obj.name }}
</a>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% include "blocks/b_documentation_article.html" %}
</div>
</div>
{% endblock %}

View File

@@ -1,5 +1,5 @@
{% load static %} {% load static %}
{% load i18n %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{ request.LANGUAGE_CODE }}"> <html lang="{{ request.LANGUAGE_CODE }}">
<head> <head>
@@ -12,6 +12,7 @@
<script src="{% static "jquery_v3_6_4.js" %}"></script> <script src="{% static "jquery_v3_6_4.js" %}"></script>
<script src="{% static "aerbimJS.js" %}"></script> <script src="{% static "aerbimJS.js" %}"></script>
<script> <script>
context_txt_translated = '{% trans "Содержание" %}'
lang_f_check = '' lang_f_check = ''
</script> </script>
<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">