educommon 3.5.5__py3-none-any.whl → 3.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,9 +3,9 @@ from collections.abc import (
3
3
  )
4
4
  from typing import (
5
5
  TYPE_CHECKING,
6
+ Iterable as IterableType,
6
7
  List,
7
8
  Union,
8
- Iterable as IterableType,
9
9
  )
10
10
 
11
11
  from educommon.audit_log.models import (
@@ -1,2 +1,4 @@
1
1
  """Средства аутентификации и авторизации."""
2
- from __future__ import absolute_import
2
+ from __future__ import (
3
+ absolute_import,
4
+ )
@@ -19,6 +19,10 @@ from django.utils import (
19
19
  timezone,
20
20
  )
21
21
 
22
+ from m3_db_utils.models import (
23
+ FictiveForeignKeyMixin,
24
+ )
25
+
22
26
  from educommon.integration_entities.enums import (
23
27
  EntityLogOperation,
24
28
  )
@@ -75,8 +79,24 @@ class AbstractEntitySaver(ABC):
75
79
  """
76
80
  return []
77
81
 
82
+ def _convert_fictive_foreign_keys(self, entities: Iterable[Model]):
83
+ """Преобразование значений полей фиктивных внешних ключей.
84
+
85
+ В рамках метода производится проверка наличия фиктивного внешнего ключа у модели. Если они есть и заполнены
86
+ объектами модели, то производится получения идентификатора объекта модели и замена им самого объекта.
87
+ """
88
+ for entity in entities:
89
+ if isinstance(entity, FictiveForeignKeyMixin):
90
+ for field_name in entity.fictive_foreign_key_field_names:
91
+ field_value = getattr(entity, field_name, None)
92
+
93
+ if field_value and isinstance(field_value, Model):
94
+ setattr(entity, field_name, getattr(field_value, 'pk'))
95
+
78
96
  def _create_entities(self) -> None:
79
97
  """Создает новые записи."""
98
+ self._convert_fictive_foreign_keys(entities=self._to_create_entities)
99
+
80
100
  self.model.objects.bulk_create(
81
101
  self._to_create_entities,
82
102
  batch_size=self.create_batch_size,
@@ -85,6 +105,8 @@ class AbstractEntitySaver(ABC):
85
105
 
86
106
  def _update_entities(self) -> None:
87
107
  """Обновляет записи."""
108
+ self._convert_fictive_foreign_keys(entities=self._to_create_entities)
109
+
88
110
  for entity in self._to_update_entities:
89
111
  # Поле modified имеет свойство auto_now=True и оно не обновляется при update и bulk_update.
90
112
  # Поэтому, его нужно обновить вручную:
@@ -19,6 +19,7 @@ from objectpack.actions import (
19
19
  BaseAction,
20
20
  BasePack,
21
21
  BaseWindowAction,
22
+ ObjectRowsAction,
22
23
  )
23
24
  from objectpack.models import (
24
25
  ModelProxy,
@@ -201,6 +202,17 @@ class BaseGridWinAction(BaseWindowAction):
201
202
  self.request, self.context)
202
203
 
203
204
 
205
+ class ExtObjectRowsAction(ObjectRowsAction):
206
+ def get_total_count(self):
207
+ """
208
+ В отличие от оригинала убирает из запроса лишнюю обработку даных.
209
+
210
+ :return: Количество объектов в выборке
211
+ :rtype: int
212
+ """
213
+ return self.query.select_related(None).values('id').count()
214
+
215
+
204
216
  class RelationsCheckMixin:
205
217
  """
206
218
  Миксин для экшенов удаления и редактирования, проверяющий наличие
@@ -0,0 +1,155 @@
1
+ """Дополнение колоночных фильтров."""
2
+
3
+ from django.db.models.expressions import (
4
+ Q,
5
+ )
6
+ from m3.actions import (
7
+ DeclarativeActionContext,
8
+ )
9
+ from m3.plugins import (
10
+ ExtensionManager,
11
+ )
12
+ from m3_ext.ui import (
13
+ all_components as ext,
14
+ )
15
+
16
+ from objectpack.filters import (
17
+ ColumnFilterEngine as BaseFilterEngine,
18
+ CustomFilter,
19
+ )
20
+ from objectpack.ui import (
21
+ _create_control_for_field,
22
+ make_combo_box,
23
+ )
24
+
25
+ from educommon.utils.ui import (
26
+ ColumnFilterWithDefaultValue,
27
+ )
28
+
29
+
30
+ class ColumnFilterEngine(BaseFilterEngine):
31
+ """Колоночные фильтры с возможностью расширения плагином."""
32
+
33
+ def configure_grid(self, grid):
34
+ """Метод конфигурации грида."""
35
+ # расширение плагином
36
+ if not ExtensionManager().execute(
37
+ 'column_filter_engine.configure_grid', self, grid
38
+ ):
39
+ super().configure_grid(grid)
40
+
41
+
42
+ class ModifiedChoicesFilter(CustomFilter):
43
+ """Колоночный фильтр с выпадающим списком."""
44
+
45
+ def __init__(self, choices, *args, **kwargs):
46
+ """Метод инициализации.
47
+
48
+ Добавляем значения для выбора и тип компонента.
49
+ """
50
+ self._choices = choices
51
+ kwargs['xtype'] = 'combo'
52
+
53
+ super(ModifiedChoicesFilter, self).__init__(*args, **kwargs)
54
+
55
+ def create_control(self):
56
+ """Контрол."""
57
+ if callable(self._choices):
58
+ choices = self._choices()
59
+ else:
60
+ choices = self._choices
61
+ return make_combo_box(data=list(choices))
62
+
63
+ def get_control(self):
64
+ """Настройка контрола."""
65
+ control = self.create_control()
66
+ control._put_config_value('filterName', self._uid)
67
+ control._put_config_value('tooltip', self._tooltip or control.label)
68
+ control.name = self._uid
69
+ control.allow_blank = True
70
+ control.hide_clear_trigger = False
71
+ control.value = None
72
+ return control
73
+
74
+ def get_script(self):
75
+ """Генерация кода компонента."""
76
+ return [self.get_control().render()]
77
+
78
+
79
+ class BoolChoicesFilter(ModifiedChoicesFilter):
80
+ """Колоночный фильтр с выпадающим списком значений булевого поля."""
81
+
82
+ def __init__(self, field_name, *args, **kwargs):
83
+ """Инициализация параметров."""
84
+ choices = ((None, ''), (True, 'Да'), (False, 'Нет'))
85
+
86
+ def lookup(v):
87
+ """Формирование lookup для фильтра."""
88
+ return Q(**{field_name: v}) if v is not None else Q()
89
+
90
+ super(BoolChoicesFilter, self).__init__(
91
+ *args, choices=choices, parser='boolean', lookup=lookup, **kwargs
92
+ )
93
+
94
+
95
+ class DateFilter(ColumnFilterWithDefaultValue):
96
+ """Колоночный фильтр по датам."""
97
+
98
+ def create_control(self):
99
+ """Создание контрола."""
100
+ return _create_control_for_field(
101
+ self.field,
102
+ **self._field_fabric_params
103
+ )
104
+
105
+ def get_control(self):
106
+ """Настройка контрола."""
107
+ control = self.create_control()
108
+ control.value = self.default_value
109
+ control._put_config_value('filterName', self._uid)
110
+ control._put_config_value('tooltip', self._tooltip or control.label)
111
+ control.name = self._uid
112
+ control.allow_blank = True
113
+ control.hide_clear_trigger = False
114
+ return control
115
+
116
+ def get_script(self):
117
+ """Рендер контрола."""
118
+ return [self.get_control().render()]
119
+
120
+
121
+ class DateFilterByAnnotatedField(DateFilter):
122
+ """
123
+ Колоночный фильтр по аннотируему полю даты.
124
+
125
+ Фильтр по полю, которое отсутствует у модели и данные по которому
126
+ собираются в кварисете через annotate.
127
+ """
128
+
129
+ def __init__(
130
+ self, model, field_name, lookup=None, tooltip=None, default_value=None,
131
+ **field_fabric_params
132
+ ):
133
+ """Инициализация параметров."""
134
+ field_name = field_name.replace('.', '__')
135
+ self._model = model
136
+ self._field_name = field_name
137
+ self._tooltip = tooltip
138
+ self._field_fabric_params = field_fabric_params
139
+ self._default_value = default_value
140
+ self._parser = DeclarativeActionContext._parsers['datetime']
141
+ if lookup:
142
+ # шаблонизация лукапа, если петтерн указан
143
+ if not callable(lookup) and '%s' in lookup:
144
+ lookup = lookup % field_name
145
+ else:
146
+ def lookup(x):
147
+ return Q(**{field_name: x})
148
+ self._lookup = lookup
149
+
150
+ def create_control(self):
151
+ """Создание контрола."""
152
+ params = {'format': 'd.m.Y'}
153
+ params.update(**self._field_fabric_params)
154
+
155
+ return ext.ExtDateField(**params)
@@ -0,0 +1,258 @@
1
+ """Утилиты для ObjectGrid."""
2
+ import json
3
+
4
+ from m3.actions.urls import (
5
+ get_url,
6
+ )
7
+ from m3_ext.ui import (
8
+ all_components as ext,
9
+ )
10
+
11
+
12
+ def add_action_button(label, grid, action, icon_cls, index=None):
13
+ """
14
+ Добавление кнопки в тулбар ObjectGrid'а.
15
+
16
+ label - Имя кнопки
17
+ grid - ObjectGrid
18
+ action - Action для кнопки
19
+ icon_cls - Значек кнопки
20
+ index - Позиция добавления кнопки. По-умолчанию справа.
21
+
22
+ Примеры подключения и использования для ObjectPack'а:
23
+
24
+ def create_list_window(self, *args, **kwargs):
25
+ win = super(ObjectPack, self).create_list_window(*args, **kwargs)
26
+ append_template_globals(win, 'ui-js/object-grid-buttons.js')
27
+ return win
28
+
29
+ def configure_grid(self, grid, *args, **kwargs):
30
+ super(ObjectPack, self).configure_grid(grid, *args, **kwargs)
31
+ add_action_button('Печать', grid, self.print_action, Icons.PRINTER)
32
+ """
33
+ action_url = get_url(action)
34
+ button = ext.ExtButton(
35
+ text=label,
36
+ handler=_get_action_handler(action_url),
37
+ icon_cls=icon_cls)
38
+ if index is not None:
39
+ grid.top_bar.items.insert(index, button)
40
+ else:
41
+ grid.top_bar.items.append(button)
42
+
43
+
44
+ def add_one_row_button(label, grid, action, icon_cls,
45
+ dbl_clicked=False, index=None):
46
+ """
47
+ Добавление кнопки в тулбар и popup меню ObjectGrid'а.
48
+
49
+ label - Имя кнопки
50
+ grid - ObjectGrid
51
+ action - Action для кнопки
52
+ icon_cls - Значек кнопки
53
+ dbl_clicked - Вызов действия по даблклику строк
54
+ index - Позиция добавления кнопки. По-умолчанию справа.
55
+
56
+ Примеры подключения и использования для ObjectPack'а:
57
+
58
+ def create_list_window(self, *args, **kwargs):
59
+ win = super(ObjectPack, self).create_list_window(*args, **kwargs)
60
+ append_template_globals(win, 'ui-js/object-grid-buttons.js')
61
+ return win
62
+
63
+ def configure_grid(self, grid, *args, **kwargs):
64
+ super(ObjectPack, self).configure_grid(grid, *args, **kwargs)
65
+ grid.url_edit = None
66
+ add_one_row_button('Просмотр', grid, self.edit_window_action,
67
+ Icons.APPLICATION_VIEW_DETAIL, dbl_clicked=True)
68
+ """
69
+ params = _get_one_row_params(label, action, icon_cls)
70
+ button = ext.ExtButton(**params)
71
+ if index is not None:
72
+ grid.top_bar.items.insert(index, button)
73
+ else:
74
+ grid.top_bar.items.append(button)
75
+
76
+ menuitem = ext.ExtContextMenuItem(**params)
77
+ grid.context_menu_row.items.append(menuitem)
78
+
79
+ if dbl_clicked:
80
+ grid.dblclick_handler = button.handler
81
+ grid.handler_dblclick = grid.dblclick_handler
82
+
83
+
84
+ def add_multi_row_button(label, grid, action, icon_cls,
85
+ confirm_required=False, index=None):
86
+ """
87
+ Добавление кнопки в тулбар и popup меню ObjectGrid'а.
88
+
89
+ label - Имя кнопки
90
+ grid - ObjectGrid
91
+ action - Action для кнопки
92
+ icon_cls - Значек кнопки
93
+ confirm_required - Запрашивать подтверждение действия.
94
+ index - Позиция добавления кнопки. По-умолчанию справа.
95
+
96
+ Примеры подключения и использования для ObjectPack'а:
97
+
98
+ def create_list_window(self, *args, **kwargs):
99
+ win = super(ObjectPack, self).create_list_window(*args, **kwargs)
100
+ append_template_globals(win, 'ui-js/object-grid-buttons.js')
101
+ return win
102
+
103
+ def configure_grid(self, grid, *args, **kwargs):
104
+ super(ObjectPack, self).configure_grid(grid, *args, **kwargs)
105
+ add_multi_row_button(
106
+ 'Переотправить', grid, self.resend_action,
107
+ 'icon_send_message ' + Icons.ARROW_ROTATE_CLOCKWISE
108
+ )
109
+ """
110
+ params = _get_multirow_params(label, action, icon_cls, confirm_required)
111
+ button = ext.ExtButton(**params)
112
+ if index is not None:
113
+ grid.top_bar.items.insert(index, button)
114
+ else:
115
+ grid.top_bar.items.append(button)
116
+
117
+ menuitem = ext.ExtContextMenuItem(**params)
118
+ grid.context_menu_row.items.append(menuitem)
119
+
120
+
121
+ def _get_one_row_params(label, action, icon_cls):
122
+ action_url = get_url(action)
123
+ return dict(
124
+ text=label,
125
+ icon_cls=icon_cls,
126
+ handler=_get_one_row_handler(label, action_url),
127
+ )
128
+
129
+
130
+ def _get_multirow_params(label, action, icon_cls, confirm_required):
131
+ action_url = get_url(action)
132
+ return dict(
133
+ text=label,
134
+ icon_cls=icon_cls,
135
+ handler=_get_multi_row_handler(label, action_url, confirm_required),
136
+ )
137
+
138
+
139
+ def _get_action_handler(url):
140
+ return """
141
+ function(){
142
+ onObjGridAction(objGrid, '%s');
143
+ }
144
+ """ % url
145
+
146
+
147
+ def _get_one_row_handler(action_name, url):
148
+ return """
149
+ function(){
150
+ onObjGridOneRecordAction(objGrid, '%s', '%s');
151
+ }
152
+ """ % (action_name, url)
153
+
154
+
155
+ def _get_multi_row_handler(action_name, url, confirm_required):
156
+ return """
157
+ function(){
158
+ onObjGridMultiRecordAction(objGrid, '%s', '%s', %s);
159
+ }
160
+ """ % (action_name, url, int(bool(confirm_required)))
161
+
162
+
163
+ def column_style_renderer(styles_map, default_style=''):
164
+ """Изменение стиля в колонке.
165
+
166
+ :param styles_map: словарь карты стилей по значению в колонке
167
+ :param default_style: стиль по-умолчанию
168
+ """
169
+ func = (
170
+ """function (value, metaData, record, rowIndex, colIndex, store) {
171
+ var styles_map = Ext.util.JSON.decode('%(styles_map)s');
172
+ metaData.style += styles_map[value] || '%(default_style)s';
173
+ return value;
174
+ }""") % {'styles_map': styles_map, 'default_style': default_style}
175
+ return func
176
+
177
+
178
+ def set_grid_initial(grid, initializers):
179
+ """Установка инициализирующих грид функций.
180
+
181
+ :param grid: грид.
182
+ :param initializers: список инициализирующих грид функций
183
+
184
+ Пример:
185
+
186
+ def configure_grid(self, grid, *args, **kwargs):
187
+ super(ObjectPack, self).configure_grid(
188
+ grid, *args, **kwargs)
189
+ set_grid_initial(grid, (
190
+ styling_grid_rows(
191
+ 'result_status_code', ResultStatus.styles,
192
+ 'grid-row-yellow-background'
193
+ ),
194
+ ))
195
+ """
196
+ grid_initializers = ''.join(initializers)
197
+ grid._listeners['added'] = """
198
+ function() {
199
+ var grid = Ext.getCmp('%(client_id)s');
200
+ %(initializers)s
201
+ }
202
+ """ % {'initializers': grid_initializers, 'client_id': grid.client_id}
203
+
204
+
205
+ def styling_grid_rows(data_index, styles_map, default_style=''):
206
+ """Стилизация строк грида по значению в колонке.
207
+
208
+ :param data_index: имя колонки
209
+ :param styles_map: словарь карты стилей по значению в колонке
210
+ :param default_style: стиль по-умолчанию
211
+ """
212
+ return """
213
+ var styles_map = Ext.util.JSON.decode('%(styles_map)s');
214
+ grid.getView().getRowClass = function(record, rowIndex, rp, ds){
215
+ return styles_map[
216
+ record.json.%(data_index)s
217
+ ] || '%(default_style)s';
218
+ };
219
+ """ % {
220
+ 'data_index': data_index,
221
+ 'styles_map': json.dumps(styles_map),
222
+ 'default_style': default_style,
223
+ }
224
+
225
+
226
+ def add_tooltip_to_grid_rows(delegate: str, column_with_text: str) -> str:
227
+ """Добавление всплывающей подсказки для строк грида.
228
+
229
+ :param delegate: css-класс строк к которым добавляется подсказка
230
+ :param column_with_text: наименование колонки содержащей текст подсказки
231
+ """
232
+ return """
233
+ var view = grid.getView();
234
+ var store = grid.getStore();
235
+ grid.on('render', function(grid) {
236
+ grid.tooltip = new Ext.ToolTip({
237
+ target: view.mainBody,
238
+ delegate: '%(delegate)s',
239
+ listeners: {
240
+ show: function updateTipBody(tooltip) {
241
+ var rowIndex = view.findRowIndex(tooltip.triggerElement);
242
+ var text = store.getAt(rowIndex).data['%(column)s'];
243
+ tooltip.update(text);
244
+ }
245
+ }
246
+ });
247
+ });
248
+ """ % {
249
+ 'delegate': delegate,
250
+ 'column': column_with_text,
251
+ }
252
+
253
+
254
+ def boolean_column_renderer():
255
+ """
256
+ Возвращает JS-рендерер для булевых колонок грида
257
+ """
258
+ return 'function(v){return (!!v ? "Да" : "Нет")}'
educommon/utils/ui.py CHANGED
@@ -13,12 +13,18 @@ from django.db.models import (
13
13
  Q,
14
14
  TextField,
15
15
  )
16
+ from m3 import (
17
+ ApplicationLogicException,
18
+ )
16
19
  from m3.actions.context import (
17
20
  ActionContext,
18
21
  )
19
22
  from m3_ext.ui import (
20
23
  all_components as ext,
21
24
  )
25
+ from m3_ext.ui.base import (
26
+ BaseExtComponent,
27
+ )
22
28
  from m3_ext.ui.icons import (
23
29
  Icons,
24
30
  )
@@ -394,3 +400,35 @@ class FilterByTextField(FilterByField):
394
400
  max_length=self.field.max_length,
395
401
  **self._field_fabric_params
396
402
  )
