Edelvalle Reactor Versions Save

Phoenix LiveView but for Django

1.2.0b0

4 years ago

Breaking changes in how to test components, for better

Using async with reactor() as comm, you get an object that you can use to register components, send commands... doc is a PyQuery object containing the HTML rendering of the object, so you can perform checkings of the rendering of the object.

from pytest import mark
from channels.db import database_sync_to_async as db
from reactor.tests import reactor

@mark.django_db(transaction=True)
async def test_live_components():
        x_list = comm.add_component(
            'x-todo-list',
            {'id': 'someid', 'showing': 'all'}
        )
        x_todo_counter = comm.add_component(
            'x-todo-counter',
            {'id': 'someid-counter'}
        )
        doc = await comm.send_join(x_list)
        todo_list = doc('#someid')
        assert json.loads(todo_list.attr['state']) == comm[x_list].state

        # Add new item
        doc = await comm.send(x_list, 'add', new_item='First task')

        # There was an item crated and rendered
        assert await db(Item.objects.count)() == 1
        assert len(doc('x-todo-item')) == 1
        todo_item_id = doc('x-todo-item')[0].get('id')
        todo_item_label = doc('x-todo-item label')[0]
        assert todo_item_label.text == 'First task'

1.1.0b0

4 years ago

Added:

  • Component.send_redirect has a new parameter push_state=True, when set it will do a push state in the front-end.
  • In the front-end you can use push_state(url) to trigger this in the front-end.

1.0.0b0

4 years ago

Changed

  • Rename reactor.component.send_to_group to reactor.broadcast
  • Open the reactor channel after all HTML5 elements are created.
  • Improve reconnect timing logic.
  • When an event is sent to the back-end and the event originates from a form or inside of it, just the form data is serialized and sent to the back-end.

Added

  • Django settings REACTOR_AUTO_BROADCAST = True will trigger broadcast updates when models instances are manipulated.
  • Add a component for authenticated user only and staff component: AuthComponent and StaffComponent
  • Add debounce function to send events to the backend.
  • Add directive reactor-once when an element is market with it, it will not be updated.
  • Add ReactorChannel.reconnect, closes the connection and reopens it.
  • Add public parameter to class inheritance, so you can decide if the element is exposed or not.

0.3.0b0

4 years ago

Changes

Breaking changes:

  • Now the dispatching of incoming events from the front-end are not atomic transactions. You will have to put @atomic when you want something to be atomic. The reason for this is that some events don't have to deal at all with the database because they just change the local state of the component.

Added:

  • reactor.broadcast(*names): this broadcasts the messages that you can subscribe to using Component.subscribe().
  • Component.send_redirect(url): now you can send a URL redirect to the front-end, when the component is being rendered for first time the redirect is rendered as a <meta http-equiv="refresh" content="0; url={{ url }}">, if the component is alive then the front-end controller executes the redirect.
  • AuthComponent, this component has a user attributed taken from the Component._context and on mount if the user is authenticated returns the True, if the user is not returns None and sends a redirect to settings.LOGIN_URL.
  • Serialization of arrays in the front-end, in case you have:
    <input name="query" value="q">
    <input name="persons[].name" value="a">
    <input name="persons[].name" value="b">

This will be serialized as: {query: "q", persons: [{name: "a"}, {name: "b"}]}

Room for improvement:

  • Proper documentation.
  • More testing.

0.2.1b0

4 years ago
  • Adds to component component send_redirect(url). Example:
def receive_save(self, name, **kwargs):
    self.instance.name = name
    self.instance.save()
    self.send_redirect(self.instance.get_absolute_url())
  • Components are now based on div and this can be redefined by the user overwriting the extends attribute. Example:
class MySpecialInput(Component):
    extends = 'input'