Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/31 custom action #34

Merged
merged 5 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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