403
+
404
+
405
+ def append_template_globals(comp, template):
406
+ """
407
+ Добавляет шаблон к BaseExtComponent.template_globals.
408
+
409
+ В template_globals допускается использование как строки, так и кортежа
410
+ со списком. Метод введен для возможности простого добавления нового
411
+ шаблона к уже существующим без заглядывания в реализацию базовых
412
+ классов для определения, какого типа ожидается template_globals.
413
+
414
+ :param comp: Компонент, которому нужно добавить шаблон для рендеринга
415
+ :type comp: BaseExtComponent
416
+ :param template: Имя файла шаблона
417
+ :type template: str or unicode
418
+ """
419
+ if not isinstance(comp, BaseExtComponent):
420
+ raise ApplicationLogicException(
421
+ 'Component has no attribute template_globals')
422
+ if isinstance(comp.template_globals, str):
423
+ # если template_globals - пустая строка, просто заменяем ее
424
+ if len(comp.template_globals) == 0:
425
+ comp.template_globals = template
426
+ # иначе создаем кортеж из старого значения и добавляемого
427
+ else:
428
+ comp.template_globals = (comp.template_globals, template)
429
+ elif isinstance(comp.template_globals, tuple):
430
+ comp.template_globals += (template,)
431
+ elif isinstance(comp.template_globals, list):
432
+ comp.template_globals.append(template)
433
+ else:
434
+ raise ApplicationLogicException('Unknown type of template_globals')
educommon/version.conf CHANGED
@@ -4,8 +4,8 @@
4
4
  # нормальной установки обновлений.
