Skip to content

Commit

Permalink
Feature/31 custom action (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-yin authored Jan 16, 2024
1 parent 9cfaa2c commit 6d9c2bd
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 53 deletions.
4 changes: 4 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ def _get_version() -> str:
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".

html_theme_options = {
"announcement": 'If you are new to Hotwire, you may be interested in this free eBook <a href="https://tutorial.saashammer.com/" rel="nofollow" target="_blank">Hotwire Django Tutorial</a>',
}
57 changes: 46 additions & 11 deletions docs/source/turbo_stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ turbo_stream.append("dom_id", "OK")
turbo_stream.append("dom_id", content="OK")

# template example
turbo_stream.append("dom_id", template="simple.html", context={"msg": "my content"}, request=request)
turbo_stream.append(
"dom_id",
template="simple.html",
context={"msg": "my content"},
request=request
)
```

Turbo Stream built-in actions are supported in syntax `turbo_stream.xxx`:
Expand All @@ -34,8 +39,18 @@ from turbo_helper import TurboStreamResponse

# render multiple turbo stream elements in one response
return TurboStreamResponse([
turbo_stream.append("message", template="message.html", context={"msg": "my content"}, request=request),
turbo_stream.update("form", template="form.html", context={"form": form}, request=request),
turbo_stream.append(
"message",
template="message.html",
context={"msg": "my content"},
request=request
),
turbo_stream.update(
"form",
template="form.html",
context={"form": form},
request=request
),
])
```

Expand All @@ -46,8 +61,18 @@ from turbo_helper import turbo_stream

# render multiple turbo stream elements in one response
return turbo_stream.response([
turbo_stream.append("message", template="message.html", context={"msg": "my content"}, request=request),
turbo_stream.update("form", template="form.html", context={"form": form}, request=request),
turbo_stream.append(
"message",
template="message.html",
context={"msg": "my content"},
request=request
),
turbo_stream.update(
"form",
template="form.html",
context={"form": form},
request=request
),
])
```

Expand Down Expand Up @@ -80,20 +105,30 @@ You can extend Turbo Stream Action by `register_turbo_stream_action` decorator.

```python
from turbo_helper import (
register_turbo_stream_action,
turbo_stream,
register_turbo_stream_action,
turbo_stream,
)


# register toast action
@register_turbo_stream_action("toast")
def toast(target, message, position="left"):
return turbo_stream.render_action(
"toast", target=target, data_message=message, data_position=position
def toast(target, content=None, **kwargs):
position = kwargs.get('position', 'left')
return turbo_stream.action(
"toast", target=target, message=kwargs['message'], position=position
)


turbo_stream.toast("dom_id", message="hello world", position="right")
# <turbo-stream action="toast" target="dom_id" data-message="hello world" data-position="right">
# <turbo-stream action="toast" target="dom_id" message="hello world" position="right">
```

Or you can do it in template:

```django
{% load turbo_helper %}
{% turbo_stream "toast" "target" message="Hello Word" position="right" %}{% endturbo_stream %}
```

## Targeting Multiple Elements
Expand Down
32 changes: 16 additions & 16 deletions src/turbo_helper/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(self):
def is_registered(self, name):
return name in self.registered_actions

def render_action(self, action, target, content=None, **kwargs):
def action(self, action, target, content=None, **kwargs):
if not content and kwargs.get("template", None):
# render template content
template = kwargs.pop("template")
Expand All @@ -28,7 +28,7 @@ def render_action(self, action, target, content=None, **kwargs):
action=action, content=content, target=target, attributes=kwargs
)

def render_action_all(self, action, targets, content=None, **kwargs):
def action_all(self, action, targets, content=None, **kwargs):
if not content and kwargs.get("template", None):
# render template content
template = kwargs.pop("template")
Expand Down Expand Up @@ -69,72 +69,72 @@ def decorator(func):

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


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


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


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


@register_turbo_stream_action("remove")
def remove(target, **kwargs):
return turbo_stream.render_action("remove", target, **kwargs)
return turbo_stream.action("remove", target, **kwargs)


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


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


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


@register_turbo_stream_action("append_all")
def append_all(targets, content=None, **kwargs):
return turbo_stream.render_action_all("append", targets, content, **kwargs)
return turbo_stream.action_all("append", targets, content, **kwargs)


@register_turbo_stream_action("after_all")
def after_all(targets, content=None, **kwargs):
return turbo_stream.render_action_all("after", targets, content, **kwargs)
return turbo_stream.action_all("after", targets, content, **kwargs)


@register_turbo_stream_action("before_all")
def before_all(targets, content=None, **kwargs):
return turbo_stream.render_action_all("before", targets, content, **kwargs)
return turbo_stream.action_all("before", targets, content, **kwargs)


@register_turbo_stream_action("prepend_all")
def prepend_all(targets, content=None, **kwargs):
return turbo_stream.render_action_all("prepend", targets, content, **kwargs)
return turbo_stream.action_all("prepend", targets, content, **kwargs)


@register_turbo_stream_action("remove_all")
def remove_all(targets, **kwargs):
return turbo_stream.render_action_all("remove", targets, **kwargs)
return turbo_stream.action_all("remove", targets, **kwargs)


@register_turbo_stream_action("replace_all")
def replace_all(targets, content=None, **kwargs):
return turbo_stream.render_action_all("replace", targets, content, **kwargs)
return turbo_stream.action_all("replace", targets, content, **kwargs)


@register_turbo_stream_action("update_all")
def update_all(targets, content=None, **kwargs):
return turbo_stream.render_action_all("update", targets, content, **kwargs)
return turbo_stream.action_all("update", targets, content, **kwargs)
33 changes: 21 additions & 12 deletions src/turbo_helper/templatetags/turbo_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
from django.template import Node, TemplateSyntaxError
from django.template.base import token_kwargs

from turbo_helper.renderers import (
render_turbo_frame,
render_turbo_stream,
render_turbo_stream_from,
)
from turbo_helper import turbo_stream
from turbo_helper.renderers import render_turbo_frame, render_turbo_stream_from

register = template.Library()

Expand Down Expand Up @@ -106,13 +103,25 @@ def render(self, context):
for key, value in self.extra_context.items()
}

return render_turbo_stream(
action=self.action.resolve(context),
target=self.target.resolve(context) if self.target else None,
targets=self.targets.resolve(context) if self.targets else None,
content=children,
attributes=attributes,
)
target = self.target.resolve(context) if self.target else None
targets = self.targets.resolve(context) if self.targets else None

if target:
action = self.action.resolve(context)
func = getattr(turbo_stream, f"{action}")
return func(
target=target,
content=children,
**attributes,
)
elif targets:
action = self.action.resolve(context)
func = getattr(turbo_stream, f"{action}_all")
return func(
targets=targets,
content=children,
**attributes,
)


class TurboStreamFromTagNode(Node):
Expand Down
18 changes: 18 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,21 @@ def todo():
from tests.testapp.models import TodoItem

return TodoItem.objects.create(description="test")


@pytest.fixture()
def register_toast_action():
from turbo_helper import register_turbo_stream_action, turbo_stream

@register_turbo_stream_action("toast")
def toast(target, content=None, **kwargs):
position = kwargs.get("position", "left")
return turbo_stream.action(
"toast", target=target, message=kwargs["message"], position=position
)

yield

# cleanup
delattr(turbo_stream, "toast")
turbo_stream.registered_actions.remove("toast")
17 changes: 3 additions & 14 deletions tests/test_stream.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from django.http import HttpRequest
from django.utils.safestring import mark_safe

from turbo_helper import (
TURBO_STREAM_CONTENT_TYPE,
register_turbo_stream_action,
turbo_stream,
)
from turbo_helper import TURBO_STREAM_CONTENT_TYPE, turbo_stream


class TestTurboStream:
Expand Down Expand Up @@ -65,17 +61,10 @@ def test_template_multiple_targets(self):
assert "my content" in s
assert '<turbo-stream action="append" targets=".old_records">' in s

def test_custom_register(self):
# register toast action
@register_turbo_stream_action("toast")
def toast(target, message, position="left"):
return turbo_stream.render_action(
"toast", target=target, data_message=message, data_position=position
)

def test_custom_register(self, register_toast_action):
s = turbo_stream.toast("dom_id", message="hello world", position="right")
assert (
'<turbo-stream action="toast" target="dom_id" data-message="hello world" data-position="right">'
'<turbo-stream action="toast" target="dom_id" message="hello world" position="right">'
in s
)

Expand Down
12 changes: 12 additions & 0 deletions tests/test_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ def test_dom_id_variable(self):
== '<turbo-stream action="append" target="test"><template>Test</template></turbo-stream>'
)

def test_custom_register(self, register_toast_action):
template = """
{% load turbo_helper %}
{% turbo_stream "toast" dom_id message="Hello Word" position="right" %}{% endturbo_stream %}
"""
output = render(template, {"dom_id": "test"}).strip()
assert (
'<turbo-stream action="toast" target="test" message="Hello Word" position="right">'
in output
)


class TestStreamAll:
def test_string(self):
Expand Down

0 comments on commit 6d9c2bd

Please sign in to comment.