# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['reactor', 'reactor.templatetags']

package_data = \
{'': ['*'],
 'reactor': ['static/reactor/.gitignore',
             'static/reactor/.gitignore',
             'static/reactor/.gitignore',
             'static/reactor/.gitignore',
             'static/reactor/.gitignore',
             'static/reactor/morphdom.min.js',
             'static/reactor/morphdom.min.js',
             'static/reactor/morphdom.min.js',
             'static/reactor/morphdom.min.js',
             'static/reactor/morphdom.min.js',
             'static/reactor/reactor.coffee',
             'static/reactor/reactor.coffee',
             'static/reactor/reactor.coffee',
             'static/reactor/reactor.coffee',
             'static/reactor/reactor.coffee',
             'static/reactor/reactor.css',
             'static/reactor/reactor.css',
             'static/reactor/reactor.css',
             'static/reactor/reactor.css',
             'static/reactor/reactor.css',
             'static/reactor/turbolinks.min.js',
             'static/reactor/turbolinks.min.js',
             'static/reactor/turbolinks.min.js',
             'static/reactor/turbolinks.min.js',
             'static/reactor/turbolinks.min.js',
             'templates/*']}

install_requires = \
['channels>=2.2.0,<2.5', 'orjson>=3,<4', 'splinter[django]>=0.14.0,<0.15.0']