5
5
 
6
6
  [version]
7
- BRANCH = tags/3.5.5
8
- VERSION = 3.5.5
9
- REVISION = b237c6e435e2056e12f9a04d94c08b69fdda0bb8
10
- VERSION_DATE = 04.12.2023
11
- REVISION_DATE = 04.12.2023
7
+ BRANCH = tags/3.6.1
8
+ VERSION = 3.6.1
9
+ REVISION = 5c849c3a296d1e7c1b370e73a9a661b385c43293
10
+ VERSION_DATE = 16.12.2023
11
+ REVISION_DATE = 16.12.2023
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: educommon
3
- Version: 3.5.5
3
+ Version: 3.6.1
4
4
  Summary: Общая кодовая база для проектов БЦ Образование
5
5
  Home-page: https://stash.bars-open.ru/projects/EDUBASE/repos/educommon
6
6
  Author: BARS Group
@@ -34,7 +34,7 @@ Requires-Dist: celery
34
34
  Requires-Dist: spyne
35
35
  Requires-Dist: xlsxwriter <1,>=0.9.3
36
36
  Requires-Dist: m3-builder <2,>=1.2
37
- Requires-Dist: m3-db-utils >=0.3.4
37
+ Requires-Dist: m3-db-utils >=0.3.11
38
38
  Requires-Dist: m3-django-compat <2,>=1.9.1
