accrete 0.0.53__py3-none-any.whl → 0.0.55__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.
@@ -13,7 +13,8 @@ from .context import (
13
13
  extract_url_params,
14
14
  exclude_params,
15
15
  url_param_str,
16
- get_table_fields
16
+ get_table_fields,
17
+ default_table_context
17
18
  )
18
19
  from .elements import (
19
20
  ClientActionGroup,
@@ -1,12 +1,13 @@
1
1
  import logging
2
+ import json
2
3
  from urllib.parse import quote_plus
3
4
  from dataclasses import dataclass, field
4
- from typing import TypedDict, Callable
5
+ from typing import Type, TypedDict, Callable
5
6
  from django.utils.translation import gettext_lazy as _t
6
7
  from django.db import models
7
8
  from django.db.models import Model, QuerySet
8
9
  from django.core.paginator import Paginator
9
- from django.core import paginator
10
+ from django.core import paginator, exceptions
10
11
  from django.forms import Form, ModelForm
11
12
  from accrete.annotation import Annotation
12
13
  from .elements import (
@@ -14,7 +15,7 @@ from .elements import (
14
15
  ClientActionGroup
15
16
  )
16
17
  from .filter import Filter
17
-
18
+ from accrete.utils import filter_from_querystring
18
19
 
19
20
  _logger = logging.getLogger(__name__)
20
21
 
@@ -60,6 +61,46 @@ class TableContext(Context):
60
61
  field_selection: bool = True
61
62
 
62
63
 
64
+ def default_table_context(model: Type[Model], params: dict, queryset=None, **kwargs) -> TableContext:
65
+ if queryset is None:
66
+ queryset = filter_from_querystring(model, params)
67
+ page = list_page(
68
+ queryset,
69
+ cast_param(params, 'paginate_by', int, 40),
70
+ cast_param(params, 'page', int, 1)
71
+ )
72
+ try:
73
+ has_name_field = (
74
+ model._meta.get_field('name').get_internal_type() == 'CharField'
75
+ )
76
+ except exceptions.FieldDoesNotExist:
77
+ has_name_field = False
78
+
79
+ ctx = TableContext(
80
+ title=str(model._meta.verbose_name_plural),
81
+ object_label=str(model._meta.verbose_name),
82
+ object_param_str=url_param_str(
83
+ params,
84
+ ['q', 'paginate_by', 'page', 'fields']
85
+ ),
86
+ fields=get_table_fields(
87
+ cast_param(params, 'fields', json.loads, []), model
88
+ ),
89
+ list_page=page,
90
+ pagination_param_str=url_param_str(
91
+ params, ['q', 'paginate_by', 'fields']
92
+ ),
93
+ endless_scroll=True,
94
+ filter=Filter(
95
+ model,
96
+ default_filter_term='name__icontains' if has_name_field else ''
97
+ ),
98
+ kwargs=kwargs
99
+ )
100
+ return ctx
101
+
102
+
103
+
63
104
  @dataclass
64
105
  class ListContext(Context):
65
106
 
@@ -67,7 +108,7 @@ class ListContext(Context):
67
108
  object_param_str: str
68
109
  list_page: paginator.Page
69
110
  pagination_param_str: str
70
- filter: Filter
111
+ filter: Filter = None
71
112
  endless_scroll: bool = True
72
113
  column_height: int = 4
73
114
  column_width: int = 12
@@ -93,7 +134,9 @@ class DetailContext(Context):
93
134
  class FormContext(Context):
94
135
 
95
136
  form: Form | ModelForm
96
- form_id: str
137
+ form_id: str = 'form'
138
+ form_method: str = 'post'
139
+ form_action: str = ''
97
140
 
98
141
 
99
142
  def cast_param(params: dict, param: str, cast_to: Callable, default):
@@ -115,9 +158,8 @@ def url_param_dict(get_params: dict) -> dict:
115
158
 
116
159
  def url_param_str(params: dict, extract: list[str] = None) -> str:
117
160
  """
118
- Return a URL Querystring from the given parameters
119
- If extract is supplied, extract the value from the dictionary and prepare
120
- them, so that each value is formatted e.g. {'page': '&page=1'}
161
+ Return a URL Querystring from the given params dict.
162
+ If extract is supplied, only specified keys will be used.
121
163
  """
122
164
  if extract:
123
165
  params = extract_url_params(params, extract)
@@ -155,6 +197,15 @@ def detail_page(queryset: QuerySet, obj: Model) -> dict:
155
197
  'deactivate pagination.'
156
198
  )
157
199
  return {}
200
+ if obj not in queryset:
201
+ url = obj.get_absolute_url()
202
+ return {
203
+ 'previous_object_url': url,
204
+ 'next_object_url': url,
205
+ 'current_object_idx': 1,
206
+ 'total_objects': 1
207
+ }
208
+
158
209
  idx = (*queryset,).index(obj)
159
210
  previous_object_url = (
160
211
  queryset[idx - 1] if idx - 1 >= 0 else queryset.last()
@@ -1,4 +1,3 @@
1
- import time
2
1
  import logging
3
2
  from django.db.models.fields.related import ManyToOneRel, ManyToManyRel
4
3
  from django.core.cache import cache
@@ -301,10 +300,11 @@ class Filter:
301
300
  and not isinstance(x, (ManyToOneRel, ManyToManyRel)),
302
301
  self.model._meta.get_fields()
303
302
  )]
304
- fields.extend([
305
- (x['annotation'].verbose_name, x['name'])
306
- for x in self.model.get_annotations()
307
- ])
303
+ if hasattr(self.model, 'get_annotations'):
304
+ fields.extend([
305
+ (x['annotation'].verbose_name, x['name'])
306
+ for x in self.model.get_annotations()
307
+ ])
308
308
  sorted_fields = sorted(fields, key=lambda x: x[0].lower())
309
309
  for field in sorted_fields:
310
310
  html += f"""
@@ -20923,10 +20923,9 @@ select:focus {
20923
20923
  border-bottom-right-radius: 0;
20924
20924
  }
20925
20925
 
20926
- #list-customization * .dropdown-menu {
20927
- width: 292px;
20928
- border-top-left-radius: 0;
20929
- border-top-right-radius: 0;
20926
+ .dropdown-button.is-active {
20927
+ border-bottom-left-radius: 0;
20928
+ border-bottom-right-radius: 0;
20930
20929
  }
20931
20930
 
20932
20931
  @media screen and (max-width: 768px) {
@@ -20956,6 +20955,23 @@ select:focus {
20956
20955
  display: inline-block;
20957
20956
  }
20958
20957
  }
20958
+ /* Chrome, Safari, Edge, Opera */
20959
+ input::-webkit-outer-spin-button,
20960
+ input::-webkit-inner-spin-button {
20961
+ -webkit-appearance: none;
20962
+ margin: 0;
20963
+ }
20964
+
20965
+ /* Firefox */
20966
+ input[type=number] {
20967
+ -moz-appearance: textfield;
20968
+ }
20969
+
20970
+ /* Fix CKEditor List Display */
20971
+ .ck-editor__editable_inline {
20972
+ padding: 0 30px !important;
20973
+ }
20974
+
20959
20975
  @media screen and (max-width: 1407px) {
20960
20976
  #list-customization * .dropdown-menu {
20961
20977
  width: auto;