Skip to content

Commit

Permalink
Feature/43 (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-yin authored Aug 1, 2024
1 parent a657d87 commit 861d1e0
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 45 deletions.
16 changes: 16 additions & 0 deletions docs/source/signal-decorator.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,19 @@ Notes:
2. The function decorated by `after_create_commit`, `after_update_commit`, receive the same arguments as `post_save` signal handler.
3. The function decorated by `after_delete_commit` receive the same arguments as `post_delete` signal handler.
4. This can make our code more clear, especially when we need to some broadcasts.

## django-lifecycle

Another approach is to use `django-lifecycle` package, which is inspired by Rails' `ActiveRecord` callbacks.

So we can write the code in Django model like this:

```python
@hook(AFTER_UPDATE, on_commit=True)
def broadcast_updated(self):
pass

@hook(BEFORE_DELETE)
def broadcast_deleted(self):
pass
```
1 change: 1 addition & 0 deletions docs/source/turbo_stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Turbo Stream built-in actions are all supported in syntax `turbo_stream.xxx`:
- remove
- before
- after
- morph

### TurboStreamResponse

Expand Down
10 changes: 10 additions & 0 deletions src/turbo_helper/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ def update(target, content=None, **kwargs):
return turbo_stream.action("update", target, content, **kwargs)


@register_turbo_stream_action("morph")
def morph(target, content=None, **kwargs):
return turbo_stream.action("morph", target, content, **kwargs)


################################################################################


Expand Down Expand Up @@ -166,3 +171,8 @@ def replace_all(targets, content=None, **kwargs):
@register_turbo_stream_action("update_all")
def update_all(targets, content=None, **kwargs):
return turbo_stream.action_all("update", targets, content, **kwargs)


@register_turbo_stream_action("morph_all")
def morph_all(targets, content=None, **kwargs):
return turbo_stream.action_all("morph_all", targets, content, **kwargs)
30 changes: 19 additions & 11 deletions src/turbo_helper/turbo_power.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,25 @@ def custom_action_all(action, targets=None, content=None, **kwargs):
)


################################################################################

"""
When defining custom action, `target` or `targets` are both supported
def example_action(targets=None, **attributes):
pass
This action by default will use `targets` as the target selector
turbo_stream.example_action("A")
Generate: <turbo-stream targets="A"
if you want to use `target` as the target selector, should explicitly pass the target
turbo_stream.example_action(target="A")
Generate: <turbo-stream target="A"
"""

# DOM Actions


Expand All @@ -62,17 +81,6 @@ def graft(targets=None, parent=None, **attributes):
)


@register_turbo_stream_action("morph")
def morph(targets=None, html=None, **attributes):
html = html or attributes.pop("content", None)
return custom_action_all(
"morph",
targets=targets,
content=mark_safe(html) if html else None,
**attributes,
)


# Attribute Actions


Expand Down
22 changes: 22 additions & 0 deletions tests/test_stream.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.http import HttpRequest
from django.utils.safestring import mark_safe

from tests.utils import assert_dom_equal
from turbo_helper import turbo_stream
from turbo_helper.constants import TURBO_STREAM_MIME_TYPE

Expand Down Expand Up @@ -98,3 +99,24 @@ def test_response(self, rf):
'<turbo-stream action="append" target="dom_id_2">'
in response.content.decode("utf-8")
)


class TestMorph:
def test_morph(self):
stream = '<turbo-stream target="#input" action="morph"><template><p>Morph</p></template></turbo-stream>'
assert_dom_equal(
stream, turbo_stream.morph("#input", mark_safe("<p>Morph</p>"))
)

def test_morph_with_targets_as_positional_arg_and_html_as_kwarg(self):
stream = '<turbo-stream targets=".test" action="morph_all"><template><p>Morph</p></template></turbo-stream>'
assert_dom_equal(
stream, turbo_stream.morph_all(".test", mark_safe("<p>Morph</p>"))
)

def test_morph_with_additional_arguments(self):
stream = '<turbo-stream target="#input" action="morph" something="else"><template><p>Morph</p></template></turbo-stream>'
assert_dom_equal(
stream,
turbo_stream.morph("#input", mark_safe("<p>Morph</p>"), something="else"),
)
34 changes: 0 additions & 34 deletions tests/test_turbo_power.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,40 +29,6 @@ def test_graft_with_additional_arguments(self):
)


class TestMorph:
def test_morph(self):
stream = '<turbo-stream targets="#input" action="morph"><template><p>Morph</p></template></turbo-stream>'
assert_dom_equal(stream, turbo_stream.morph("#input", "<p>Morph</p>"))

def test_morph_with_targets_and_html_as_kwargs(self):
stream = '<turbo-stream targets="#input" action="morph"><template><p>Morph</p></template></turbo-stream>'
assert_dom_equal(
stream, turbo_stream.morph(targets="#input", html="<p>Morph</p>")
)

def test_morph_with_target_and_html_as_kwargs(self):
stream = '<turbo-stream target="input" action="morph"><template><p>Morph</p></template></turbo-stream>'
assert_dom_equal(
stream, turbo_stream.morph(target="input", html="<p>Morph</p>")
)

def test_morph_with_html_and_targets_as_kwargs(self):
stream = '<turbo-stream targets="#input" action="morph"><template><p>Morph</p></template></turbo-stream>'
assert_dom_equal(
stream, turbo_stream.morph(html="<p>Morph</p>", targets="#input")
)

def test_morph_with_targets_as_positional_arg_and_html_as_kwarg(self):
stream = '<turbo-stream targets="#input" action="morph"><template><p>Morph</p></template></turbo-stream>'
assert_dom_equal(stream, turbo_stream.morph("#input", html="<p>Morph</p>"))

def test_morph_with_additional_arguments(self):
stream = '<turbo-stream targets="#input" action="morph" something="else"><template><p>Morph</p></template></turbo-stream>'
assert_dom_equal(
stream, turbo_stream.morph("#input", html="<p>Morph</p>", something="else")
)


class TestAddCssClass:
def test_add_css_class(self):
stream = '<turbo-stream targets="#element" action="add_css_class" classes="container text-center"><template></template></turbo-stream>'
Expand Down

0 comments on commit 861d1e0

Please sign in to comment.