39
39
  Requires-Dist: m3-core <3,>=2.2.16
40
40
  Requires-Dist: m3-ui <3,>=2.2.40
@@ -1,6 +1,6 @@
1
1
  educommon/__init__.py,sha256=fvsBDL7g8HgOTd-JHOh7TSvMcnUauvGVgPuyA2Z9hUI,419
2
2
  educommon/thread_data.py,sha256=n0XtdesP9H92O3rJ8K6fVnJLiHqyJEfh2xpuT36wzxs,61
3
- educommon/version.conf,sha256=kcLlscgL7Gd0L6Do57NSvMaWvRRm1AwScBunCZkjths,448
3
+ educommon/version.conf,sha256=CyZ0wpuD4ZOjQH46Sg9nCZPExDS0F8wrAc0C3w-oTOs,448
4
4
  educommon/about/README.rst,sha256=U48UW5jv-8qHyaV56atzzkNMvzHKXVcWSb_NR06PnMo,2685
5
5
  educommon/about/__init__.py,sha256=H1W0IgW-qX9LCZ49GOJzHdmQGHhh-MA6U1xmNx7WnfM,132
6
6
  educommon/about/apps.py,sha256=GrpJAOE2sF0ukWsqugP_WJS88DO4aL-T3kTLprrJrcA,259