setup_kwargs = {
    'name': 'django-reactor',
    'version': '2.2.0b0',
    'description': 'Brings LiveView from Phoenix framework into Django',
    'long_description': '# Reactor, a LiveView library for Django\n\nReactor enables you to do something similar to Phoenix framework LiveView using Django Channels.\n\n![TODO MVC demo app](demo.gif)\n\n## What\'s in the box?\n\nThis is no replacement for VueJS or ReactJS, or any JavaScript but it will allow you use all the potential of Django to create interactive front-ends. This method has its drawbacks because if connection is lost to the server the components in the front-end go busted until connection is re-established. But also has some advantages, as everything is server side rendered the interface comes already with meaningful information in the first request response, you can use all the power of Django template without limitations, if connection is lost or a component crashes, the front-end will have enough information to rebuild their state in the last good known state.\n\n## Installation and setup\n\nReactor requires Python >=3.6.\n\nInstall reactor:\n\n```bash\npip install django-reactor\n```\n\nReacto makes use of `django-channels`, by default this one uses an InMemory channel layer which is not capable of a real broadcasting, so you might wanna use the Redis one, take a look here: [Channel Layers](https://channels.readthedocs.io/en/latest/topics/channel_layers.html) \n\nAdd `reactor` and `channels` to your `INSTALLED_APPS` before the Django applications so channels can override the `runserver` command. \n\n```python\nINSTALLED_APPS = [\n    \'reactor\',\n    \'channels\',\n    ...\n]\n\n...\n\nASGI_APPLICATION = \'project_name.asgi.application\'\n```\n\nRegister the reactor consumer at the url `/__reactor__` in your `project_name/urls.py` as in:\n\n```python\nfrom django.contrib import admin\nfrom django.urls import path\nfrom reactor.channels import ReactorConsumer\n\nurlpatterns = [\n    path(\'admin/\', admin.site.urls),\n]\n\nwebsocket_urlpatterns = [\n    path(\'__reactor__\', ReactorConsumer),\n]\n```\n\nand modify your `project_name/asgi.py` file like:\n\n```python\nimport os\n\nos.environ.setdefault(\'DJANGO_SETTINGS_MODULE\', \'project_name.settings\')\n\nfrom reactor.asgi import get_asgi_application  # noqa\n\napplication = get_asgi_application()\n```\n\nNote 1: The reactor `ASGIHandler` will be load the URLs from your `project_name/urls.py` and the HTTP ones and the WebSocket ones, so if you need to add more WebSocket handlers feel free to add them to `websocket_urlpatterns`.\n\nNote 1: Reactor since version 2, autoloads any `live.py` file in your applications with the hope to find there Reactor Components so they get registered and can be instantiated.\n\nIn the templates where you want to use reactive components you have to load the reactor static files. So do something like this so the right JavaScript gets loaded:\n\n```html\n{% load reactor %}\n<!doctype html>\n<html>\n  <head>\n     ....\n     {% reactor_header %}\n  </head>\n  ...\n</html>\n```\n\nDon\'t worry if you put this as early as possible, the scripts are loaded using `<script defer>` so they will be downloaded in parallel with the html, and then all is loaded they are executed.\n\n## Settings:\n\n- `REACTOR_AUTO_BROADCAST` (default: `False`), when enabled will activate listeners for every time a model is created, modified or deleted, and will broadcast a message related to that modification that you can subscribe to and use to refresh your components in real-time, you can fine tune what kind of notification you want to get by turning this in a dictionary, for example:\n\n```python\nAUTO_BROADCAST = {\n    # model_a\n    # model_a.del\n    # model_a.new\n    \'MODEL\': True,\n\n    # model_a.1234\n    \'MODEL_PK\': True,\n\n    # model_b.1234.model_a_set\n    # model_b.1234.model_a_set.new\n    # model_b.1234.model_a_set.del\n    \'RELATED\': True,\n\n    # model_b.1234.model_a_set\n    # model_a.1234.model_b_set\n    \'M2M\': True,\n}\n```\n\n- `REACTOR_INCLUDE_TURBOLINKS` (default: `False`), when enabled will load [Turbolinks](https://github.com/turbolinks/turbolinks) as part of the reactor headers and the reactor redirects (`Component.send_redirect`) will use `Turbolinks.visit`. This also affects all the links in your application, check out the documentation of Turbolinks.\n- `REACTOR_USE_HTML_DIFF` (default: `True`), when enabled uses `difflib` to create diffs to patch the front-end, reducing bandwidth.\n\n## Back-end APIs\n\n### Template tags and filters of `react` library\n\n- `{% reactor_headers %}`: that includes the necessary JavaScript to make this library work. ~5Kb of minified JS, compressed with gz or brotli.\n- `{% component \'x-component-name\' param1=1 param2=2 %}`: Renders a component by its name and passing whatever parameters you put there to the `Component.mount` method.\n- `tojson`: Takes something and renders it in JSON, the `ReactorJSONEncoder` extends the `DjangoJSONEncoder` it serializes a `Model` instance to its `id` and a `QuerySet` as a list of `ids`.\n- `tojson_safe`: Same as `tojson` but does not "HTML escapes" the output.\n- `then`: Use as a shorthand for if, `{% if expression %}print-this{% endif %}` is equivalent to `{{ expresssion|then:\'print-this\' }}`.\n- `ifnot`: Use a shorthand for if not, `{% if not expression %}print-this{% endif %}` is equivalent to `{{ expresssion|ifnot:\'print-this\' }}, and can be concatenated with then, like in: `{{ expression|then:\'positive\'|ifnot:\'negative\' }}`\n- `eq`: Compares its arguments and returns `"yes"` or empty string, `{{ this_thing|qe:other_other|then:\'print-this\' }}`.\n\n### `reactor.component` module\n\n- `Component`: This is the base component you should extend.\n- `AuthComponent`: Extends `Component` and ensures the user is logged in.\n- `broadcast(*names)`: Broadcasts the given names too all the system.\n- `on_commit(function)(*args, **kwargs)`: Calls `function` with the given arguments after database commit. \n\n#### Component API\n\n- `template_name`: Set the name of the template of the component.\n- `extends`: Tag name HTML element the component extends.\n- `serialize`: Should returns a dictionary with the persistent state of the component (stored in the front-end) so when the components is connects to the back-end (or reconnects) that state can be recreated, By default serializes just the `id` of the component, and the `id` should always be serialized.\n- `mount(**kwargs)`: Loads the initial state of the component when is rendered from the back-end or it reconnects from the front-end (using the information created by `serialize`), it is also called in case a subscription of the component is triggered.\n- `subscribe(*names)`: Subscribes the current component to the given signal names, when one of those signals is broadcasted the component is refreshed, meaning that `mount` is called passing the result `serialize` and the component is re-rendered.\n- `send_redirect(url, *args, **kwargs )`: Resolves the `url`, and instructs the front-end to redirect to that `url`.\n- `send_destroy()`: Removes the component from the interface.\n- `send(_name, id=None, **kwargs)`: Sends a message with the name `_name` to the component with `id`, if `id` is `None` the message is sent to the current component.\n- `send_parent(_name, kwargs)`: Sends a message with the name `_name` to the parent component.\n\n\n#### AuthComponent API\n\nThis component ensures the user is logged in or redirects the user to the login screen; when using this component and overriding `mount` make sure to call the support mount first.\n\n- `mount(**kwargs)`: Same as before, but returns `True` if the user is logged in.\n- `user`: the current logged-in user.\n\n## Front-end APIs\n\n- `reactor.push_state(url)`: pulls the next page from the backend with a get request, and applies it to the current page.\n- `reactor.send(element, event_name, args)`: send the event `event_name` with the `args` parameters to the HTML `element`. It what is used to forward user event to the back-end.\n\n### Special HTMLElement attributes\n\n- `:keep`: Prevent the value of an input from being changed across renders.\n- `:override`: When an input is being updated and the user has the focus there reactor by default will not update the input field value (has if it had `:keep`), use `:override` to do otherwise.\n- `:once`: Reactor will render this element and children once, and never update it again.\n- `:focus`: Sets the focus on this element after an HTML update.\n\n### Event binding in the front-end\n\nLook at this:\n\n```html\n  <button @click.prevent="submit">Submit</button?>\n```\n\nThe format is `@<event>[.modifier][.modifier]="event_name[ {arg1: 1, arg2: \'2\'}]"`:\n\n- `event`: is the name of the HTMLElement event: `click`, `blur`, `change`, `keypress`, `keyup`, `keydown`...\n- `modifier`: can be concatenated after the event name and represent actions or conditions to be met before the event execution. This is very similar as [how VueJS does event binding](https://vuejs.org/v2/guide/events.html):\n  - `prevent`: calls `event.preventDefault();`\n  - `stop`: calls (`event.stopPropagation();`), \n  - `enter`, `ctrl`, `alt`, `space`, expects any of those keys to be press.\n  - `inlinejs`: allows you to write your custom JavaScript in the event handler.\n  - `debounce`: the bounces the event, it needs a name and the delay in milliseconds. Example: `@keypress.100.search.debounce=\'message\'`. \n- `event_name`: is the name of the message to be send to this component\n- The arguments can be completely omitted, or specified as a dictionary. \n\nWhen the arguments are omitted reactor serializes the form where the current element is or the current component if no form is found, and sends that as the arguments. The arguments will be always sent with the `id` of the current component as a parameter.\n\n### JS Hooks\n\nThis are custom events triggered by reactor in different instants of the life cycle of the component.\n\n- `@reactor-init`: Triggered on any HTML element when the component is initialized.\n- `@reactor-added`: Triggered on any HTML element that is added to the DOM of the component.\n- `@reactor-updated`: Triggered on any HTML element that is updated, after the update happens.\n- `@reactor-leave`: Triggered on the root element when the element had been removed from the DOM.\n\n### Serialization\n\nSerialization of means to look at a chunk of HTML and extract the value of all elements with a `name` attribute in it. Reactor serialization supports nesting:\n\nNote on `contenteditable` elements, if they hava a name attribute they are serialized taking their inner HTML, if they have the special attribute `:as-text`, just their text is serialized.\n\n#### Example 1\n\n```html\n<input name="a" value="q">\n<input name="b" value="x">\n```\n\nResult: `{a: "q", b: "x"}`\n\n#### Example 2\n\n```html\n<input name="query" value="q">\n<input name="person.name" value="John">\n<input name="person.age" value="99">\n```\n\nResult: `{query: "q", person: {name: "John", value: "99"}}`\n\n#### Example 3\n\n```html\n<input name="query" value="q">\n<input name="persons[].name" value="a">\n<input name="persons[].name" value="b">\n```\n\nResult: `{query: "q", persons: [{name: "a"}, {name: "b"}]}`\n\n### Event handlers in the back-end\n\nGiven:\n\n```html\n<button @click="inc {amount: 2}">Increment</button?>\n```\n\nYou will need an event handler in that component in the back-end:\n\n```python\n def receive_inc(self, amount, **kwargs):\n    pass\n```\n\nAlways prefix the method name with `receice_` and add `**kwargs` at the end because more data is always sent to the component, like the component\'s own `id`.\n\n## Simple example of a counter\n\nIn your app create a template `x-counter.html`:\n\n```html\n{% load reactor %}\n<div {{ header }}>\n  {{ amount }}\n  <button @click="inc">+</button>\n  <button @click="dec">-</button>\n  <button @click="set_to {amount: 0}">reset</button>\n</div>\n```\n\nAnatomy of a template: each component should be a [custom web component](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) that inherits from [HTMLElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement). They should have an `id` so the backend knows which instance is this one and a `state` attribute with the necessary information to recreate the full state of the component on first render and in case of reconnection to the back-end.\n\nRender things as usually, so you can use full Django template language, `trans`, `if`, `for` and so on. Just keep in mind that the instance of the component is referred as `this`.\n\nForwarding events to the back-end: Notice that for event binding in-line JavaScript is used on the event handler of the HTML elements. How this works? When the increment button receives a click event `send(this, \'inc\')` is called, `send` is a reactor function that will look for the parent custom component and will dispatch to it the `inc` message, or the `set_to` message and its parameters `{amount: 0}`. The custom element then will send this message to the back-end, where the state of the component will change and then will be re-rendered back to the front-end. In the front-end `morphdom` (just like in Phoenix LiveView) is used to apply the new HTML.\n\nNow let\'s write the behavior part of the component in `live.py`:\n\n```python\nfrom reactor import Component\n\nclass XCounter(Component):\n\n    amount = None\n\n    # reference the template from above\n    template_name = \'x-counter.html\' \n\n    # A component is instantiated during normal rendering and when the component\n    # connects from the front-end. Then  __init__ is called passing `context` of\n    # creation (in case of HTML  rendering is the context of the template, in\n    # case of a WebSocket connection is the scope of django channels) Also the\n    # `id` is passed if any is provided, otherwise a `uuid4` is  generated on\n    # the fly.\n\n    # This method is called after __init__ passing the initial state of the \n    # Component, this method is responsible taking the state of the component\n    # and construct or reconstruct the component. Sometimes loading things from\n    # the database like tests of this project.\n    def mount(self, amount=0, **kwargs):\n        self.amount = amount\n\n    # This method is used to capture the essence of the state of a component\n    # state, so it can be reconstructed at any given time on the future.\n    # By passing what ever is returned by this method to `mount`.\n    def serialize(self):\n        return dict(id=self.id, amount=self.amount)\n\n    # This are the event handlers they always start with `receive_`\n\n    def receive_inc(self, **kwargs):\n        self.amount += 1\n\n    def receive_dec(self, **kwargs):\n        self.amount -= 1\n\n    def receive_set_to(self, amount, **kwargs):\n        self.amount = amount\n```\n\nLet\'s now render this counter, expose a normal view that renders HTML, like:\n\n\n```python\ndef index(request):\n    return render(request, \'index.html\')\n```\n\nAnd the index template being:\n\n```html\n{% load reactor %}\n<!doctype html>\n<html>\n  <head>\n     ....\n     {% reactor_header %}\n  </head>\n  <body>\n    {% component \'x-counter\' %}\n\n    <!-- or passing an initial state -->\n    {% component \'x-counter\' amount=100 %}    \n\n  </body>\n</html>\n```\n\nDon\'t forget to update your `urls.py` to call the index view.\n\n## More complex components\n\nI made a TODO list app using models that signals from the model to the respective channels to update the interface when something gets created, modified or deleted.\n\nThis example contains nested components and some more complex interactions than a simple counter, the app is in the `/tests/` directory.\n\n\n## Development & Contribution\n\nClone the repo and create a virtualenv or any other contained environment, get inside the repo directory, build the development environment and the run tests.\n\n```bash\ngit clone git@github.com:edelvalle/reactor.git\ncd reactor\nmake install\nmake test\n```\n\nIf you wanna run the inside Django project that is used for testing do:\n\n```bash\nmake\ncd tests\npython manage.py runserver\n```\n\nEnjoy!\n',
    'author': 'Eddy Ernesto del Valle Pino',
    'author_email': 'eddy@edelvalle.me',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/edelvalle/reactor',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.6,<4',
}


setup(**setup_kwargs)
