accrete 0.0.141__py3-none-any.whl → 0.0.143__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 +6 -1
- accrete/contrib/ui/context.py +0 -2
- accrete/contrib/ui/static/css/.sass-cache/15adf1eed05371361b08787c918a7f18fc15be79/accrete.scssc +0 -0
- accrete/contrib/ui/static/css/accrete.css.map +1 -1
- accrete/contrib/ui/static/css/accrete.scss +1 -0
- accrete/contrib/ui/templates/ui/favicon.html +2 -0
- accrete/contrib/ui/templates/ui/form_error.html +1 -1
- accrete/contrib/ui/templates/ui/layout.html +5 -5
- accrete/contrib/ui/templates/ui/list.html +5 -5
- accrete/contrib/ui/templates/ui/message.html +1 -1
- accrete/contrib/ui/templates/ui/modal.html +1 -0
- accrete/contrib/ui/templates/ui/table.html +5 -5
- accrete/contrib/ui/templates/ui/templatetags/field.html +2 -2
- accrete/contrib/ui/templates/ui/widgets/model_search_select_multi.html +3 -3
- accrete/contrib/ui/utils.py +47 -3
- accrete/contrib/ui/widgets/search_select.py +5 -3
- accrete/utils/forms.py +39 -27
- {accrete-0.0.141.dist-info → accrete-0.0.143.dist-info}/METADATA +1 -1
- {accrete-0.0.141.dist-info → accrete-0.0.143.dist-info}/RECORD +21 -20
- {accrete-0.0.141.dist-info → accrete-0.0.143.dist-info}/WHEEL +0 -0
- {accrete-0.0.141.dist-info → accrete-0.0.143.dist-info}/licenses/LICENSE +0 -0
accrete/contrib/ui/__init__.py
CHANGED
accrete/contrib/ui/context.py
CHANGED
@@ -36,7 +36,6 @@ class ListContext(Context):
|
|
36
36
|
page: paginator.Page
|
37
37
|
queryset: QuerySet
|
38
38
|
endless_scroll: bool = True
|
39
|
-
detail_enabled: bool = True
|
40
39
|
filter: Filter = None
|
41
40
|
column_count: int = 1
|
42
41
|
column_height: int = 150
|
@@ -66,7 +65,6 @@ class TableContext(Context):
|
|
66
65
|
queryset: QuerySet
|
67
66
|
footer: dict = field(default_factory=dict)
|
68
67
|
endless_scroll: bool = True
|
69
|
-
detail_enabled: bool = True
|
70
68
|
filter: Filter = None
|
71
69
|
|
72
70
|
|
accrete/contrib/ui/static/css/.sass-cache/15adf1eed05371361b08787c918a7f18fc15be79/accrete.scssc
CHANGED
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
|
-
"mappings": "AAAQ,mCAAwB;AAEhC,KAAM;EACJ,iBAAiB,CAAC,KAAK;EACvB,qBAAqB,CAAC,KAAK;EAC3B,4BAA4B,CAAC,kBAAkB;EAC/C,6BAA6B,CAAC,MAAM;EACpC,4BAA4B,CAAC,MAAM;EACnC,8BAA8B,CAAC,qBAAqB;EACpD,mBAAmB,CAAC,qBAAqB;EACzC,mBAAmB,CAAC,qBAAqB;EACzC,2BAA2B,CAAC,qBAAqB;EACjD,qBAAqB,CAAC,QAAQ;;AAIhC,wBAAyB;EACvB,mBAAmB,CAAC,uBAAuB;EAC3C,mBAAmB,CAAC,uBAAuB;EAC3C,mBAAmB,CAAC,uBAAuB;EAC3C,8BAA8B,CAAC,IAAI;EACnC,yBAAyB,CAAC,IAAI;EAC9B,2BAA2B,CAAC,qBAAqB;EACjD,qBAAqB,CAAC,QAAQ;;AAGhC,uBAAwB;EACtB,2BAA2B,CAAC,qBAAqB;EACjD,qBAAqB,CAAC,QAAQ;EAE9B,wCAAiB;IACf,gBAAgB,CAAC,oBAAoB;IACrC,gBAAgB,CAAC,oBAAoB;IACrC,gBAAgB,CAAC,oBAAoB;IACrC,2BAA2B,CAAC,oBAAoB;IAChD,uBAAuB,CAAC,oBAAoB;IAC5C,2BAA2B,CAAC,IAAI;IAChC,sBAAsB,CAAC,2BAA2B;IAClD,6BAA6B,CAAC,EAAE;EAGlC,kDAA2B;IACzB,2BAA2B,CAAC,oBAAoB;IAChD,sBAAsB,CAAC,kCAAkC;EAG3D,+CAAwB;IACtB,2BAA2B,CAAC,0BAA0B;;AAI1D,SAAU;EACR,OAAO,EAAE,eAAe;;AAG1B,CAAE;EACA,KAAK,EAAE,OAAO;EACd,eAAe,EAAE,OAAO;;AAI1B,cAAe;EACb,KAAK,EAAE,KAAK;;AAGd,iBAAkB;EAChB,UAAU,EAAE,IAAI;EAChB,MAAM,EAAE,IAAI;;AAGd,MAAO;EACL,UAAU,EAAE,IAAI;EAChB,YAAY,EAAE,IAAI;EAClB,WAAW,EAAE,IAAI;EACjB,sBAAsB,EAAE,CAAC;EACzB,uBAAuB,EAAE,CAAC;EAC1B,0BAA0B,EAAE,CAAC;EAC7B,yBAAyB,EAAE,CAAC;EAC5B,UAAU,EAAE,IAAI;;AAGlB,iCAAkC;EAChC,UAAU,EAAE,IAAI;EAChB,aAAa,EAAE,8BAA8B;;
|
3
|
+
"mappings": "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",
|
4
4
|
"sources": ["accrete.scss"],
|
5
5
|
"names": [],
|
6
6
|
"file": "accrete.css"
|
@@ -5,7 +5,7 @@
|
|
5
5
|
{{ form.non_field_errors }}
|
6
6
|
{% if form.save_error %}
|
7
7
|
<p>{{ form.save_error }}</p>
|
8
|
-
<span>{% translate 'Error ID' %}: {{ form.save_error_id }}</span>
|
8
|
+
{% if form.save_error_id %}<span>{% translate 'Error ID' %}: {{ form.save_error_id }}</span>{% endif %}
|
9
9
|
{% endif %}
|
10
10
|
</div>
|
11
11
|
{% endif %}
|
@@ -10,8 +10,8 @@
|
|
10
10
|
{% block head %}
|
11
11
|
<meta charset="utf-8">
|
12
12
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
13
|
-
{%
|
14
|
-
<link rel="stylesheet" type="text/css" href="{% static "css/accrete.css" %}?v=
|
13
|
+
{% include 'ui/favicon.html' %}
|
14
|
+
<link rel="stylesheet" type="text/css" href="{% static "css/accrete.css" %}?v=4">
|
15
15
|
<link rel="stylesheet" type="text/css" href="{% static "css/icons.css" %}">
|
16
16
|
<link rel="stylesheet" type="text/css" href="{% static "css/fa.css" %}">
|
17
17
|
|
@@ -150,7 +150,7 @@
|
|
150
150
|
<div class="mr-1">
|
151
151
|
<p class="title is-5 px-2 py-1 my-1">{{ title }}</p>
|
152
152
|
</div>
|
153
|
-
<div class="buttons mx-2">
|
153
|
+
<div id="content-left-buttons" class="buttons mx-2">
|
154
154
|
{% block header_left_buttons %}{% endblock %}
|
155
155
|
</div>
|
156
156
|
{% endblock %}
|
@@ -162,7 +162,7 @@
|
|
162
162
|
<button id="pagination-prev-button" class="button"
|
163
163
|
hx-get="{% if page.has_previous %}{% querystring page=page.previous_page_number %}{% else %}{% querystring page=page.paginator.num_pages %}{% endif %}"
|
164
164
|
hx-replace-url="true"
|
165
|
-
hx-select-oob="#content-left,#pagination"
|
165
|
+
hx-select-oob="#content-left,#pagination,#content-left-buttons"
|
166
166
|
>
|
167
167
|
<
|
168
168
|
</button>
|
@@ -180,7 +180,7 @@
|
|
180
180
|
<button id="pagination-next-button" class="button"
|
181
181
|
hx-get="{% if page.has_next %}{% querystring page=page.next_page_number %}{% else %}{% querystring page=1 %}{% endif %}"
|
182
182
|
hx-replace-url="true"
|
183
|
-
hx-select-oob="#content-left,#pagination"
|
183
|
+
hx-select-oob="#content-left,#pagination,#content-left-buttons"
|
184
184
|
>
|
185
185
|
>
|
186
186
|
</button>
|
@@ -4,17 +4,16 @@
|
|
4
4
|
{% load partials %}
|
5
5
|
|
6
6
|
{% block content_left %}
|
7
|
+
{% partialdef content inline=True %}
|
7
8
|
<div class="fixed-grid has-{{ column_count }}-cols has-1-cols-mobile m-2">
|
8
9
|
<div id="list-grid" class="grid m-0">
|
9
10
|
{% for object in page.object_list %}
|
10
11
|
<div id="list-entry-{{ object.pk }}" class="list-entry cell pb-0" style="height: {{ column_height }}{{ column_height_unit }}">
|
11
12
|
<div class="box p-3"
|
12
13
|
style="word-break: break-word; height: 100%; overflow-y: auto; {% if object.get_absolute_url %}cursor:pointer;{% endif %}"
|
13
|
-
{% if object.get_absolute_url
|
14
|
-
hx-get="{{ object.get_absolute_url }}{% querystring %}" hx-
|
15
|
-
x-on:click="$dispatch('unselect-list-entry');
|
16
|
-
{% elif object.get_absolute_url and not detail_enabled %}
|
17
|
-
hx-get="{{ object.get_absolute_url }}{% querystring %}" hx-target="body" hx-push-url="true"
|
14
|
+
{% if object.get_absolute_url %}
|
15
|
+
hx-get="{{ object.get_absolute_url }}{% querystring %}" hx-swap="none"
|
16
|
+
x-on:click="$dispatch('unselect-list-entry'); selected = true; $nextTick(() => { $el.scrollIntoView( {block: 'nearest'} ) });" x-bind:class="selected ? 'box selected' : ''"
|
18
17
|
{% endif %}
|
19
18
|
x-data="{selected: false}" @unselect-list-entry.window="selected = false"
|
20
19
|
>
|
@@ -40,4 +39,5 @@
|
|
40
39
|
<progress id="endless-scroll-indicator" class="htmx-indicator progress is-small is-success" max="100">15%</progress>
|
41
40
|
{% endif %}
|
42
41
|
</div>
|
42
|
+
{% endpartialdef %}
|
43
43
|
{% endblock %}
|
@@ -4,7 +4,7 @@
|
|
4
4
|
{% for message in messages %}
|
5
5
|
<div hx-swap-oob="{% if append %}beforeend:#message{% else %}innerHTML:#message{% endif %}">
|
6
6
|
<div class="mb-2" style="min-width: 340px; max-width: 340px" x-data="{ show: false }" x-show="show" x-cloak="" x-init="show = true; {% if not persistent %}setTimeout(() => show = false, 4000){% endif %}" x-transition.duration.200ms>
|
7
|
-
<div class="notification has-text-centered {{ message|message_class }}">
|
7
|
+
<div class="notification has-text-centered {{ message|message_class }}" style="box-shadow: 2px 2px 5px">
|
8
8
|
{% if persistent %}<button class="delete" x-on:click="show = false;"></button>{% endif %}
|
9
9
|
{{ message }}
|
10
10
|
</div>
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
<div id="{{ modal_id }}" x-data="{showModal: false, close() {$dispatch('close-modal-{{ modal_id }}')} }" x-ref="modal" class="modal is-active"
|
5
5
|
@close-modal-{{ modal_id }}.window="showModal = false; setTimeout(() => $refs.modal.remove(), 200);"
|
6
|
+
@close-modals.window="showModal = false; setTimeout(() => $refs.modal.remove(), 200);"
|
6
7
|
@keyup.escape.window="if (! $refs.{{ modal_id|xrefsave }}Indicator.classList.contains('htmx-request')) {$dispatch('close-modal-{{ modal_id }}')}"
|
7
8
|
{% if blocking %}
|
8
9
|
hx-indicator="#{{ modal_id }}-indicator"
|
@@ -17,11 +17,11 @@
|
|
17
17
|
{% for object in page.object_list %}
|
18
18
|
{% partialdef tr inline=True %}
|
19
19
|
<tr id="tr-{{ object.pk }}"
|
20
|
-
{% if
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
{% if object.get_absolute_url %}
|
21
|
+
style="cursor: pointer;"
|
22
|
+
hx-get="{{ object.get_absolute_url }}{% querystring %}" hx-swap="none"
|
23
|
+
x-data="{selected: false}" @unselect-tr.window="selected = false"
|
24
|
+
x-on:click="$dispatch('unselect-tr'); selected = true; $nextTick(() => { $el.scrollIntoView( {block: 'nearest'} ) });" x-bind:class="selected ? 'is-success' : ''"
|
25
25
|
{% endif %}
|
26
26
|
>
|
27
27
|
{% partialdef td inline=True %}
|
@@ -1,6 +1,6 @@
|
|
1
|
-
<label class="label mb-
|
1
|
+
<label class="label mt-2 mb-5">
|
2
2
|
{{ field.label }}
|
3
|
-
<p class="helptext">{{ field.help_text }}</p>
|
4
3
|
{{ field }}
|
5
4
|
<span class="has-text-danger is-size-7">{{ field.errors }}</span>
|
5
|
+
<p class="helptext">{{ field.help_text }}</p>
|
6
6
|
</label>
|
@@ -11,12 +11,12 @@
|
|
11
11
|
</select>
|
12
12
|
<div id="{{ widget.attrs.id }}_display" class="input select py-1 pl-1" tabindex="0" x-ref="inputDisplay" aria-label="inputDisplay"
|
13
13
|
style="padding-right: 30px; border-radius: 0; border-top: 0; border-right:0; border-left: 0; min-height: var(--bulma-control-height); height: fit-content; width: 100%"
|
14
|
-
x-on:focus="open = true;"
|
14
|
+
x-on:focus="if (!$event.target.classList.contains('delete')) {open = true;}"
|
15
15
|
x-on:keydown="if (![9, 27, 38, 40].includes($event.keyCode)) {$refs.searchInput.focus();}"
|
16
|
-
x-on:mousedown.stop="if (open) {open = false; } else {open = true; $refs.searchInput.focus()}"
|
16
|
+
x-on:mousedown.stop="if (!$event.target.classList.contains('delete')) {if (open) {open = false; } else {open = true; $refs.searchInput.focus();}}"
|
17
17
|
>
|
18
18
|
<div class="tags" x-ref="inputDisplayTags"
|
19
|
-
|
19
|
+
x-on:click="
|
20
20
|
if ($event.target.classList.contains('delete')) {
|
21
21
|
let val = $event.target.getAttribute('data-value');
|
22
22
|
$refs.inputValue.querySelector(`option[value=${CSS.escape(val)}]`).remove();
|
accrete/contrib/ui/utils.py
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
import ast
|
2
2
|
import json
|
3
|
+
|
3
4
|
from django.http import HttpRequest, HttpResponse
|
4
5
|
from django.shortcuts import render
|
5
|
-
from .
|
6
|
+
from django.template.loader import render_to_string
|
7
|
+
|
8
|
+
from . import OobContext
|
9
|
+
from .context import BaseContext, ModalContext
|
10
|
+
from accrete.utils import render_templates
|
6
11
|
|
7
12
|
|
8
13
|
def modal_response(
|
@@ -24,8 +29,47 @@ def modal_response(
|
|
24
29
|
return res
|
25
30
|
|
26
31
|
|
32
|
+
def detail_response(
|
33
|
+
request: HttpRequest,
|
34
|
+
header_template: str = None,
|
35
|
+
content_template: str = None,
|
36
|
+
context: BaseContext | dict = None,
|
37
|
+
extra_content: str | None = None
|
38
|
+
) -> HttpResponse:
|
39
|
+
if isinstance(context, BaseContext):
|
40
|
+
context = context.dict()
|
41
|
+
templates = [
|
42
|
+
('ui/message.html', context)
|
43
|
+
]
|
44
|
+
if header_template:
|
45
|
+
templates.append(('ui/oob.html', OobContext(
|
46
|
+
template=header_template,
|
47
|
+
swap='innerHTML:#content-right-header',
|
48
|
+
extra=context
|
49
|
+
).dict()))
|
50
|
+
if content_template:
|
51
|
+
templates.append(('ui/oob.html', OobContext(
|
52
|
+
template=content_template,
|
53
|
+
swap='innerHTML:#content-right',
|
54
|
+
extra=context
|
55
|
+
).dict()))
|
56
|
+
content = render_templates(templates, request=request)
|
57
|
+
if extra_content:
|
58
|
+
content += extra_content
|
59
|
+
res = HttpResponse(content=content)
|
60
|
+
add_trigger(res, 'activate-content-right')
|
61
|
+
return res
|
62
|
+
|
63
|
+
|
64
|
+
def search_select_response(queryset) -> HttpResponse:
|
65
|
+
return HttpResponse(render_to_string(
|
66
|
+
'ui/widgets/model_search_select_options.html',
|
67
|
+
{'options': queryset}
|
68
|
+
))
|
69
|
+
|
70
|
+
|
27
71
|
def add_trigger(
|
28
|
-
response:
|
72
|
+
response: HttpResponse,
|
29
73
|
trigger: dict | str,
|
30
74
|
header: str = 'HX-Trigger'
|
31
75
|
) -> HttpResponse:
|
@@ -40,5 +84,5 @@ def add_trigger(
|
|
40
84
|
except SyntaxError:
|
41
85
|
res_trigger = {response.headers[header]: ''}
|
42
86
|
res_trigger.update(trigger)
|
43
|
-
response.headers[header] = json.dumps(
|
87
|
+
response.headers[header] = json.dumps(res_trigger)
|
44
88
|
return response
|
@@ -11,6 +11,7 @@ class ModelSearchSelect(widgets.NumberInput):
|
|
11
11
|
def __init__(
|
12
12
|
self,
|
13
13
|
search_url: str,
|
14
|
+
search_kwargs: dict = None,
|
14
15
|
search_parameter: str = 'search',
|
15
16
|
limit: int | None = 5,
|
16
17
|
hx_trigger_on_change: bool = False,
|
@@ -18,9 +19,10 @@ class ModelSearchSelect(widgets.NumberInput):
|
|
18
19
|
):
|
19
20
|
super().__init__()
|
20
21
|
self.search_url = search_url
|
22
|
+
self.search_kwargs = search_kwargs or {}
|
21
23
|
self.search_parameter = search_parameter
|
22
24
|
self.limit = limit
|
23
|
-
self.hx_trigger_on_change = hx_trigger_on_change
|
25
|
+
self.hx_trigger_on_change = hx_trigger_on_change # trigger 'change' event on the actual input field
|
24
26
|
self.choices = choices
|
25
27
|
|
26
28
|
def get_context(self, name, value, attrs):
|
@@ -38,7 +40,7 @@ class ModelSearchSelect(widgets.NumberInput):
|
|
38
40
|
'value_display': self.value_display(value),
|
39
41
|
"attrs": self.build_attrs(self.attrs, attrs),
|
40
42
|
"template_name": self.template_name,
|
41
|
-
'search_url': resolve_url(self.search_url),
|
43
|
+
'search_url': resolve_url(self.search_url, **self.search_kwargs),
|
42
44
|
'search_parameter': self.search_parameter,
|
43
45
|
'hx_trigger_on_change': self.hx_trigger_on_change,
|
44
46
|
'uuid': uuid
|
@@ -80,7 +82,7 @@ class ModelSearchSelectMulti(widgets.SelectMultiple):
|
|
80
82
|
self.search_kwargs = search_kwargs or {}
|
81
83
|
self.search_parameter = search_parameter
|
82
84
|
self.limit = limit
|
83
|
-
self.hx_trigger_on_change = hx_trigger_on_change
|
85
|
+
self.hx_trigger_on_change = hx_trigger_on_change # trigger 'change' event on the actual input field
|
84
86
|
self.choices = choices
|
85
87
|
|
86
88
|
def get_context(self, name, value, attrs):
|
accrete/utils/forms.py
CHANGED
@@ -1,79 +1,91 @@
|
|
1
1
|
import re
|
2
2
|
import logging
|
3
3
|
from uuid import uuid4
|
4
|
-
from typing import Type
|
4
|
+
from typing import Type, Any
|
5
|
+
from dataclasses import dataclass, field
|
5
6
|
from django.db import transaction
|
6
7
|
from django.forms import BaseFormSet, Form, ModelForm
|
7
8
|
|
8
9
|
_logger = logging.getLogger(__name__)
|
9
10
|
|
10
11
|
|
11
|
-
|
12
|
+
@dataclass
|
13
|
+
class FormResult:
|
14
|
+
|
15
|
+
form: Form | ModelForm
|
16
|
+
is_saved: bool = False
|
17
|
+
save_error: str | None = None
|
18
|
+
save_error_id: str | None = None
|
19
|
+
res: Any = None # return value of form.save()
|
20
|
+
inline_formsets: list = field(default_factory=list)
|
21
|
+
|
22
|
+
def __getattr__(self, item):
|
23
|
+
return getattr(self.form, item)
|
24
|
+
|
25
|
+
def __getitem__(self, item):
|
26
|
+
return self.form.__getitem__(item)
|
27
|
+
|
28
|
+
|
29
|
+
def save_form(form: Form | ModelForm, commit=True, reraise=False) -> FormResult:
|
12
30
|
if not hasattr(form, 'save'):
|
13
31
|
raise AttributeError('Form must have method "save" implemented.')
|
14
|
-
|
15
|
-
form.save_error = None
|
16
|
-
form.save_error_id = None
|
17
|
-
form.res = None
|
32
|
+
result = FormResult(form=form)
|
18
33
|
try:
|
19
34
|
if form.is_valid():
|
20
35
|
with transaction.atomic():
|
21
|
-
|
22
|
-
|
36
|
+
result.res = form.save(commit=commit)
|
37
|
+
result.is_saved = True
|
23
38
|
except Exception as e:
|
24
|
-
|
39
|
+
result.save_error = repr(e)
|
25
40
|
error_id = str(uuid4())[:8]
|
26
41
|
_logger.exception(f'{error_id}: {e}')
|
27
|
-
|
42
|
+
result.save_error_id = error_id
|
28
43
|
if reraise:
|
29
44
|
raise e
|
30
|
-
return
|
45
|
+
return result
|
31
46
|
|
32
47
|
|
33
|
-
def save_forms(form, inline_formsets: list = None, commit=True, reraise: bool = False) ->
|
48
|
+
def save_forms(form, inline_formsets: list = None, commit=True, reraise: bool = False) -> FormResult:
|
34
49
|
|
35
50
|
def handle_error(error):
|
36
|
-
|
51
|
+
result.save_error = repr(error)
|
37
52
|
error_id = str(uuid4())[:8]
|
38
53
|
_logger.exception(f'{error_id}: {error}')
|
39
|
-
|
54
|
+
result.save_error_id = error_id
|
40
55
|
|
41
56
|
if not hasattr(form, 'save'):
|
42
57
|
raise AttributeError('Form must have method "save" implemented.')
|
43
58
|
|
44
|
-
|
45
|
-
|
46
|
-
form.save_error_id = None
|
47
|
-
form.res = None
|
48
|
-
form.inline_forms = inline_formsets
|
59
|
+
result = FormResult(form=form)
|
60
|
+
result.inline_forms = inline_formsets
|
49
61
|
|
50
62
|
try:
|
51
63
|
form.is_valid()
|
52
64
|
inlines_valid = all([
|
53
|
-
inline_formset.is_valid() for inline_formset in inline_formsets
|
65
|
+
inline_formset.is_valid() for inline_formset in result.inline_formsets
|
54
66
|
])
|
55
67
|
except Exception as e:
|
56
68
|
handle_error(e)
|
57
69
|
if reraise:
|
58
70
|
raise e
|
59
|
-
return
|
71
|
+
return result
|
60
72
|
|
61
73
|
if not form.is_valid() or not inlines_valid:
|
62
|
-
return
|
74
|
+
return result
|
63
75
|
|
64
76
|
try:
|
65
77
|
with transaction.atomic():
|
66
|
-
|
67
|
-
for inline_formset in inline_formsets:
|
78
|
+
result.res = form.save(commit=commit)
|
79
|
+
for inline_formset in result.inline_formsets:
|
68
80
|
inline_formset.save(commit=commit)
|
69
81
|
except Exception as e:
|
70
82
|
handle_error(e)
|
71
83
|
if reraise:
|
72
84
|
raise e
|
73
|
-
return
|
85
|
+
return result
|
74
86
|
|
75
|
-
|
76
|
-
return
|
87
|
+
result.is_saved = True
|
88
|
+
return result
|
77
89
|
|
78
90
|
|
79
91
|
def inline_vals_from_post(post: dict, prefix: str) -> list[dict]:
|
@@ -60,16 +60,16 @@ accrete/contrib/system_mail/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2
|
|
60
60
|
accrete/contrib/system_mail/views.py,sha256=xc1IQHrsij7j33TUbo-_oewy3vs03pw_etpBWaMYJl0,63
|
61
61
|
accrete/contrib/system_mail/migrations/0001_initial.py,sha256=6cwkkRXGjXvwXoMjjgmWmcPyXSTlUbhW1vMiHObk9MQ,1074
|
62
62
|
accrete/contrib/system_mail/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
63
|
-
accrete/contrib/ui/__init__.py,sha256=
|
63
|
+
accrete/contrib/ui/__init__.py,sha256=7zRjbKxFZ_ox5XQmHmfxbKKJRcm_wxgmjXS759GdlEo,328
|
64
64
|
accrete/contrib/ui/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
|
65
65
|
accrete/contrib/ui/apps.py,sha256=E0ao2ox6PQ3ldfeR17FXJUUJuGiWjm2DPCxHbPXGzls,152
|
66
|
-
accrete/contrib/ui/context.py,sha256=
|
66
|
+
accrete/contrib/ui/context.py,sha256=7FBNcPG77dU7asMomiRACP1bypE3lbsHXdg90MXbjf4,2616
|
67
67
|
accrete/contrib/ui/filter.py,sha256=zLTWWSvsfvwBMNWgpZqP2kRKXCVW_50mhTQyJA36ywo,13323
|
68
68
|
accrete/contrib/ui/middleware.py,sha256=QprWR8FXK9iMPIvLQAeYASaUJSW0uD9BHoYroMKrph0,1560
|
69
69
|
accrete/contrib/ui/models.py,sha256=Vjc0p2XbAPgE6HyTF6vll98A4eDhA5AvaQqsc4kQ9AQ,57
|
70
70
|
accrete/contrib/ui/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
71
71
|
accrete/contrib/ui/urls.py,sha256=5XUfK85HYWYf7oopMoJEEYmQ6pNgHgZBErBEn97pBt4,337
|
72
|
-
accrete/contrib/ui/utils.py,sha256=
|
72
|
+
accrete/contrib/ui/utils.py,sha256=f660YNavcQQkO6TtpnEBsT2O3KoJk-M5wgBnhnWB1EI,2563
|
73
73
|
accrete/contrib/ui/views.py,sha256=5VUbP0jgMcLMv9-3AKxkV315RA0qXuw5PmTRejPc0Yg,1136
|
74
74
|
accrete/contrib/ui/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
75
75
|
accrete/contrib/ui/static/bulma/LICENSE,sha256=--fY7Bi3Lt7RXXnKc9pe756OJY9fGv-D5OmT5pdSJ5w,1080
|
@@ -169,11 +169,11 @@ accrete/contrib/ui/static/bulma/versions/bulma-no-helpers-prefixed.scss,sha256=N
|
|
169
169
|
accrete/contrib/ui/static/bulma/versions/bulma-no-helpers.scss,sha256=gyRiEug6frpDJEaxZ7VybdApnmNS5R5A9Zn1R0yWLJg,335
|
170
170
|
accrete/contrib/ui/static/bulma/versions/bulma-prefixed.scss,sha256=cDhte1VyFupdjYFXpUyQb7wGB8aUKDGYuKluZCY5CtA,133
|
171
171
|
accrete/contrib/ui/static/css/accrete.css,sha256=uvPIU2FvJFnFwyvISjhrHVDC1OV9H1MsDU9id4HZiJg,6862
|
172
|
-
accrete/contrib/ui/static/css/accrete.css.map,sha256=
|
173
|
-
accrete/contrib/ui/static/css/accrete.scss,sha256=
|
172
|
+
accrete/contrib/ui/static/css/accrete.css.map,sha256=UFEDkXkiYpwyBsk0N3SVaAx316bMz0SPsGUUibpbfag,3887
|
173
|
+
accrete/contrib/ui/static/css/accrete.scss,sha256=ZuIwivXkinl4vPJTTy1J48yYXON5YjLLpUBOgCYgomg,7205
|
174
174
|
accrete/contrib/ui/static/css/fa.css,sha256=wiz7ZSCn_btzhjKDQBms9Hx4sSeUYsDrTLg7roPstac,102641
|
175
175
|
accrete/contrib/ui/static/css/icons.css,sha256=5550KHsaayeEtRaUdf0h7esQhyec-_5ZfecZ_sOC6v0,6334
|
176
|
-
accrete/contrib/ui/static/css/.sass-cache/15adf1eed05371361b08787c918a7f18fc15be79/accrete.scssc,sha256=
|
176
|
+
accrete/contrib/ui/static/css/.sass-cache/15adf1eed05371361b08787c918a7f18fc15be79/accrete.scssc,sha256=COJYmUzNErZkHzYxo3GVAqn7leI8NHOyD_YSii9XjHU,71246
|
177
177
|
accrete/contrib/ui/static/icons/Logo.svg,sha256=hGZuxrAa-LRpFavFiF8Lnc7X9OQcqmb6Xl_dxx-27hM,1861
|
178
178
|
accrete/contrib/ui/static/icons/accrete.svg,sha256=CWHJKIgk3hxL7xIaFSz2j1cK-eF1TroCbjcF58bgOIs,1024
|
179
179
|
accrete/contrib/ui/static/js/alpine-3.14.9.js,sha256=tgDjY9mdlURNtUrL-y3v_smueSqpmgkim82geOW1VkM,44758
|
@@ -198,28 +198,29 @@ accrete/contrib/ui/templates/django/forms/widgets/select.html,sha256=uSfDpOQox2m
|
|
198
198
|
accrete/contrib/ui/templates/django/forms/widgets/text.html,sha256=MSmLlQc7PsPoDLVtTOOiWNprrsPriNr712yFxaHyDIo,47
|
199
199
|
accrete/contrib/ui/templates/django/forms/widgets/textarea.html,sha256=c9BTedqb3IkXLyVYd0p9pR8DFnsXCNGoxVBWZTk_Fic,278
|
200
200
|
accrete/contrib/ui/templates/ui/content_right.html,sha256=3DQqbjAafaLtWUTGcBTCzObQEII35DVLfWQ6i6KDh6Y,379
|
201
|
-
accrete/contrib/ui/templates/ui/
|
202
|
-
accrete/contrib/ui/templates/ui/
|
203
|
-
accrete/contrib/ui/templates/ui/
|
201
|
+
accrete/contrib/ui/templates/ui/favicon.html,sha256=ZSK6qDGV4Cexgt0VA3KOHYN100yZHOFjfOiFZVudWg0,90
|
202
|
+
accrete/contrib/ui/templates/ui/form_error.html,sha256=WWqfFWyJ_LCzm5IkxXztn23GFak5wyM2HZcmiZ3Eq9s,417
|
203
|
+
accrete/contrib/ui/templates/ui/layout.html,sha256=yDcZYMUdT3ZaqXPC1qg2Lme_dBnBUG2ZzGyrG0V6ces,13174
|
204
|
+
accrete/contrib/ui/templates/ui/list.html,sha256=o0YGM2O4SUlFcP5jMwdEOXVTCuEfanvd77yH7OBRRws,2208
|
204
205
|
accrete/contrib/ui/templates/ui/list_update.html,sha256=mLQTCgkKfVI5jrgei-Upc1u87iXL0Q63uLzXHPwMyeo,110
|
205
|
-
accrete/contrib/ui/templates/ui/message.html,sha256=
|
206
|
-
accrete/contrib/ui/templates/ui/modal.html,sha256=
|
206
|
+
accrete/contrib/ui/templates/ui/message.html,sha256=jhqkPlWtOaPDoclTm4yKwowA7vR-bWbwfjo2b48uJt0,764
|
207
|
+
accrete/contrib/ui/templates/ui/modal.html,sha256=2HwmqcUvGqWfKpuKO1EOfr5F1Lcwn7eChbu3XbrxvYg,2233
|
207
208
|
accrete/contrib/ui/templates/ui/oob.html,sha256=lZHIBBYclefbGkKguS1A7vrtOhODJizbSRaGAAHDvG8,267
|
208
|
-
accrete/contrib/ui/templates/ui/table.html,sha256=
|
209
|
+
accrete/contrib/ui/templates/ui/table.html,sha256=u6JJz1FykuljZiiC2hL83hy8RbMeXcSH8xuU1ji2SHc,3939
|
209
210
|
accrete/contrib/ui/templates/ui/table_row_update.html,sha256=_7tKQlCXxczguYQ-6rkZRwukYBswsh3J2cwT4ke_sQM,445
|
210
211
|
accrete/contrib/ui/templates/ui/filter/filter.html,sha256=RBYzmgQmgWKjVNrtZo9L98IW23vWLKSDQrZRb88VxrQ,758
|
211
212
|
accrete/contrib/ui/templates/ui/filter/query_input.html,sha256=Qg_41fODXMgL534ohktb0QOxNzAEbaeBzAajJCEK7Pg,2035
|
212
213
|
accrete/contrib/ui/templates/ui/filter/query_operator.html,sha256=h4WWLDnse6DK5Rb_0TTb0wqWxhvY_g3qjwx8_eENMuI,569
|
213
214
|
accrete/contrib/ui/templates/ui/filter/query_params.html,sha256=wCkyZ9oSK_ivraNiL-UAY_9TflYw5EspnHHm6V6uOzk,9548
|
214
215
|
accrete/contrib/ui/templates/ui/filter/query_tags.html,sha256=QSdM5w8UduT89x4S1ttdmzECBBnR-JipKOsf7rBCfL4,1562
|
215
|
-
accrete/contrib/ui/templates/ui/templatetags/field.html,sha256=
|
216
|
+
accrete/contrib/ui/templates/ui/templatetags/field.html,sha256=xQGixZBcgRfQVkRDDOcQVvz2blPia_h0sS6Deatgbkc,198
|
216
217
|
accrete/contrib/ui/templates/ui/widgets/model_search_select.html,sha256=bk6m38_u_hbudQoXqzGunGUhvHRphVDlfKjkdcB9rEs,2748
|
217
|
-
accrete/contrib/ui/templates/ui/widgets/model_search_select_multi.html,sha256=
|
218
|
+
accrete/contrib/ui/templates/ui/widgets/model_search_select_multi.html,sha256=ojj3n6kAAWL-O8-dqGX2nqFWnPpLlbVvAyiZytSuq10,4599
|
218
219
|
accrete/contrib/ui/templates/ui/widgets/model_search_select_options.html,sha256=4Wky0XkYWZlIKXTXzGjJkJTX3H9rhjXTY1hYai3Q3TA,242
|
219
220
|
accrete/contrib/ui/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
220
221
|
accrete/contrib/ui/templatetags/ui.py,sha256=_aKZoLwH_AcDszy3a3lehQsTg9zDaNeMmbSnjFK2wpM,4220
|
221
222
|
accrete/contrib/ui/widgets/__init__.py,sha256=W_y10jfu37lygp4frXuKFSGec97gpNbWskG6DMhTKtY,69
|
222
|
-
accrete/contrib/ui/widgets/search_select.py,sha256=
|
223
|
+
accrete/contrib/ui/widgets/search_select.py,sha256=zKmOt54QsxUobNkDNEA2ut3pPAl8a5DqmEpcfam1l1I,3762
|
223
224
|
accrete/contrib/user/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
224
225
|
accrete/contrib/user/admin.py,sha256=0SGhVB5RcIsbCvrLf9ZSgIFH68XmGlPzovisMP8bb6c,710
|
225
226
|
accrete/contrib/user/apps.py,sha256=oHDrAiHf-G57mZLyxqGJzRY2DbPprGFD-QgyVJG_ruI,156
|
@@ -269,11 +270,11 @@ accrete/migrations/0007_accessgroup_description.py,sha256=T8BX0gSckC_fM_uD6a5-fd
|
|
269
270
|
accrete/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
270
271
|
accrete/utils/__init__.py,sha256=saw9zi2XItJOPbv4fjTXOpl7StNtC803jHhapFcGx08,312
|
271
272
|
accrete/utils/dates.py,sha256=apM6kt6JhGrKgoT0jfav1W-8AUVTxNc9xt3fJQ2n0JI,1492
|
272
|
-
accrete/utils/forms.py,sha256=
|
273
|
+
accrete/utils/forms.py,sha256=H8ojiMRrafdj6Jd-86w2SxkaqshKepNHP2_XOXsMmKQ,3758
|
273
274
|
accrete/utils/log.py,sha256=BH0MBDweAjx30wGBO4F3sFhbgkSoEs7T1lLLjlYZNnA,407
|
274
275
|
accrete/utils/models.py,sha256=2xTacvcpmDK_Bp4rAK7JdVLf8HU009LYNJ6eSpMgYZI,1014
|
275
276
|
accrete/utils/views.py,sha256=PsKpUFjxCm6_l_nfVs-cNIY0lNTdkocm2uohR3o9eEo,5025
|
276
|
-
accrete-0.0.
|
277
|
-
accrete-0.0.
|
278
|
-
accrete-0.0.
|
279
|
-
accrete-0.0.
|
277
|
+
accrete-0.0.143.dist-info/METADATA,sha256=JfyR1afDladHASbgL-b4Kg1nA6ijfDlOmqEv2qV0qyc,4953
|
278
|
+
accrete-0.0.143.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
279
|
+
accrete-0.0.143.dist-info/licenses/LICENSE,sha256=vHwb4Qnv8UfYKFiCWyTuRGsi49x19UQwHRCky3b2_NE,1057
|
280
|
+
accrete-0.0.143.dist-info/RECORD,,
|
File without changes
|
File without changes
|