@@ -29,7 +29,7 @@ educommon/audit_log/actions.py,sha256=hPlnFK8Q8uITA6Rn0CvAyxo76pxVGC1X-g8vzWphgG
29
29
  educommon/audit_log/app_meta.py,sha256=fMPgP5S6kDe_lskTEhPVLzjDLDhoVPKCIjUeD4L7sHA,310
30
30
  educommon/audit_log/apps.py,sha256=zHeBEoF8HVNc6YIIQTW-lpEMXjrywnB23uqxXIR9IKg,5033
31
31
  educommon/audit_log/constants.py,sha256=96Gp-rYpt6poKAu8LbXY_0aApdOWYBy09235kAB0rSo,880
32
- educommon/audit_log/helpers.py,sha256=0pU_MJmrSJ_IHDs2safMCzcohV1C1IANloll1I4wtxI,738
32
+ educommon/audit_log/helpers.py,sha256=qJLV6yVgf3Z-Mgalc6kGfFvxk8h1L4bTO9fdSL36OPk,738
33
33
  educommon/audit_log/middleware.py,sha256=HkxBh-1RQJnhKqckkXaMbFjJ34WgZGJssbk04wiS3ts,1140
34
34
  educommon/audit_log/models.py,sha256=F4KW-sdGbKxIKdo3GKpPeu66ykO32MxYZ5afvT_Clyg,8305
