accrete 0.0.143__py3-none-any.whl → 0.0.145__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/log/admin.py +1 -1
- accrete/contrib/system_mail/tasks.py +4 -5
- accrete/contrib/ui/__init__.py +15 -14
- accrete/contrib/ui/filter.py +22 -13
- accrete/contrib/ui/response.py +353 -0
- accrete/contrib/ui/static/css/accrete.css +69 -12
- accrete/contrib/ui/static/css/accrete.css.map +1 -1
- accrete/contrib/ui/static/css/accrete.scss +370 -300
- accrete/contrib/ui/templates/ui/content.html +0 -0
- accrete/contrib/ui/templates/ui/content_right.html +2 -2
- accrete/contrib/ui/templates/ui/detail.html +11 -0
- accrete/contrib/ui/templates/ui/filter/filter.html +5 -5
- accrete/contrib/ui/templates/ui/filter/query_tags.html +1 -1
- accrete/contrib/ui/templates/ui/layout.html +69 -64
- accrete/contrib/ui/templates/ui/list.html +21 -19
- accrete/contrib/ui/templates/ui/list_update.html +9 -3
- accrete/contrib/ui/templates/ui/message.html +1 -1
- accrete/contrib/ui/templates/ui/modal.html +41 -32
- accrete/contrib/ui/templates/ui/table_row_update.html +2 -2
- accrete/contrib/ui/templates/ui/templatetags/field.html +19 -6
- accrete/contrib/ui/templates/ui/widgets/model_search_select.html +7 -7
- accrete/contrib/ui/templates/ui/widgets/model_search_select_multi.html +3 -3
- accrete/contrib/ui/templatetags/ui.py +24 -2
- accrete/contrib/user/templates/user/password_forgotten.html +1 -0
- accrete/contrib/user/templates/user/user_preferences.html +43 -0
- accrete/contrib/user/views.py +36 -37
- accrete/migrations/0008_alter_member_access_groups_and_more.py +23 -0
- accrete/utils/__init__.py +1 -0
- accrete/utils/forms.py +11 -3
- accrete/utils/views.py +1 -2
- accrete/views.py +2 -3
- {accrete-0.0.143.dist-info → accrete-0.0.145.dist-info}/METADATA +2 -2
- {accrete-0.0.143.dist-info → accrete-0.0.145.dist-info}/RECORD +35 -33
- accrete/contrib/ui/context.py +0 -123
- accrete/contrib/ui/static/css/.sass-cache/15adf1eed05371361b08787c918a7f18fc15be79/accrete.scssc +0 -0
- accrete/contrib/ui/utils.py +0 -88
- accrete/contrib/user/templates/user/user_form.html +0 -58
- {accrete-0.0.143.dist-info → accrete-0.0.145.dist-info}/WHEEL +0 -0
- {accrete-0.0.143.dist-info → accrete-0.0.145.dist-info}/licenses/LICENSE +0 -0
accrete/contrib/log/admin.py
CHANGED
@@ -36,8 +36,7 @@ def run_mail_queue():
|
|
36
36
|
_logger.error(f'Failed to send system mail\n{error_str}')
|
37
37
|
email.error = error_str
|
38
38
|
email.save()
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
email.save()
|
39
|
+
else:
|
40
|
+
email.sent = True
|
41
|
+
email.error = None
|
42
|
+
email.save()
|
accrete/contrib/ui/__init__.py
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
from . import widgets
|
2
2
|
from .filter import Filter
|
3
|
-
from .
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
detail_response,
|
3
|
+
from .response import (
|
4
|
+
Response,
|
5
|
+
WindowResponse,
|
6
|
+
ListResponse,
|
7
|
+
ListEntryResponse,
|
8
|
+
TableResponse,
|
9
|
+
TableRowResponse,
|
10
|
+
DetailResponse,
|
11
|
+
ModalResponse,
|
12
|
+
OobResponse,
|
13
|
+
TriggerResponse,
|
14
|
+
ClientTrigger,
|
16
15
|
search_select_response,
|
17
|
-
|
16
|
+
message_response,
|
17
|
+
add_trigger,
|
18
|
+
update
|
18
19
|
)
|
accrete/contrib/ui/filter.py
CHANGED
@@ -46,12 +46,21 @@ class Filter:
|
|
46
46
|
TYPES_TIME = ['TimeField']
|
47
47
|
|
48
48
|
def __init__(
|
49
|
-
self,
|
49
|
+
self,
|
50
|
+
model,
|
51
|
+
query_dict: QueryDict,
|
52
|
+
default_lookup: str = None,
|
53
|
+
query: Q = None,
|
54
|
+
select_related: list[str] = None,
|
55
|
+
prefetch_related: list[str] = None
|
50
56
|
):
|
51
57
|
self.model = model
|
52
|
-
self.
|
58
|
+
self.query_dict = query_dict
|
53
59
|
self.model_name = f'{self.model._meta.app_label}.{self.model._meta.model_name}'
|
54
|
-
|
60
|
+
self.query = query or Q()
|
61
|
+
self.select_related = select_related
|
62
|
+
self.prefetch_related = prefetch_related
|
63
|
+
seen_models = query_dict.get('models', '').split(',')
|
55
64
|
self.seen_models = [
|
56
65
|
model for model in seen_models
|
57
66
|
if model and model != self.model_name
|
@@ -67,14 +76,14 @@ class Filter:
|
|
67
76
|
) -> paginator.Page:
|
68
77
|
return page_from_querystring(
|
69
78
|
self.model,
|
70
|
-
self.
|
71
|
-
select_related=select_related,
|
72
|
-
prefetch_related=prefetch_related,
|
73
|
-
query=query
|
79
|
+
self.query_dict,
|
80
|
+
select_related=select_related or self.select_related,
|
81
|
+
prefetch_related=prefetch_related or self.prefetch_related,
|
82
|
+
query=query or self.query
|
74
83
|
)
|
75
84
|
|
76
85
|
def get_queryset(self) -> QuerySet:
|
77
|
-
return filter_from_querystring(self.model, self.
|
86
|
+
return filter_from_querystring(self.model, self.query_dict)
|
78
87
|
|
79
88
|
def query_params(self):
|
80
89
|
fields = filter(
|
@@ -82,7 +91,7 @@ class Filter:
|
|
82
91
|
self.model._meta.get_fields()
|
83
92
|
)
|
84
93
|
params = []
|
85
|
-
path = self.
|
94
|
+
path = self.query_dict.get('path', '')
|
86
95
|
for field in fields:
|
87
96
|
field_params = self._get_field_params(field)
|
88
97
|
if not field.is_relation or field_params['model_name'] not in self.seen_models:
|
@@ -115,7 +124,7 @@ class Filter:
|
|
115
124
|
if not lookup:
|
116
125
|
ctx = {
|
117
126
|
'verbose_lookup': str(_('Select an attribute')),
|
118
|
-
'query_dict': self.
|
127
|
+
'query_dict': self.query_dict,
|
119
128
|
'model_name': self.model_name
|
120
129
|
}
|
121
130
|
return render_to_string('ui/filter/query_input.html', ctx)
|
@@ -133,14 +142,14 @@ class Filter:
|
|
133
142
|
'lookup': prefix + lookup,
|
134
143
|
'input': input_params,
|
135
144
|
'lookup_operator': lookup_operator,
|
136
|
-
'query_dict': self.
|
145
|
+
'query_dict': self.query_dict,
|
137
146
|
'model_name': self.model_name
|
138
147
|
}
|
139
148
|
return render_to_string('ui/filter/query_input.html', ctx)
|
140
149
|
|
141
150
|
def query_tags(self, query: list | dict = None, operator: str = None):
|
142
151
|
if not query:
|
143
|
-
query = json.loads(self.
|
152
|
+
query = json.loads(self.query_dict.get('q', '[]'))
|
144
153
|
if isinstance(query, dict):
|
145
154
|
query = [query]
|
146
155
|
operator = operator or '&'
|
@@ -291,7 +300,7 @@ class Filter:
|
|
291
300
|
return str(labels[lookup])
|
292
301
|
|
293
302
|
def _get_field_params(self, field):
|
294
|
-
path = self.
|
303
|
+
path = self.query_dict.get('path', '')
|
295
304
|
label = ''
|
296
305
|
name = field.name
|
297
306
|
if path:
|
@@ -0,0 +1,353 @@
|
|
1
|
+
import re
|
2
|
+
import ast
|
3
|
+
import json
|
4
|
+
from dataclasses import dataclass
|
5
|
+
|
6
|
+
from django.core import paginator
|
7
|
+
from django.db.models import Model
|
8
|
+
from django.http import HttpResponse
|
9
|
+
from django.template.loader import render_to_string
|
10
|
+
from django.utils.translation import gettext_lazy as _
|
11
|
+
from accrete.contrib.ui import Filter
|
12
|
+
|
13
|
+
|
14
|
+
class Response:
|
15
|
+
|
16
|
+
def __init__(self, *, template: str, context: dict):
|
17
|
+
self.template = template
|
18
|
+
self.context = context
|
19
|
+
|
20
|
+
@staticmethod
|
21
|
+
def add_trigger(response):
|
22
|
+
pass
|
23
|
+
|
24
|
+
def render(self, request) -> str:
|
25
|
+
return render_to_string(
|
26
|
+
template_name=self.template, context=self.context, request=request
|
27
|
+
)
|
28
|
+
|
29
|
+
def response(self, request, extra_content: str = None, replace_body: bool = False) -> HttpResponse:
|
30
|
+
extra_content = extra_content or ''
|
31
|
+
res = HttpResponse(content=(
|
32
|
+
self.render(request)
|
33
|
+
+ render_to_string('ui/message.html', request=request)
|
34
|
+
+ extra_content
|
35
|
+
))
|
36
|
+
self.add_trigger(res)
|
37
|
+
if replace_body:
|
38
|
+
res.headers['HX-Retarget'] = 'body'
|
39
|
+
res.headers['HX-Reswap'] = 'innerHTML'
|
40
|
+
res.headers['HX-Push-Url'] = request.path
|
41
|
+
return res
|
42
|
+
|
43
|
+
|
44
|
+
class OobResponse(Response):
|
45
|
+
|
46
|
+
oob_template = 'ui/oob.html'
|
47
|
+
|
48
|
+
def __init__(self, *, template: str, context: dict, swap: str, tag: str = 'div'):
|
49
|
+
super().__init__(template=self.oob_template, context=context)
|
50
|
+
self.context.update({'oob': {
|
51
|
+
'template': template,
|
52
|
+
'swap': swap,
|
53
|
+
'tag': tag
|
54
|
+
}})
|
55
|
+
|
56
|
+
|
57
|
+
class WindowResponse(Response):
|
58
|
+
|
59
|
+
base_template = 'ui/layout.html'
|
60
|
+
|
61
|
+
def __init__(
|
62
|
+
self, *,
|
63
|
+
title: str,
|
64
|
+
context: dict,
|
65
|
+
overview_template: str = None,
|
66
|
+
header_template: str = None,
|
67
|
+
panel_template: str = None,
|
68
|
+
is_centered: bool = False
|
69
|
+
):
|
70
|
+
super().__init__(template=self.base_template, context=context)
|
71
|
+
self.panel_template = panel_template
|
72
|
+
if 'has_panel' not in self.context.keys():
|
73
|
+
self.context.update(has_panel=self._has_panel())
|
74
|
+
self.context.update({
|
75
|
+
'title': title,
|
76
|
+
'overview_template': overview_template,
|
77
|
+
'header_template': header_template,
|
78
|
+
'panel_template': panel_template,
|
79
|
+
'is_centered': is_centered
|
80
|
+
})
|
81
|
+
|
82
|
+
def _has_panel(self):
|
83
|
+
return bool(self.panel_template)
|
84
|
+
|
85
|
+
def response(self, request, extra_content: str = None, replace_body: bool = True) -> HttpResponse:
|
86
|
+
return super().response(request, extra_content, replace_body)
|
87
|
+
|
88
|
+
|
89
|
+
class ListResponse(WindowResponse):
|
90
|
+
|
91
|
+
def __init__(
|
92
|
+
self, *,
|
93
|
+
title: str,
|
94
|
+
context: dict,
|
95
|
+
list_entry_template: str = None,
|
96
|
+
page: paginator.Page = None,
|
97
|
+
ui_filter: Filter = None,
|
98
|
+
endless_scroll: bool = True,
|
99
|
+
header_template: str = None,
|
100
|
+
panel_template: str = None,
|
101
|
+
column_count: int = 1,
|
102
|
+
column_height: str = '150px',
|
103
|
+
overview_template: str = 'ui/list.html'
|
104
|
+
):
|
105
|
+
assert page is not None or ui_filter is not None, _(
|
106
|
+
'Argument page or ui_filter must be supplied'
|
107
|
+
)
|
108
|
+
self.ui_filter = ui_filter
|
109
|
+
self.overview_template = overview_template
|
110
|
+
super().__init__(
|
111
|
+
title=title,
|
112
|
+
context=context,
|
113
|
+
overview_template=self.overview_template,
|
114
|
+
header_template=header_template,
|
115
|
+
panel_template=panel_template,
|
116
|
+
)
|
117
|
+
if ui_filter and not page:
|
118
|
+
page = ui_filter.get_page()
|
119
|
+
self.context.update({
|
120
|
+
'list_entry_template': list_entry_template,
|
121
|
+
'page': page,
|
122
|
+
'ui_filter': ui_filter,
|
123
|
+
'endless_scroll': endless_scroll,
|
124
|
+
'column_count': column_count,
|
125
|
+
'column_height': column_height
|
126
|
+
})
|
127
|
+
|
128
|
+
def _has_panel(self):
|
129
|
+
return bool(self.panel_template or self.ui_filter)
|
130
|
+
|
131
|
+
def response(self, request, extra_content: str = None, replace_body: bool = False) -> HttpResponse:
|
132
|
+
return super().response(request, extra_content, replace_body)
|
133
|
+
|
134
|
+
|
135
|
+
class ListEntryResponse(Response):
|
136
|
+
|
137
|
+
base_template = 'ui/list_update.html'
|
138
|
+
|
139
|
+
def __init__(
|
140
|
+
self, *,
|
141
|
+
instance: Model,
|
142
|
+
list_entry_template: str,
|
143
|
+
context: dict = None,
|
144
|
+
page: paginator.Page,
|
145
|
+
is_new: bool,
|
146
|
+
column_count: int = 1,
|
147
|
+
column_height: str = '150px',
|
148
|
+
):
|
149
|
+
self.page = page
|
150
|
+
super().__init__(template=self.base_template, context=context or {})
|
151
|
+
self.context.update({
|
152
|
+
'instance': instance,
|
153
|
+
'list_entry_template': list_entry_template,
|
154
|
+
'is_new': is_new,
|
155
|
+
'column_count': column_count,
|
156
|
+
'column_height': column_height
|
157
|
+
})
|
158
|
+
|
159
|
+
def render(self, request) -> str:
|
160
|
+
res = super().render(request)
|
161
|
+
if self.page:
|
162
|
+
pagination_update = OobResponse(
|
163
|
+
template='ui/layout.html#pagination',
|
164
|
+
swap='innerHTML:#pagination',
|
165
|
+
context=dict(page=self.page)
|
166
|
+
).render(request)
|
167
|
+
res += pagination_update
|
168
|
+
return res
|
169
|
+
|
170
|
+
|
171
|
+
class TableResponse(WindowResponse):
|
172
|
+
|
173
|
+
def __init__(
|
174
|
+
self, *,
|
175
|
+
title: str,
|
176
|
+
context: dict,
|
177
|
+
object_label: str,
|
178
|
+
fields: list[str],
|
179
|
+
footer: dict = None,
|
180
|
+
page: paginator.Page = None,
|
181
|
+
ui_filter: Filter = None,
|
182
|
+
endless_scroll: bool = True,
|
183
|
+
header_template: str = None,
|
184
|
+
panel_template: str = None,
|
185
|
+
overview_template: str = 'ui/table.html'
|
186
|
+
):
|
187
|
+
assert page is not None or ui_filter is not None, _(
|
188
|
+
'Argument page or ui_filter must be supplied'
|
189
|
+
)
|
190
|
+
self.ui_filter = ui_filter
|
191
|
+
self.overview_template = overview_template
|
192
|
+
super().__init__(
|
193
|
+
title=title,
|
194
|
+
context=context,
|
195
|
+
overview_template=self.overview_template,
|
196
|
+
header_template=header_template,
|
197
|
+
panel_template=panel_template
|
198
|
+
)
|
199
|
+
if ui_filter and not page:
|
200
|
+
page = ui_filter.get_page()
|
201
|
+
self.context.update({
|
202
|
+
'page': page,
|
203
|
+
'ui_filter': ui_filter,
|
204
|
+
'endless_scroll': endless_scroll,
|
205
|
+
'fields': fields,
|
206
|
+
'object_label': object_label,
|
207
|
+
'footer': footer
|
208
|
+
})
|
209
|
+
|
210
|
+
def _has_panel(self):
|
211
|
+
return bool(self.panel_template or self.ui_filter)
|
212
|
+
|
213
|
+
def response(self, request, extra_content: str = None, replace_body: bool = False) -> HttpResponse:
|
214
|
+
return super().response(request, extra_content, replace_body)
|
215
|
+
|
216
|
+
|
217
|
+
class TableRowResponse(Response):
|
218
|
+
|
219
|
+
base_template = 'ui/table_row_update.html'
|
220
|
+
|
221
|
+
def __init__(
|
222
|
+
self, *,
|
223
|
+
instance: Model,
|
224
|
+
fields: list[str],
|
225
|
+
footer: dict = None,
|
226
|
+
page: paginator.Page = None,
|
227
|
+
):
|
228
|
+
self.page = page
|
229
|
+
context = {
|
230
|
+
'instance': instance,
|
231
|
+
'fields': fields,
|
232
|
+
'footer': footer,
|
233
|
+
}
|
234
|
+
super().__init__(template=self.base_template, context=context)
|
235
|
+
|
236
|
+
def render(self, request) -> str:
|
237
|
+
res = super().render(request)
|
238
|
+
if self.page:
|
239
|
+
pagination_update = OobResponse(
|
240
|
+
template='ui/layout.html#pagination',
|
241
|
+
swap='innerHTML:#pagination',
|
242
|
+
context=dict(page=self.page)
|
243
|
+
).render(request)
|
244
|
+
res += pagination_update
|
245
|
+
return res
|
246
|
+
|
247
|
+
|
248
|
+
class DetailResponse(Response):
|
249
|
+
|
250
|
+
base_template = 'ui/detail.html'
|
251
|
+
|
252
|
+
def __init__(
|
253
|
+
self, *,
|
254
|
+
context: dict,
|
255
|
+
detail_header_template: str = None,
|
256
|
+
detail_data_template: str = None
|
257
|
+
):
|
258
|
+
super().__init__(template=self.base_template, context=context)
|
259
|
+
self.context.update({
|
260
|
+
'detail_header_template': detail_header_template,
|
261
|
+
'detail_data_template': detail_data_template
|
262
|
+
})
|
263
|
+
|
264
|
+
@staticmethod
|
265
|
+
def add_trigger(response):
|
266
|
+
add_trigger(response, 'activate-detail')
|
267
|
+
|
268
|
+
|
269
|
+
class ModalResponse(Response):
|
270
|
+
|
271
|
+
def __init__(
|
272
|
+
self, *,
|
273
|
+
modal_id: str,
|
274
|
+
template: str,
|
275
|
+
context: dict,
|
276
|
+
title: str = None,
|
277
|
+
is_update: bool = False,
|
278
|
+
is_blocking: bool = False,
|
279
|
+
modal_width: str = None
|
280
|
+
|
281
|
+
):
|
282
|
+
super().__init__(template=template, context=context)
|
283
|
+
self.context.update({
|
284
|
+
'title': title,
|
285
|
+
'modal_id': re.sub(r'[^A-Za-z-]+', '', modal_id).strip('-'),
|
286
|
+
'is_update': is_update,
|
287
|
+
'is_blocking': is_blocking,
|
288
|
+
'modal_width': modal_width
|
289
|
+
})
|
290
|
+
|
291
|
+
|
292
|
+
@dataclass
|
293
|
+
class ClientTrigger:
|
294
|
+
|
295
|
+
trigger: dict | str
|
296
|
+
header: str = 'HX-Trigger'
|
297
|
+
|
298
|
+
|
299
|
+
class TriggerResponse:
|
300
|
+
|
301
|
+
def __init__(self, trigger: list[ClientTrigger]):
|
302
|
+
self.trigger = trigger
|
303
|
+
|
304
|
+
def response(self):
|
305
|
+
res = HttpResponse()
|
306
|
+
res.headers['HX-Reswap'] = 'None'
|
307
|
+
for trigger in self.trigger:
|
308
|
+
add_trigger(res, trigger.trigger, trigger.header)
|
309
|
+
return res
|
310
|
+
|
311
|
+
|
312
|
+
def search_select_response(queryset) -> HttpResponse:
|
313
|
+
return HttpResponse(render_to_string(
|
314
|
+
'ui/widgets/model_search_select_options.html',
|
315
|
+
{'options': queryset}
|
316
|
+
))
|
317
|
+
|
318
|
+
|
319
|
+
def message_response(request, persistent: bool = False):
|
320
|
+
return HttpResponse(content=(render_to_string(
|
321
|
+
'ui/message.html', context={'persistent': persistent}, request=request
|
322
|
+
)))
|
323
|
+
|
324
|
+
|
325
|
+
def add_trigger(
|
326
|
+
response: HttpResponse,
|
327
|
+
trigger: dict | str,
|
328
|
+
header: str = 'HX-Trigger'
|
329
|
+
) -> HttpResponse:
|
330
|
+
if isinstance(trigger, str):
|
331
|
+
trigger = {trigger: ''}
|
332
|
+
res_trigger = response.headers.get(header)
|
333
|
+
if not res_trigger:
|
334
|
+
response.headers[header] = json.dumps(trigger)
|
335
|
+
return response
|
336
|
+
try:
|
337
|
+
res_trigger = ast.literal_eval(response.headers.get(header, '{}'))
|
338
|
+
except SyntaxError:
|
339
|
+
res_trigger = {response.headers[header]: ''}
|
340
|
+
res_trigger.update(trigger)
|
341
|
+
response.headers[header] = json.dumps(res_trigger)
|
342
|
+
return response
|
343
|
+
|
344
|
+
|
345
|
+
def update(request, ui_responses: list[Response]) -> HttpResponse:
|
346
|
+
response = HttpResponse()
|
347
|
+
content = ''
|
348
|
+
for res in ui_responses:
|
349
|
+
content += res.render(request)
|
350
|
+
res.add_trigger(response)
|
351
|
+
content += render_to_string('ui/message.html', request=request)
|
352
|
+
response.content = content
|
353
|
+
return response
|
@@ -3,11 +3,12 @@
|
|
3
3
|
--bulma-body-size: .9em;
|
4
4
|
--bulma-navbar-height: 40px;
|
5
5
|
--bulma-menu-item-selected-h: --bulma-success-h;
|
6
|
-
--accrete-
|
6
|
+
--accrete-detail-width: 500px;
|
7
7
|
--accrete-action-panel-width: 320px;
|
8
8
|
--bulma-input-icon-focus-color: var(--bulma-success);
|
9
9
|
--bulma-input-arrow: var(--bulma-success);
|
10
10
|
--bulma-arrow-color: var(--bulma-success);
|
11
|
+
--bulma-menu-nested-list-margin: .5em 0 0.5em 0.75em;
|
11
12
|
--bulma-navbar-burger-color: var(--bulma-success);
|
12
13
|
--accrete-hover-color: #F0F2F4; }
|
13
14
|
|
@@ -18,10 +19,12 @@ html[data-theme='light'] {
|
|
18
19
|
--bulma-menu-item-background-l: 50%;
|
19
20
|
--bulma-menu-item-color-l: 10%;
|
20
21
|
--bulma-navbar-burger-color: var(--bulma-success);
|
22
|
+
--bulma-input-disabled-border-color: var(--bulma-input-border-color) !important;
|
21
23
|
--accrete-hover-color: #F0F2F4; }
|
22
24
|
|
23
25
|
html[data-theme='dark'] {
|
24
26
|
--bulma-navbar-burger-color: var(--bulma-success);
|
27
|
+
--bulma-input-disabled-border-color: var(--bulma-input-border-color) !important;
|
25
28
|
--accrete-hover-color: #1E2128; }
|
26
29
|
html[data-theme='dark'] .button.is-light {
|
27
30
|
--bulma-button-h: var(--bulma-dark-h);
|
@@ -45,12 +48,18 @@ a {
|
|
45
48
|
color: inherit;
|
46
49
|
text-decoration: inherit; }
|
47
50
|
|
51
|
+
.label {
|
52
|
+
font-weight: normal; }
|
53
|
+
|
48
54
|
.navbar-burger {
|
49
55
|
color: black; }
|
50
56
|
|
51
57
|
.button.is-subtle {
|
52
58
|
box-shadow: none;
|
53
|
-
border:
|
59
|
+
border-top-color: transparent;
|
60
|
+
border-right-color: transparent;
|
61
|
+
border-bottom-color: transparent;
|
62
|
+
border-left-color: transparent; }
|
54
63
|
|
55
64
|
.input {
|
56
65
|
border-top: none;
|
@@ -60,12 +69,20 @@ a {
|
|
60
69
|
border-top-right-radius: 0;
|
61
70
|
border-bottom-right-radius: 0;
|
62
71
|
border-bottom-left-radius: 0;
|
63
|
-
box-shadow: none;
|
72
|
+
box-shadow: none;
|
73
|
+
font-weight: bold; }
|
64
74
|
|
65
75
|
.input:focus, .input:focus-within {
|
66
76
|
box-shadow: none;
|
67
77
|
border-bottom: 1px solid var(--bulma-success); }
|
68
78
|
|
79
|
+
input[disabled] {
|
80
|
+
background-color: transparent !important;
|
81
|
+
cursor: unset !important; }
|
82
|
+
|
83
|
+
input[disabled] ~ .helptext {
|
84
|
+
font-weight: normal !important; }
|
85
|
+
|
69
86
|
textarea {
|
70
87
|
border-top: transparent !important;
|
71
88
|
border-right: transparent !important;
|
@@ -94,15 +111,16 @@ select {
|
|
94
111
|
border-right: transparent !important;
|
95
112
|
border-left: transparent !important;
|
96
113
|
border-radius: 0 !important;
|
97
|
-
box-shadow: none !important;
|
114
|
+
box-shadow: none !important;
|
115
|
+
font-weight: bold; }
|
98
116
|
|
99
117
|
select:focus {
|
100
118
|
box-shadow: none;
|
101
119
|
border-bottom: 1px solid var(--bulma-success) !important; }
|
102
120
|
|
103
|
-
#
|
121
|
+
#detail-container {
|
104
122
|
flex-shrink: 0;
|
105
|
-
width: var(--accrete-
|
123
|
+
width: var(--accrete-detail-width);
|
106
124
|
border-top-left-radius: var(--bulma-radius-medium);
|
107
125
|
border-bottom-left-radius: var(--bulma-radius-medium);
|
108
126
|
box-shadow: -2px 0 20px 0 var(--bulma-grey-light);
|
@@ -111,8 +129,8 @@ select:focus {
|
|
111
129
|
.responsive-heading {
|
112
130
|
display: none; }
|
113
131
|
|
114
|
-
#
|
115
|
-
container-name:
|
132
|
+
#overview-container {
|
133
|
+
container-name: overview-container;
|
116
134
|
container-type: inline-size; }
|
117
135
|
|
118
136
|
.htmx-indicator {
|
@@ -124,6 +142,24 @@ select:focus {
|
|
124
142
|
.modal-request-overlay.htmx-request {
|
125
143
|
pointer-events: auto; }
|
126
144
|
|
145
|
+
#detail-indicator {
|
146
|
+
position: fixed;
|
147
|
+
background: rgba(47, 47, 62, 0.2);
|
148
|
+
height: 100%;
|
149
|
+
width: 100%;
|
150
|
+
z-index: -100; }
|
151
|
+
|
152
|
+
#detail-indicator.htmx-request {
|
153
|
+
z-index: 999;
|
154
|
+
transition-delay: 300ms;
|
155
|
+
transition-property: opacity; }
|
156
|
+
|
157
|
+
#detail-indicator > .progress {
|
158
|
+
position: fixed;
|
159
|
+
top: 50%;
|
160
|
+
margin-left: 3%;
|
161
|
+
max-width: calc(var(--accrete-detail-width) - 6%); }
|
162
|
+
|
127
163
|
.list-entry > .box:hover, .box.selected {
|
128
164
|
outline: 2px solid var(--bulma-success); }
|
129
165
|
|
@@ -135,7 +171,11 @@ select:focus {
|
|
135
171
|
font-weight: var(--bulma-weight-normal);
|
136
172
|
line-height: 1.25; }
|
137
173
|
|
138
|
-
|
174
|
+
.container {
|
175
|
+
padding-left: 0.5rem;
|
176
|
+
padding-right: 0.5rem; }
|
177
|
+
|
178
|
+
@container overview-container (max-width: 768px) {
|
139
179
|
table.can-compact * td {
|
140
180
|
width: 100%;
|
141
181
|
float: left;
|
@@ -168,8 +208,11 @@ select:focus {
|
|
168
208
|
|
169
209
|
.list-entry {
|
170
210
|
height: fit-content !important; } }
|
211
|
+
@media screen and (min-width: 769px) {
|
212
|
+
.modal-card {
|
213
|
+
max-width: 100%; } }
|
171
214
|
@media screen and (max-width: 768px) {
|
172
|
-
#
|
215
|
+
#detail-container {
|
173
216
|
flex-grow: 1;
|
174
217
|
flex-shrink: 1;
|
175
218
|
width: auto;
|
@@ -177,7 +220,16 @@ select:focus {
|
|
177
220
|
border-bottom-left-radius: 0; }
|
178
221
|
|
179
222
|
.level > .level-item.box {
|
180
|
-
width: 100%; }
|
223
|
+
width: 100%; }
|
224
|
+
|
225
|
+
.modal {
|
226
|
+
padding-top: 0 !important;
|
227
|
+
padding-bottom: 0 !important;
|
228
|
+
justify-content: center !important; }
|
229
|
+
|
230
|
+
.modal-card {
|
231
|
+
width: 100% !important;
|
232
|
+
max-height: 100svh; } }
|
181
233
|
#action-panel {
|
182
234
|
max-width: var(--accrete-action-panel-width);
|
183
235
|
min-width: var(--accrete-action-panel-width);
|
@@ -188,7 +240,7 @@ select:focus {
|
|
188
240
|
#action-panel {
|
189
241
|
position: absolute;
|
190
242
|
background: var(--bulma-scheme-main);
|
191
|
-
z-index:
|
243
|
+
z-index: 40;
|
192
244
|
box-shadow: 2px 0 20px 0 var(--bulma-grey-light); } }
|
193
245
|
.menu-list a.is-active, .menu-list a.is-selected, .menu-list button.is-active, .menu-list button.is-selected, .menu-list .menu-item.is-active, .menu-list .menu-item.is-selected {
|
194
246
|
--bulma-menu-item-h: var(--bulma-success-h);
|
@@ -235,4 +287,9 @@ input[type=number] {
|
|
235
287
|
padding-left: 0;
|
236
288
|
border-left: none !important; }
|
237
289
|
|
290
|
+
.header-items > * {
|
291
|
+
margin-right: 0.4rem;
|
292
|
+
margin-bottom: 0.5rem;
|
293
|
+
margin-left: 0.4rem; }
|
294
|
+
|
238
295
|
/*# sourceMappingURL=accrete.css.map */
|