accrete 0.0.9__py3-none-any.whl → 0.0.11__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.
- accrete/contrib/ui/__init__.py +1 -2
- accrete/contrib/ui/helper.py +31 -29
- accrete/contrib/ui/static/css/accrete.css +31 -99
- accrete/contrib/ui/templates/ui/detail.html +0 -1
- accrete/contrib/ui/templates/ui/form.html +0 -1
- accrete/contrib/ui/templates/ui/layout.html +70 -55
- accrete/contrib/ui/templates/ui/list.html +8 -20
- accrete/contrib/ui/templates/ui/partials/header.html +25 -37
- accrete/contrib/ui/templates/ui/partials/pagination_detail.html +7 -11
- accrete/contrib/ui/templates/ui/partials/pagination_list.html +7 -9
- accrete/contrib/ui/templates/ui/table.html +28 -29
- accrete/contrib/ui/templatetags/accrete_ui.py +15 -0
- accrete/contrib/ui/views.py +1 -1
- {accrete-0.0.9.dist-info → accrete-0.0.11.dist-info}/METADATA +1 -1
- {accrete-0.0.9.dist-info → accrete-0.0.11.dist-info}/RECORD +17 -19
- accrete/contrib/ui/config.py +0 -10
- accrete/contrib/ui/templates/ui/partials/actions.html +0 -30
- {accrete-0.0.9.dist-info → accrete-0.0.11.dist-info}/WHEEL +0 -0
- {accrete-0.0.9.dist-info → accrete-0.0.11.dist-info}/licenses/LICENSE +0 -0
accrete/contrib/ui/__init__.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
from . import config
|
2
1
|
from .filter import Filter
|
3
2
|
from .helper import (
|
4
3
|
ClientAction,
|
@@ -6,7 +5,7 @@ from .helper import (
|
|
6
5
|
FormContext,
|
7
6
|
ListContext,
|
8
7
|
BreadCrumb,
|
8
|
+
TableField,
|
9
9
|
build_querystring,
|
10
|
-
parse_client_actions,
|
11
10
|
queryset_from_querystring
|
12
11
|
)
|
accrete/contrib/ui/helper.py
CHANGED
@@ -8,11 +8,10 @@ from django.utils.translation import gettext_lazy as _
|
|
8
8
|
from django.core.exceptions import FieldDoesNotExist
|
9
9
|
from django.core.paginator import Paginator
|
10
10
|
from accrete.contrib.ui.filter import Filter
|
11
|
-
from . import config
|
12
11
|
|
13
12
|
_logger = logging.getLogger(__name__)
|
14
13
|
|
15
|
-
|
14
|
+
DEFAULT_PAGINATE_BY = 40
|
16
15
|
|
17
16
|
|
18
17
|
@dataclass
|
@@ -25,18 +24,6 @@ class ClientAction:
|
|
25
24
|
submit: bool = False
|
26
25
|
form_id: str = 'form'
|
27
26
|
class_list: list = field(default_factory=list)
|
28
|
-
mobile: bool = True
|
29
|
-
tablet: bool = True
|
30
|
-
|
31
|
-
|
32
|
-
def parse_client_actions(actions: list[ClientAction], actions_template: str = None):
|
33
|
-
tablet = (not all(action.tablet for action in actions))
|
34
|
-
mobile = (not all(action.mobile for action in actions))
|
35
|
-
return {
|
36
|
-
'actions_template': actions_template or ACTIONS_TEMPLATE,
|
37
|
-
'actions': actions,
|
38
|
-
'action_button': {'mobile': mobile, 'tablet': tablet}
|
39
|
-
}
|
40
27
|
|
41
28
|
|
42
29
|
@dataclass
|
@@ -46,6 +33,13 @@ class BreadCrumb:
|
|
46
33
|
url: str
|
47
34
|
|
48
35
|
|
36
|
+
@dataclass
|
37
|
+
class TableField:
|
38
|
+
|
39
|
+
label: str
|
40
|
+
name: str
|
41
|
+
|
42
|
+
|
49
43
|
@dataclass
|
50
44
|
class ListContext:
|
51
45
|
|
@@ -57,12 +51,14 @@ class ListContext:
|
|
57
51
|
extra_query: Q = None
|
58
52
|
related_fields: list[str] = field(default_factory=list)
|
59
53
|
prefetch_fields: list[str] = field(default_factory=list)
|
60
|
-
paginate_by: int =
|
54
|
+
paginate_by: int = DEFAULT_PAGINATE_BY
|
61
55
|
order_by: list[str] = None
|
62
56
|
column_width: int = 12
|
63
57
|
filter_relation_depth: int = 4
|
64
58
|
actions: list[ClientAction] = field(default_factory=list)
|
65
59
|
breadcrumbs: list[BreadCrumb] = field(default_factory=list)
|
60
|
+
obj_label: str = None
|
61
|
+
fields: list[TableField] = field(default_factory=list)
|
66
62
|
|
67
63
|
def get_queryset(self):
|
68
64
|
order = self.get_order()
|
@@ -116,10 +112,11 @@ class ListContext:
|
|
116
112
|
'filter_terms': Filter(self.model, self.filter_relation_depth).get_query_terms(),
|
117
113
|
'view_type': 'list',
|
118
114
|
'breadcrumbs': self.breadcrumbs,
|
119
|
-
'querystring': build_querystring(self.get_params)
|
115
|
+
'querystring': build_querystring(self.get_params),
|
116
|
+
'actions': self.actions,
|
117
|
+
'obj_label': self.obj_label or _('Name'),
|
118
|
+
'fields': self.fields
|
120
119
|
}
|
121
|
-
if self.actions:
|
122
|
-
context.update(parse_client_actions(self.actions))
|
123
120
|
context.update(self.context)
|
124
121
|
return context
|
125
122
|
|
@@ -130,14 +127,15 @@ class DetailContext:
|
|
130
127
|
obj: Model
|
131
128
|
get_params: dict
|
132
129
|
order_by: str = None
|
133
|
-
paginate_by: int =
|
130
|
+
paginate_by: int = DEFAULT_PAGINATE_BY
|
134
131
|
title: str = None
|
135
132
|
queryset: type[QuerySet] = None
|
136
133
|
extra_query: Q = None
|
137
134
|
related_fields: list[str] = field(default_factory=list)
|
138
135
|
prefetch_fields: list[str] = field(default_factory=list)
|
139
136
|
actions: list[ClientAction] = field(default_factory=list)
|
140
|
-
breadcrumbs: list[BreadCrumb] = field(default_factory=list)
|
137
|
+
breadcrumbs: list[BreadCrumb] = field(default_factory=list),
|
138
|
+
context: dict = field(default_factory=dict)
|
141
139
|
|
142
140
|
def get_queryset(self):
|
143
141
|
order = self.get_order()
|
@@ -197,25 +195,26 @@ class DetailContext:
|
|
197
195
|
'detail_pagination': False,
|
198
196
|
'view_type': 'detail',
|
199
197
|
'breadcrumbs': self.breadcrumbs,
|
200
|
-
'querystring': build_querystring(self.get_params, ['page'])
|
198
|
+
'querystring': build_querystring(self.get_params, ['page']),
|
199
|
+
'actions': self.actions
|
201
200
|
}
|
202
201
|
if self.paginate_by > 0:
|
203
202
|
ctx.update(self.get_pagination_context())
|
204
|
-
|
205
|
-
ctx.update(parse_client_actions(self.actions))
|
203
|
+
ctx.update(self.context)
|
206
204
|
return ctx
|
207
205
|
|
208
206
|
|
209
207
|
@dataclass
|
210
208
|
class FormContext:
|
211
209
|
|
212
|
-
model: Model|type[Model]
|
210
|
+
model: Model | type[Model]
|
213
211
|
get_params: dict
|
214
212
|
title: str = None
|
215
213
|
context: dict = field(default_factory=dict)
|
216
214
|
form_id: str = 'form'
|
217
215
|
add_default_actions: bool = True
|
218
216
|
discard_url: str = None
|
217
|
+
actions: list[ClientAction] = field(default_factory=list)
|
219
218
|
|
220
219
|
def get_default_form_actions(self):
|
221
220
|
actions = [
|
@@ -228,12 +227,11 @@ class FormContext:
|
|
228
227
|
]
|
229
228
|
try:
|
230
229
|
url = self.discard_url or self.model.get_absolute_url()
|
231
|
-
except TypeError
|
232
|
-
|
230
|
+
except TypeError:
|
231
|
+
raise TypeError(
|
233
232
|
'Supply the discard_url parameter if FormContext is called '
|
234
233
|
'with a model class instead of an instance.'
|
235
234
|
)
|
236
|
-
raise e
|
237
235
|
except AttributeError as e:
|
238
236
|
_logger.error(
|
239
237
|
'Supply the discard_url parameter if FormContext is '
|
@@ -264,10 +262,12 @@ class FormContext:
|
|
264
262
|
'title': self.get_title(),
|
265
263
|
'view_type': 'form',
|
266
264
|
'form_id': self.form_id,
|
267
|
-
'querystring': build_querystring(self.get_params, ['page'])
|
265
|
+
'querystring': build_querystring(self.get_params, ['page']),
|
266
|
+
'actions': []
|
268
267
|
}
|
269
268
|
if self.add_default_actions:
|
270
|
-
ctx.update(
|
269
|
+
ctx.update({'actions': self.get_default_form_actions()})
|
270
|
+
ctx['actions'].extend(self.actions)
|
271
271
|
ctx.update(self.context)
|
272
272
|
return ctx
|
273
273
|
|
@@ -276,6 +276,8 @@ def build_querystring(get_params: dict, extra_params: list[str] = None) -> str:
|
|
276
276
|
querystring = f'?q={get_params.get("q", "[]")}'
|
277
277
|
if paginate_by := get_params.get('paginate_by', False):
|
278
278
|
querystring += f'&paginate_by={paginate_by}'
|
279
|
+
# if page := get_params.get('page', False):
|
280
|
+
# querystring += f'&page={page}'
|
279
281
|
if order_by := get_params.get('order_by', False):
|
280
282
|
querystring += f'&order_by={order_by}'
|
281
283
|
for param in extra_params or []:
|
@@ -1,32 +1,9 @@
|
|
1
|
-
.
|
2
|
-
|
3
|
-
top: 0;
|
4
|
-
background: white;
|
5
|
-
}
|
6
|
-
|
7
|
-
table {
|
8
|
-
margin-bottom: 12px !important;
|
9
|
-
}
|
10
|
-
|
11
|
-
th {
|
12
|
-
background-color: white;
|
13
|
-
}
|
14
|
-
|
15
|
-
/*tbody > tr:hover {*/
|
16
|
-
/* background-color: #f5f5f5;*/
|
17
|
-
/*}*/
|
18
|
-
|
19
|
-
label {
|
20
|
-
word-break: break-word;
|
21
|
-
}
|
22
|
-
|
23
|
-
.dropdown-link:hover {
|
24
|
-
cursor: pointer;
|
25
|
-
background-color: #f5f5f5;
|
1
|
+
.columns {
|
2
|
+
margin: 0;
|
26
3
|
}
|
27
4
|
|
28
|
-
.
|
29
|
-
|
5
|
+
.columns:last-child {
|
6
|
+
margin-bottom: 0;
|
30
7
|
}
|
31
8
|
|
32
9
|
.main-columns {
|
@@ -34,34 +11,16 @@ label {
|
|
34
11
|
height: 100vh;
|
35
12
|
}
|
36
13
|
|
37
|
-
.
|
38
|
-
|
39
|
-
padding: 0 4px 0 0;
|
40
|
-
border-radius: 0;
|
41
|
-
position: sticky;
|
42
|
-
top: 0;
|
43
|
-
}
|
44
|
-
|
45
|
-
.side-panel > .panel {
|
46
|
-
border-radius: 0;
|
47
|
-
height: 100%;
|
48
|
-
overflow-y: auto;
|
49
|
-
position: sticky;
|
50
|
-
top: 0;
|
51
|
-
}
|
52
|
-
|
53
|
-
.info-panel {
|
54
|
-
padding: 4px;
|
55
|
-
border-radius: 0;
|
14
|
+
.column {
|
15
|
+
padding: 0;
|
56
16
|
}
|
57
17
|
|
58
|
-
.
|
59
|
-
|
60
|
-
box-shadow: 0 0 0 0
|
18
|
+
.breadcrumb * a {
|
19
|
+
color: #0a0a0a;
|
61
20
|
}
|
62
21
|
|
63
|
-
.
|
64
|
-
|
22
|
+
.table td, .table th {
|
23
|
+
padding: .2rem .75rem .2rem 0;
|
65
24
|
}
|
66
25
|
|
67
26
|
td > a {
|
@@ -69,15 +28,7 @@ td > a {
|
|
69
28
|
width:100%;
|
70
29
|
}
|
71
30
|
|
72
|
-
|
73
|
-
word-wrap: break-word
|
74
|
-
}
|
75
|
-
|
76
|
-
.list-link {
|
77
|
-
color: #48c78e;
|
78
|
-
}
|
79
|
-
|
80
|
-
a:link:not(.list-link) {
|
31
|
+
a {
|
81
32
|
color: #0a0a0a;
|
82
33
|
}
|
83
34
|
|
@@ -85,39 +36,10 @@ a:visited {
|
|
85
36
|
color: #0a0a0a;
|
86
37
|
}
|
87
38
|
|
88
|
-
.
|
89
|
-
height: 100%;
|
90
|
-
overflow-y: auto;
|
91
|
-
}
|
92
|
-
|
93
|
-
.content-column > table > thead th {
|
94
|
-
position: sticky;
|
95
|
-
top: 0;
|
96
|
-
}
|
97
|
-
|
98
|
-
.buttons > .panel-block {
|
99
|
-
padding: .5rem 0 .5rem .5rem;
|
100
|
-
}
|
101
|
-
|
102
|
-
.level-item > .panel-block {
|
103
|
-
padding-left: 2px;
|
104
|
-
padding-right: 2px;
|
105
|
-
}
|
106
|
-
|
107
|
-
.level-item > .panel-block:first-child {
|
108
|
-
padding-left: 0;
|
109
|
-
}
|
110
|
-
|
111
|
-
.panel-block:not(:last-child) {
|
39
|
+
.side-panel * .panel-block:not(:last-child) {
|
112
40
|
border-bottom: none !important;
|
113
41
|
}
|
114
42
|
|
115
|
-
.container > .level {
|
116
|
-
margin: 0;
|
117
|
-
max-width: 100%;
|
118
|
-
overflow-x: hidden;
|
119
|
-
}
|
120
|
-
|
121
43
|
.level * {
|
122
44
|
max-width: 100%;
|
123
45
|
}
|
@@ -126,10 +48,6 @@ a:visited {
|
|
126
48
|
word-break: break-all;
|
127
49
|
}
|
128
50
|
|
129
|
-
.columns {
|
130
|
-
margin: 0;
|
131
|
-
}
|
132
|
-
|
133
51
|
input:focus {
|
134
52
|
outline: 1px solid #48c78e !important;
|
135
53
|
border: 1px solid #48c78e !important;
|
@@ -218,8 +136,22 @@ select:focus {
|
|
218
136
|
margin-bottom: 0;
|
219
137
|
}
|
220
138
|
|
221
|
-
.
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
139
|
+
.label.has-field {
|
140
|
+
height: 100%;
|
141
|
+
display: flex;
|
142
|
+
flex-direction: column;
|
143
|
+
justify-content: end;
|
144
|
+
font-weight: 300;
|
145
|
+
word-break: break-all;
|
146
|
+
padding: 12px 12px 12px 0;
|
147
|
+
}
|
148
|
+
|
149
|
+
.label.is-required {
|
150
|
+
font-weight: 700;
|
151
|
+
}
|
152
|
+
|
153
|
+
@media screen and (max-width: 768px) {
|
154
|
+
.label.has-field {
|
155
|
+
padding: 12px 0 12px 0;
|
156
|
+
}
|
157
|
+
}
|
@@ -3,7 +3,7 @@
|
|
3
3
|
{% load i18n %}
|
4
4
|
{% load accrete_ui %}
|
5
5
|
|
6
|
-
<html lang="en">
|
6
|
+
<html lang="en" style="overflow: hidden">
|
7
7
|
|
8
8
|
<head>
|
9
9
|
{% block head %}
|
@@ -62,47 +62,79 @@
|
|
62
62
|
{% endblock %}
|
63
63
|
|
64
64
|
<div class="main-columns columns m-0 is-mobile">
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
<
|
69
|
-
{%
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
{%
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
<div
|
80
|
-
{%
|
65
|
+
<div class="side-panel column is-3-widescreen is-2-fullhd is-hidden-touch is-hidden-desktop-only is-hidden-widescreen-only p-0" style="height: 100%; position: sticky; top: 0">
|
66
|
+
<nav class="panel is-shadowless pb-5" style="height: 100%; overflow-y: auto; position: sticky; top: 0">
|
67
|
+
{% if list_pagination %}
|
68
|
+
<div class="panel-block pb-0">
|
69
|
+
{% include 'ui/partials/pagination_list.html' %}
|
70
|
+
</div>
|
71
|
+
{% endif %}
|
72
|
+
{% if detail_pagination %}
|
73
|
+
<div class="panel-block pb-0">
|
74
|
+
{% include 'ui/partials/pagination_detail.html' %}
|
75
|
+
</div>
|
76
|
+
{% endif %}
|
77
|
+
<div id="panel-actions">
|
78
|
+
{% for action in actions %}
|
79
|
+
<div class="panel-block pb-0">
|
80
|
+
{% if action.submit %}
|
81
|
+
<input class="button is-fullwidth {{ action.class_list|join:' ' }}"
|
82
|
+
type="submit" form={{ action.form_id }} value="{{ action.name }}"
|
83
|
+
{% for attr in action.attrs %}{{ attr }}{% endfor %}
|
84
|
+
>
|
85
|
+
{% else %}
|
86
|
+
<a class="button is-fullwidth {{ action.class_list|join:' ' }}"
|
87
|
+
href="{{ action.url }}{{ querystring|default_if_none:'?' }}{% if page %}&page={{ page.number }}{% endif %}{{ action.query_params }}"
|
88
|
+
{% for attr in action.attrs %}{{ attr }}{% endfor %}
|
89
|
+
>{{ action.name }}
|
90
|
+
</a>
|
91
|
+
{% endif %}
|
81
92
|
</div>
|
82
|
-
|
83
|
-
<div class="panel-list px-3 has-text-centered">
|
84
|
-
<span>{% translate 'Filter' %}</span>
|
85
|
-
</div>
|
86
|
-
<div class="panel-block" style="position: sticky">
|
87
|
-
<button id="reset-filter-button"
|
88
|
-
class="button is-fullwidth mr-1">{% translate 'Reset' %}
|
89
|
-
</button>
|
90
|
-
<button id="apply-filter-button"
|
91
|
-
class="button is-fullwidth ml-1">{% translate 'Filter' %}
|
92
|
-
</button>
|
93
|
-
</div>
|
94
|
-
<div id="filter-panel">
|
95
|
-
{% include 'ui/partials/filter.html' %}
|
96
|
-
</div>
|
97
|
-
{% endif %}
|
98
|
-
</nav>
|
93
|
+
{% endfor %}
|
99
94
|
</div>
|
100
|
-
|
95
|
+
{% if filter_terms %}
|
96
|
+
<div id="filter-panel" class="mt-2">
|
97
|
+
<div class="panel-list px-3 has-text-centered">
|
98
|
+
<span>{% translate 'Filter' %}</span>
|
99
|
+
</div>
|
100
|
+
<div class="panel-block" style="position: sticky">
|
101
|
+
<button id="reset-filter-button"
|
102
|
+
class="button is-fullwidth mr-1">{% translate 'Reset' %}
|
103
|
+
</button>
|
104
|
+
<button id="apply-filter-button"
|
105
|
+
class="button is-fullwidth ml-1">{% translate 'Filter' %}
|
106
|
+
</button>
|
107
|
+
</div>
|
108
|
+
{% include 'ui/partials/filter.html' %}
|
109
|
+
</div>
|
110
|
+
{% endif %}
|
111
|
+
</nav>
|
112
|
+
</div>
|
101
113
|
|
102
|
-
|
103
|
-
|
114
|
+
<div class="column" style="overflow-x: auto">
|
115
|
+
<div class="is-flex is-flex-direction-column" style="height: 100%; overflow: hidden">
|
116
|
+
<div>
|
117
|
+
{% include 'ui/partials/header.html' %}
|
118
|
+
</div>
|
119
|
+
<div id="content" class="px-3 pb-4" style="overflow: auto; flex-grow: 1">
|
120
|
+
{% block messages %}{% endblock %}
|
121
|
+
{% block content %}{% endblock %}
|
122
|
+
</div>
|
123
|
+
<div>
|
124
|
+
{% if list_pagination or detail_pagination %}
|
125
|
+
<div class="level is-hidden-tablet is-align-self-flex-start m-3">
|
126
|
+
<div class="level-item is-align-content-flex-start">
|
127
|
+
{% if list_pagination %}
|
128
|
+
{% include 'ui/partials/pagination_list.html' %}
|
129
|
+
{% elif detail_pagination %}
|
130
|
+
{% include 'ui/partials/pagination_detail.html' %}
|
131
|
+
{% endif %}
|
132
|
+
</div>
|
133
|
+
</div>
|
134
|
+
{% endif %}
|
135
|
+
</div>
|
104
136
|
</div>
|
105
|
-
|
137
|
+
</div>
|
106
138
|
</div>
|
107
139
|
|
108
140
|
{% if filter_terms %}
|
@@ -126,22 +158,5 @@
|
|
126
158
|
</div>
|
127
159
|
{% endif %}
|
128
160
|
|
129
|
-
{% if actions %}
|
130
|
-
<div id="action-modal" class="modal">
|
131
|
-
<div class="modal-background action-modal-close"></div>
|
132
|
-
<div class="modal-card">
|
133
|
-
<header class="modal-card-head">
|
134
|
-
<p class="modal-card-title">
|
135
|
-
{% block action_modal_title %}{% translate 'Actions' %}{% endblock %}</p>
|
136
|
-
<button class="delete action-modal-close" aria-label="close"></button>
|
137
|
-
</header>
|
138
|
-
<section class="modal-card-body">
|
139
|
-
<div id="modal-actions">
|
140
|
-
{% block action_modal_body %}{% if actions_template %}{% include actions_template with all=True %}{% endif %}{% endblock %}
|
141
|
-
</div>
|
142
|
-
</section>
|
143
|
-
</div>
|
144
|
-
</div>
|
145
|
-
{% endif %}
|
146
161
|
<div id="form-modal" class="modal"></div>
|
147
162
|
</body>
|
@@ -8,27 +8,15 @@
|
|
8
8
|
{% endblock %}
|
9
9
|
|
10
10
|
{% block content %}
|
11
|
-
<div
|
12
|
-
|
13
|
-
{
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
<div class="columns is-multiline">
|
12
|
+
{% for obj in page %}
|
13
|
+
<div class="column is-{{ column_width }}">
|
14
|
+
<div class="box p-2 pb-4 mb-1" style="word-break: break-word; height: 100%; border: solid #ccc 1px">
|
15
|
+
{% block object_data %}
|
16
|
+
{{ obj }}
|
17
|
+
{% endblock %}
|
17
18
|
</div>
|
18
19
|
</div>
|
19
|
-
|
20
|
-
<div class="columns is-multiline pl-1 mb-5" style="max-width: 100%">
|
21
|
-
{% for obj in page %}
|
22
|
-
<div class="column is-{{ column_width }} mb-0 pr-0 pb-1 pt-0">
|
23
|
-
<div class="box p-2 pb-4 mb-1" style="word-break: break-word; height: 100%; border: solid #ccc 1px">
|
24
|
-
{% block object_data %}
|
25
|
-
{{ obj }}
|
26
|
-
{% endblock %}
|
27
|
-
</div>
|
28
|
-
</div>
|
29
|
-
{% endfor %}
|
30
|
-
</div>
|
31
|
-
</div>
|
32
|
-
</div>
|
20
|
+
{% endfor %}
|
33
21
|
</div>
|
34
22
|
{% endblock %}
|
@@ -1,18 +1,7 @@
|
|
1
1
|
{% load i18n %}
|
2
2
|
|
3
|
-
<div
|
4
|
-
{% if
|
5
|
-
<div class="level is-hidden-tablet is-hidden-fullhd is-align-self-flex-start pt-3 mx-2 mb-0">
|
6
|
-
<div class="level-item is-align-content-flex-start">
|
7
|
-
{% if list_pagination %}
|
8
|
-
{% include 'ui/partials/pagination_list.html' %}
|
9
|
-
{% elif detail_pagination %}
|
10
|
-
{% include 'ui/partials/pagination_detail.html' %}
|
11
|
-
{% endif %}
|
12
|
-
</div>
|
13
|
-
</div>
|
14
|
-
{% endif %}
|
15
|
-
<div class="level pt-4 px-3 level-is-shrinkable is-flex {% if detail_pagination %}is-mobile {% endif %}{% if list_pagination %}mb-1 {% else %}mb-0{% endif %}">
|
3
|
+
<div class="pt-3">
|
4
|
+
<div class="level level-is-shrinkable is-flex mb-2 pl-3 {% if detail_pagination %}is-mobile {% endif %}">
|
16
5
|
<div class="level-left">
|
17
6
|
<div class="level-item has-text-weight-bold">
|
18
7
|
<nav class="breadcrumb" aria-label="breadcrumbs" style="white-space: unset; word-break: break-word">
|
@@ -26,7 +15,7 @@
|
|
26
15
|
</div>
|
27
16
|
</div>
|
28
17
|
{% if list_pagination or detail_pagination %}
|
29
|
-
<div class="level-right is-mobile is-hidden-mobile is-hidden-fullhd
|
18
|
+
<div class="level-right is-mobile is-hidden-mobile is-hidden-fullhd is-align-self-flex-start px-3">
|
30
19
|
<div class="level-item">
|
31
20
|
{% if list_pagination %}
|
32
21
|
{% include 'ui/partials/pagination_list.html' %}
|
@@ -38,28 +27,27 @@
|
|
38
27
|
{% endif %}
|
39
28
|
</div>
|
40
29
|
|
41
|
-
<div class="
|
42
|
-
<div class="
|
43
|
-
|
44
|
-
|
45
|
-
{
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
{
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
</div>
|
58
|
-
<div class="level-item is-mobile is-hidden-fullhd is-hidden-mobile mr-0">
|
59
|
-
<div class="buttons">
|
60
|
-
<button id="modal-filter-button" class="button">Filter</button>
|
61
|
-
</div>
|
62
|
-
</div>
|
30
|
+
<div class="is-flex is-hidden-fullhd is-justify-content-space-between mb-2">
|
31
|
+
<div class="is-flex py-1 px-1 ml-2" style="overflow-x: auto">
|
32
|
+
{% for action in actions %}
|
33
|
+
{% if action.submit %}
|
34
|
+
<input class="button mr-2 {{ action.class_list|join:' ' }}"
|
35
|
+
type="submit" form={{ action.form_id }} value="{{ action.name }}"
|
36
|
+
{% for attr in action.attrs %}{{ attr }}{% endfor %}
|
37
|
+
>
|
38
|
+
{% else %}
|
39
|
+
<a class="button mr-2 {{ action.class_list|join:' ' }}"
|
40
|
+
href="{{ action.url }}{{ querystring|default_if_none:'?' }}{% if page %}&page={{ page.number }}{% endif %}{{ action.query_params }}"
|
41
|
+
{% for attr in action.attrs %}{{ attr }}{% endfor %}
|
42
|
+
>{{ action.name }}
|
43
|
+
</a>
|
44
|
+
{% endif %}
|
45
|
+
{% endfor %}
|
63
46
|
</div>
|
47
|
+
{% if filter_terms %}
|
48
|
+
<div class="is-flex ml-2 py-1 pr-3">
|
49
|
+
<button id="modal-filter-button" class="button">Filter</button>
|
50
|
+
</div>
|
51
|
+
{% endif %}
|
64
52
|
</div>
|
65
|
-
</div>
|
53
|
+
</div>
|
@@ -3,24 +3,20 @@
|
|
3
3
|
<button class="button"
|
4
4
|
hx-get="{{ previous_object_url }}{{ querystring }}"
|
5
5
|
hx-replace-url="true"
|
6
|
-
hx-select-oob="#content,#detail-pagination"
|
6
|
+
hx-select-oob="#content,#detail-pagination,#panel-actions"
|
7
7
|
><
|
8
8
|
</button>
|
9
9
|
|
10
10
|
</p>
|
11
|
-
|
12
|
-
<
|
13
|
-
<
|
14
|
-
</
|
15
|
-
|
16
|
-
<p class="control is-expanded">
|
17
|
-
<button class="button is-fullwidth px-1">{{ current_object_idx }} / {{ total_objects }}</button>
|
18
|
-
</p>
|
19
|
-
{% endif %}
|
11
|
+
<p class="control is-expanded">
|
12
|
+
<button class="button is-fullwidth px-1" style="white-space: normal">
|
13
|
+
<span class="{% if total_objects > 99999 %}is-size-7{% endif %}">{{ current_object_idx }} / {{ total_objects }}</span>
|
14
|
+
</button>
|
15
|
+
</p>
|
20
16
|
<p class="control">
|
21
17
|
<button class="button" hx-get="{{ next_object_url }}{{ querystring }}"
|
22
18
|
hx-replace-url="true"
|
23
|
-
hx-select-oob="#content,#detail-pagination"
|
19
|
+
hx-select-oob="#content,#detail-pagination,#panel-actions"
|
24
20
|
>>
|
25
21
|
</button>
|
26
22
|
</p>
|
@@ -4,25 +4,23 @@
|
|
4
4
|
<button class="button"
|
5
5
|
hx-get="{{ querystring }}&page={% if page.has_previous %}{{ page.previous_page_number }}{% else %}{{ paginator.num_pages }}{% endif %}"
|
6
6
|
hx-replace-url="true"
|
7
|
-
hx-select-oob="#content,#list-pagination"
|
7
|
+
hx-select-oob="#content,#list-pagination,#panel-actions"
|
8
8
|
>
|
9
9
|
<
|
10
10
|
</button>
|
11
11
|
</p>
|
12
12
|
<p class="control is-expanded">
|
13
|
-
|
14
|
-
<
|
15
|
-
|
16
|
-
</
|
17
|
-
|
18
|
-
<button class="button is-fullwidth">{{ page.start_index }}-{{ page.end_index }}/{{ paginator.count }}</button>
|
19
|
-
{% endif %}
|
13
|
+
<button class="button is-fullwidth px-1" style="white-space: normal">
|
14
|
+
<span class="{% if paginator.count > 9999 %}is-size-7{% endif %}">
|
15
|
+
{{ page.start_index }}-{{ page.end_index }} / {{ paginator.count }}
|
16
|
+
</span>
|
17
|
+
</button>
|
20
18
|
</p>
|
21
19
|
<p class="control">
|
22
20
|
<button class="button"
|
23
21
|
hx-get="{{ querystring }}&page={% if page.has_next %}{{ page.next_page_number }}{% else %}1{% endif %}"
|
24
22
|
hx-replace-url="true"
|
25
|
-
hx-select-oob="#content,#list-pagination"
|
23
|
+
hx-select-oob="#content,#list-pagination,#panel-actions"
|
26
24
|
>
|
27
25
|
>
|
28
26
|
</button>
|
@@ -1,6 +1,7 @@
|
|
1
1
|
{% extends 'ui/layout.html' %}
|
2
2
|
{% load static %}
|
3
3
|
{% load i18n %}
|
4
|
+
{% load accrete_ui %}
|
4
5
|
|
5
6
|
{% block script %}
|
6
7
|
{{ block.super }}
|
@@ -8,34 +9,32 @@
|
|
8
9
|
{% endblock %}
|
9
10
|
|
10
11
|
{% block content %}
|
11
|
-
<
|
12
|
-
<
|
13
|
-
{%
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
<div class="table-container">
|
20
|
-
<table class="table is-fullwidth is-hoverable">
|
21
|
-
<thead>
|
22
|
-
{% block table_header_row %}
|
23
|
-
<tr>
|
24
|
-
{% block table_header %}{% endblock %}
|
25
|
-
</tr>
|
26
|
-
{% endblock %}
|
27
|
-
</thead>
|
28
|
-
<tbody>
|
29
|
-
{% for obj in page %}
|
30
|
-
{% block table_data_row %}
|
31
|
-
<tr>
|
32
|
-
{% block table_data %}{% endblock %}
|
33
|
-
</tr>
|
34
|
-
{% endblock %}
|
12
|
+
<table class="table is-fullwidth is-hoverable">
|
13
|
+
<thead style="position: sticky; top: 0; background: white; z-index: 10">
|
14
|
+
{% block table_header_row %}
|
15
|
+
<tr>
|
16
|
+
{% block table_header %}
|
17
|
+
<th>{{ obj_label }}</th>
|
18
|
+
{% for field in fields %}
|
19
|
+
<th>{{ field.label }}</th>
|
35
20
|
{% endfor %}
|
36
|
-
|
37
|
-
</
|
38
|
-
|
39
|
-
</
|
40
|
-
|
21
|
+
{% endblock %}
|
22
|
+
</tr>
|
23
|
+
{% endblock %}
|
24
|
+
</thead>
|
25
|
+
<tbody style="z-index: 9">
|
26
|
+
{% for obj in page %}
|
27
|
+
{% block table_data_row %}
|
28
|
+
<tr>
|
29
|
+
{% block table_data %}
|
30
|
+
<td><a class="is-underlined" href="{{ obj.get_absolute_url }}{{ querystring }}&page={{ page.number }}">{{ obj }}</a></td>
|
31
|
+
{% for field in fields %}
|
32
|
+
<td>{{ obj|get_attr:field.name|default_if_none:'---' }}</td>
|
33
|
+
{% endfor %}
|
34
|
+
{% endblock %}
|
35
|
+
</tr>
|
36
|
+
{% endblock %}
|
37
|
+
{% endfor %}
|
38
|
+
</tbody>
|
39
|
+
</table>
|
41
40
|
{% endblock %}
|
@@ -1,8 +1,10 @@
|
|
1
|
+
import logging
|
1
2
|
from django import template
|
2
3
|
from django.conf import settings
|
3
4
|
from django.template.loader import render_to_string
|
4
5
|
from django.utils.safestring import mark_safe
|
5
6
|
|
7
|
+
_logger = logging.getLogger(__name__)
|
6
8
|
register = template.Library()
|
7
9
|
|
8
10
|
|
@@ -17,6 +19,19 @@ def combine_templates(template_name):
|
|
17
19
|
return mark_safe(html)
|
18
20
|
|
19
21
|
|
22
|
+
@register.filter(name='get_attr')
|
23
|
+
def get_attr_from_string(param, value):
|
24
|
+
try:
|
25
|
+
attr = getattr(param, value)
|
26
|
+
except AttributeError:
|
27
|
+
_logger.exception(f'Object {param} has no attribute {value}')
|
28
|
+
return ''
|
29
|
+
if callable(attr):
|
30
|
+
return attr()
|
31
|
+
else:
|
32
|
+
return attr
|
33
|
+
|
34
|
+
|
20
35
|
@register.filter(name='render_query_params')
|
21
36
|
def query_params_to_html(params):
|
22
37
|
html = ''
|
accrete/contrib/ui/views.py
CHANGED
@@ -32,17 +32,16 @@ accrete/contrib/system_mail/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2
|
|
32
32
|
accrete/contrib/system_mail/views.py,sha256=xc1IQHrsij7j33TUbo-_oewy3vs03pw_etpBWaMYJl0,63
|
33
33
|
accrete/contrib/system_mail/migrations/0001_initial.py,sha256=6cwkkRXGjXvwXoMjjgmWmcPyXSTlUbhW1vMiHObk9MQ,1074
|
34
34
|
accrete/contrib/system_mail/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
|
-
accrete/contrib/ui/__init__.py,sha256=
|
35
|
+
accrete/contrib/ui/__init__.py,sha256=b0Aq41co9EVKRKKrsRyhHQsUHCqtbaeI90slAxSLgK0,207
|
36
36
|
accrete/contrib/ui/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
|
37
37
|
accrete/contrib/ui/apps.py,sha256=E0ao2ox6PQ3ldfeR17FXJUUJuGiWjm2DPCxHbPXGzls,152
|
38
|
-
accrete/contrib/ui/config.py,sha256=X9cAYyJqIuE4bg5ja6N4WERHSu4HTkYEJpPvVZ4SwtA,206
|
39
38
|
accrete/contrib/ui/filter.py,sha256=xTziJ7ySfbpwtaWAusJSkNUtaZbEeX9UKES2AKIuAak,11897
|
40
|
-
accrete/contrib/ui/helper.py,sha256=
|
39
|
+
accrete/contrib/ui/helper.py,sha256=tQzUnBreoQcxv8t8a27Zmh6I7EewqmKZ7HzDO9gty0A,13235
|
41
40
|
accrete/contrib/ui/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
42
41
|
accrete/contrib/ui/urls.py,sha256=TUBlz_CGs9InTZoxM78GSnucA73I8knoh_obt12RUHM,186
|
43
|
-
accrete/contrib/ui/views.py,sha256=
|
42
|
+
accrete/contrib/ui/views.py,sha256=WpBKMsxFFG8eG4IN7TW_TPE6i3OFF7gnLDTK7JMKti8,191
|
44
43
|
accrete/contrib/ui/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
45
|
-
accrete/contrib/ui/static/css/accrete.css,sha256=
|
44
|
+
accrete/contrib/ui/static/css/accrete.css,sha256=nvU-3R0LJSclJMJ61pvQCRg1tWs07MpBRQIBNPPYBPg,2392
|
46
45
|
accrete/contrib/ui/static/css/icons.css,sha256=-a9BJHrH5P02cfL5qZLZHZkyupqigWmbc5wAa0UEDrE,3035
|
47
46
|
accrete/contrib/ui/static/icons/Logo.svg,sha256=hGZuxrAa-LRpFavFiF8Lnc7X9OQcqmb6Xl_dxx-27hM,1861
|
48
47
|
accrete/contrib/ui/static/icons/accrete.svg,sha256=CWHJKIgk3hxL7xIaFSz2j1cK-eF1TroCbjcF58bgOIs,1024
|
@@ -57,21 +56,20 @@ accrete/contrib/ui/templates/django/forms/widgets/input.html,sha256=CRu81kTsbPwi
|
|
57
56
|
accrete/contrib/ui/templates/django/forms/widgets/select.html,sha256=jT_UnHizHfdWTdJoSxjcIqTiR7NbVBA4bBSvkuDPRtw,394
|
58
57
|
accrete/contrib/ui/templates/django/forms/widgets/text.html,sha256=MSmLlQc7PsPoDLVtTOOiWNprrsPriNr712yFxaHyDIo,47
|
59
58
|
accrete/contrib/ui/templates/django/forms/widgets/textarea.html,sha256=c9BTedqb3IkXLyVYd0p9pR8DFnsXCNGoxVBWZTk_Fic,278
|
60
|
-
accrete/contrib/ui/templates/ui/detail.html,sha256=
|
61
|
-
accrete/contrib/ui/templates/ui/form.html,sha256=
|
62
|
-
accrete/contrib/ui/templates/ui/layout.html,sha256=
|
63
|
-
accrete/contrib/ui/templates/ui/list.html,sha256=
|
64
|
-
accrete/contrib/ui/templates/ui/table.html,sha256=
|
65
|
-
accrete/contrib/ui/templates/ui/partials/actions.html,sha256=urRu07sWxUBjdp9WgOpJnmf44ZHQDQXRae2QTdzV0lc,1342
|
59
|
+
accrete/contrib/ui/templates/ui/detail.html,sha256=m-CpLcoK-dL5jPlIY6Hzyq2EyEqcFZ5Bn-kB-T0Oqao,510
|
60
|
+
accrete/contrib/ui/templates/ui/form.html,sha256=HpcZCDU_ur_Zf5gpnH_F8OV6qfOYPl6Ecqg6w5RIayQ,405
|
61
|
+
accrete/contrib/ui/templates/ui/layout.html,sha256=aRC5-_co9EQiyGbtYFQ8mFDded7G-C2YnldAW4VOvQ8,7745
|
62
|
+
accrete/contrib/ui/templates/ui/list.html,sha256=HsmJAWDZU-qCPh4mrc8vGzkULbViG5fnLcmmp-NO2-4,671
|
63
|
+
accrete/contrib/ui/templates/ui/table.html,sha256=tbtccA6cbhF_ONis7Qm7S7_VK-rClddQl7fgxcO8VbU,1469
|
66
64
|
accrete/contrib/ui/templates/ui/partials/filter.html,sha256=l_Vi3ZRepF5lpX_KENU4AyIELSeichsVr0g2KGHcjIQ,1844
|
67
65
|
accrete/contrib/ui/templates/ui/partials/form_errors.html,sha256=1_TQvTdiejsn-43YSyp2YfnP52P-MFYb-HGY0DLm4oA,991
|
68
66
|
accrete/contrib/ui/templates/ui/partials/form_modal.html,sha256=FFDfI5qjOCUBSGqDjBXa8tcqN2q94wOOCNFDaiyplHQ,1032
|
69
|
-
accrete/contrib/ui/templates/ui/partials/header.html,sha256=
|
67
|
+
accrete/contrib/ui/templates/ui/partials/header.html,sha256=OhEINbE8ioFVEYZMFyqjfGTXCiFpse_gW6lvSL2amYk,2550
|
70
68
|
accrete/contrib/ui/templates/ui/partials/onchange_form.html,sha256=K5twTGqRUW1iM2dGtdWntjsJvJVo5EIzKxX2HK-H1yw,160
|
71
|
-
accrete/contrib/ui/templates/ui/partials/pagination_detail.html,sha256=
|
72
|
-
accrete/contrib/ui/templates/ui/partials/pagination_list.html,sha256=
|
69
|
+
accrete/contrib/ui/templates/ui/partials/pagination_detail.html,sha256=Mbqg8mOApBMnU-64lW-Z_H4v_PWd0UmuEiCWho5vUus,882
|
70
|
+
accrete/contrib/ui/templates/ui/partials/pagination_list.html,sha256=e4DOGaPa9fBrTFCwoW-UphNoJFlzrxFrU050bM1Cnbw,1146
|
73
71
|
accrete/contrib/ui/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
74
|
-
accrete/contrib/ui/templatetags/accrete_ui.py,sha256=
|
72
|
+
accrete/contrib/ui/templatetags/accrete_ui.py,sha256=otBEHrMM4JuYtx9DuK52OE1YM5vwS8KGs8CGevGwBpE,2478
|
75
73
|
accrete/contrib/user/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
76
74
|
accrete/contrib/user/admin.py,sha256=YS4iApli7XUaIl9GsEJxys2j8sepX0by88omYHjff-E,85
|
77
75
|
accrete/contrib/user/apps.py,sha256=oHDrAiHf-G57mZLyxqGJzRY2DbPprGFD-QgyVJG_ruI,156
|
@@ -103,7 +101,7 @@ accrete/migrations/0002_initial.py,sha256=dFOM7kdHlx7pVAh8cTDlZMtciN4O9Z547HAzEK
|
|
103
101
|
accrete/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
104
102
|
accrete/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
105
103
|
accrete/utils/dates.py,sha256=XI58CqabLCC-Sg6qo5TPWh-pHuuZfDdGDU6KQeAMlGo,1066
|
106
|
-
accrete-0.0.
|
107
|
-
accrete-0.0.
|
108
|
-
accrete-0.0.
|
109
|
-
accrete-0.0.
|
104
|
+
accrete-0.0.11.dist-info/METADATA,sha256=eAKqMGGLjjOGsbVzWBbIn9mS3ke6FEh7JsvTDIhaJEc,4846
|
105
|
+
accrete-0.0.11.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
|
106
|
+
accrete-0.0.11.dist-info/licenses/LICENSE,sha256=_7laeMIHnsd3Y2vJEXDYXq_PEXxIcjgJsGt8UIKTRWc,1057
|
107
|
+
accrete-0.0.11.dist-info/RECORD,,
|
accrete/contrib/ui/config.py
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
{% load i18n %}
|
2
|
-
|
3
|
-
{% for action in actions %}
|
4
|
-
{% if all or tablet and action.tablet or mobile and action.mobile %}
|
5
|
-
<div class="panel-block">
|
6
|
-
{% if action.template %}
|
7
|
-
{% include action.template %}
|
8
|
-
{% else %}
|
9
|
-
{% if action.submit %}
|
10
|
-
<input class="button is-fullwidth {{ action.class_list|join:' ' }}"
|
11
|
-
type="submit" form={{ action.form_id }} value="{{ action.name }}"
|
12
|
-
style="white-space: normal; height: auto"
|
13
|
-
{{ action.attrs|join:' ' }}>
|
14
|
-
{% else %}
|
15
|
-
<a class="button is-fullwidth {{ action.class|join:' ' }}"
|
16
|
-
href="{{ action.url }}{{ querystring|default_if_none:'?' }}{% if page %}&page={{ page.number }}{% endif %}{{ action.query_params }}"
|
17
|
-
{% for attr in action.attrs %}{{ attr }}{% endfor %}
|
18
|
-
style="word-break: break-word">{{ action.name }}
|
19
|
-
</a>
|
20
|
-
{% endif %}
|
21
|
-
{% endif %}
|
22
|
-
</div>
|
23
|
-
{% endif %}
|
24
|
-
{% endfor %}
|
25
|
-
|
26
|
-
{% if tablet and action_button.tablet or mobile and action_button.mobile %}
|
27
|
-
<div class="panel-block">
|
28
|
-
<button class="button panel-block action-modal-button">{% translate 'Actions' %}</button>
|
29
|
-
</div>
|
30
|
-
{% endif %}
|
File without changes
|
File without changes
|