35
35
  educommon/audit_log/permissions.py,sha256=VB040UAY4_KmqM4ioToHlVHQYSE7OP0qHEUn9bnWUSo,1241
@@ -55,7 +55,7 @@ educommon/audit_log/sql/configure_audit_log.sql,sha256=M3QxNKTZbn-uNRxGDvNxE9iJh
55
55
  educommon/audit_log/sql/install_audit_log.sql,sha256=SHrZ7WaYxawUKQEpZnj9k4HTU25NvBlxX_POqZ95HU0,14107
56
56
  educommon/audit_log/utils/__init__.py,sha256=qIO8Fre4BMfsKGYi7Q_iFXaKz95d74LxeSOrazhPw1Y,15603
57
57
  educommon/audit_log/utils/operations.py,sha256=Qjdb6FOG3WXbniG4Pau5yDa2Dfn85ivKgSFdw1WPv8A,1661
58
- educommon/auth/__init__.py,sha256=mLddwvbvKsjEozoZqVvDDSiLfiob5UKwynX1dgX4yfU,118
58
+ educommon/auth/__init__.py,sha256=JnKZNoNGR8H9TIS_6wOlMYTabOuvsxacEQGi1tIJ148,127
59
59
  educommon/auth/rbac/__init__.py,sha256=rMC51R-oN3jCqWIkV1Pkfv5xDNSblwR8Eh-P5q66UDI,329
60
60
  educommon/auth/rbac/actions.py,sha256=25zVmGmYWE2gUt2ak13Ao9pOIZlJx6rgir8eLbj6cMM,26872
61
61
  educommon/auth/rbac/app_meta.py,sha256=tnt65zLTfng6qOrlMByGnxfF3gVLZ6OATNf5gCD3IWI,450
@@ -178,7 +178,7 @@ educommon/integration_entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
178
178
  educommon/integration_entities/consts.py,sha256=XMSR-9Q5cLSXe6Bn0JWFQQ8UfTyJfs7LYT1klj0Xvsc,448
179
179
  educommon/integration_entities/entities.py,sha256=v4QQPb8NeQJMdgxjfEcY9_NmPGasQbRPoA10gZEMAjU,2005
180
180
  educommon/integration_entities/enums.py,sha256=MPS3F402TMUP9wDJXBgNHoktVOf-zM8lAD22QphnLtU,335
181
- educommon/integration_entities/helpers.py,sha256=MJtR69vC4m62Lt_cW4uoIFy_JNUogcsxY0-9qKBR1p0,8675
181
+ educommon/integration_entities/helpers.py,sha256=ETX_sn6PeKpUK9mBQQ3vtJy143EklRRB6koOQtpc-5I,9888
182
182
  educommon/integration_entities/mixins.py,sha256=wWb2nA8BAtDC3dAn66CkpvGwrW17E_tJE9f6BcI9EXg,1122
183
183
  educommon/ioc/__init__.py,sha256=1X6uu-hwwxbwRZ6g0whIE04GbpXgU7K80QmtE0v-4kQ,4028
184
184
  educommon/logger/__init__.py,sha256=KhXTyv0V96wX_6QShkVrRIk_mqJtDYpeBMBb8PtBl-A,822
@@ -203,8 +203,9 @@ educommon/m3/extensions/listeners/delete_check/signals.py,sha256=QnfevsAKpKtOE_E
203
203
  educommon/m3/extensions/listeners/delete_check/ui.py,sha256=W3sBsZGbF3q0rxuMUEmycBvFngUh--UQ-77xdjgvDP0,3507
204
204
  educommon/m3/extensions/listeners/delete_check/utils.py,sha256=m4vlKh7zhLbIRV2A8KDS54n1u_t1cL70p6o5E3VwQyQ,2979
205
205
  educommon/objectpack/__init__.py,sha256=TwmrbrumJoH9KjYhbLnKExWmo4A0UQeyNYTK__93Vr8,69
206
- educommon/objectpack/actions.py,sha256=CuUSmfWZn3Cqq57WXmWKTUKDAqZW2Q6Td_de3bfpJMM,14320
206
+ educommon/objectpack/actions.py,sha256=KanZUKMl4aUSRPZV-SJB3JwjDTYzuGweI9L5cE1KziI,14735
207
207
  educommon/objectpack/apps.py,sha256=LZl_kQ9s7G9pQ4a5_mWNPN52mFWJ7RGvGIHCHwhKYPo,220
208
+ educommon/objectpack/filters.py,sha256=je0BIBbwhfVBuGJkeREiFzXuLRMigD8a5okWaY5hsCg,5166
208
209
  educommon/objectpack/ui.py,sha256=SDP3Pjy9rZHdMJtf4Rph5h8BM4fWuxOBrcWsWZ3l-Rk,14752
209
210
  educommon/objectpack/templates/base-grid-window.js,sha256=kq49GGDGPScqLCouIy0-seOimt5eX_l2pAkQNJ0rNCw,437
210
211
  educommon/objectpack/templates/filter-panel.js,sha256=vYw_AxOMRk0ylSBUT46qphilxKkKpaXzT5HfGwwoLYo,1408
@@ -268,6 +269,7 @@ educommon/utils/conversion.py,sha256=kEe15TwIH19RmC2mRl1JrrqD8mXgbCAPOYWnkIQXxqQ
268
269
  educommon/utils/crypto.py,sha256=3uMk2CP53ZOsJ5Tcb0DLWxmk9ezINZQUsQcqF6j8XR0,2158
269
270
  educommon/utils/date.py,sha256=qE2v_nlxgkU6m1qb90eF2Hyn3NyTVBc9y02u765pcko,16799
270
271
  educommon/utils/misc.py,sha256=HGSoCSyF6hAZaeFTTgA2IkIfMAXIuURqh-rzHVNe0LE,3352
272
+ educommon/utils/object_grid.py,sha256=mUJd0HJmj4PVljmkwxlR3mQO__YnlLBmAZcFWGxTHLc,9048
271
273
  educommon/utils/patches.py,sha256=Pio9V3bmDH79tTJnM5hi8rwhMEBtbpAg30zPTk5fuN0,1157
272
274
  educommon/utils/plugins.py,sha256=YAD3FM78ihPtyaB_olNM1CoSc5Q5icF_J3A0ivFBFmY,9469
273
275
  educommon/utils/registry.py,sha256=mC_N9aentmznhLFuJn4vyTd3M7d628otWYIx1aM83KY,1995
@@ -275,7 +277,7 @@ educommon/utils/seqtools.py,sha256=v621d2X1BO8PQeKIioX4V1BlLTnwIt__GJh9zPF1uI8,5
275
277
  educommon/utils/serializer.py,sha256=qdjC6Q6l-bwl9wAzhU6Ujs2_9sc57Z5RA9iNUmzBM74,8787
276
278
  educommon/utils/storage.py,sha256=UwKZX1qnZQgbFn34wLpPnSv_xU6KdpW3M1yz_VxCmww,2883
277
279
  educommon/utils/system.py,sha256=CBdm4t3ng6luvcQANpJiKrJplFmFeM-lX0rKhuII5Ik,2834
278
- educommon/utils/ui.py,sha256=25M8DjZ9QW3ZYUYYHU5VJgvQjyHaCSvNuPyVxR0Fl14,14251
280
+ educommon/utils/ui.py,sha256=zZU6XIi-lV_xkXv_O9fNcvzAs26PpHtcO-3H-mo-KhU,16082
279
281
  educommon/utils/db/__init__.py,sha256=np9pL-_tv4C6i0iQzTjc-ZGKhaotJK8YSryoPaJ0QQA,7734
280
282
  educommon/utils/db/postgresql.py,sha256=3LOvLqG8QV3hsvo_fupkV26cQmSf0WNBhgpVcfs-lWc,2820
281
283
  educommon/utils/fonts/Arial.ttf,sha256=NcDzVZ2NtWnjbDEJW4pg1EFkPZX1kTneQOI_ragZuDM,275572
@@ -323,8 +325,8 @@ educommon/ws_log/smev/exceptions.py,sha256=lmy7o2T3dJkqgIhG07qyh5yPqO3qZAYABuT4J
323
325
  educommon/ws_log/templates/report/smev_logs.xlsx,sha256=nnYgB0Z_ix8HoxsRICjsZfFRQBdra-5Gd8nWhCxTjYg,10439
324
326
  educommon/ws_log/templates/ui-js/smev-logs-list-window.js,sha256=AGup3D8GTJSY9WdDPj0zBJeYQBFOmGgcbxPOJbKK-nY,513
325
327
  educommon/ws_log/templates/ui-js/smev-logs-report-setting-window.js,sha256=nQ7QYK9frJcE7g7kIt6INg9TlEEJAPPayBJgRaoTePA,1103
326
- educommon-3.5.5.dist-info/METADATA,sha256=ZXRFmVo6h6nBJBIa-kTCdJ1BDrif-kt4vWqCULEVk9U,1735
327
- educommon-3.5.5.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
328
- educommon-3.5.5.dist-info/dependency_links.txt,sha256=RNlr4t-BxZRm7e_IfVo1ikr5ln-7viimzLHvQMO1C_Q,43
329
- educommon-3.5.5.dist-info/top_level.txt,sha256=z5fbW7bz_0V1foUm_FGcZ9_MTpW3N1dBN7-kEmMowl4,10
330
- educommon-3.5.5.dist-info/RECORD,,
328
+ educommon-3.6.1.dist-info/METADATA,sha256=j7fq3ajpRnYwfk1aYrW_xomuaEyvu5SBE8ePinJisTY,1736
329
+ educommon-3.6.1.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
330
+ educommon-3.6.1.dist-info/dependency_links.txt,sha256=RNlr4t-BxZRm7e_IfVo1ikr5ln-7viimzLHvQMO1C_Q,43
331
+ educommon-3.6.1.dist-info/top_level.txt,sha256=z5fbW7bz_0V1foUm_FGcZ9_MTpW3N1dBN7-kEmMowl4,10
332
+ educommon-3.6.1.dist-info/RECORD,,