Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
About rendering action URLs¶
This document is about the is_on_main_actor
attribute of an action
request.
Side note: Code snippets (lines starting with >>>
) in this document get
tested as part of our development workflow. The following
initialization snippet tells you which demo project is being used in
this document.
>>> from lino import startup
>>> startup('lino_book.projects.noi1e.settings.demo')
>>> from lino.api.doctest import *
Screenshot¶
This document uses the detail view of ticket #57 in the noi1e demo. Here is how this window looks in ExtJS (left) and in React (right):
The “Working sessions” panel in this screen shows that two users are currently working on this ticket. For each of these open sessions, you can either open the session itself (its detail window), or invoke its end_session action.
This summary panel is defined by the SessionsByTicket
table, which has its default
display mode set to ‘summary’. The summary is customized, it the total
durations and a list of active sessions. In case you wonder how this summary is
being generated, consult the source code of the table_as_summary
method of SessionsByTicket
.
Why we need is_on_main_actor
¶
When you render an action button, you get a clickable html element that, when clicked, executes a given action.
The lino_xl.lib.working.Session.end_session
action on a ticket is a
window-less custom action. Such an action has no parameters and therefore does
not open any popup window before executing. Clicking on such a button should
immediately execute it.
In ExtJS, these actions are implemented as global JS functions that just call
the global Lino.run_row_action function, which is defined in
linoweb.js
.
The action itself still runs on the server, so Lino.run_row_action sends an AJAX request.
That AJAX request needs to pass certain information that is available only in the JS client, e.g. the selected row, the requesting panel or the base parameters. But this should not happen (and would cause errors) for actions on a slave table.
We do not want Lino.run_row_action to add the parameter values of its
requesting panel when it is being run from within a “non-main context”. A
“non-main context” is for example in
lino.core.actors.Actor.slave_as_html_meth()
(i.e. when display_mode
is html
.
Note that currently we also don’t pass the mk
and mt
parameters (master
key and master type). I think that this is correct.
Let A be our slave table (an actor) and obj the master instance for this slave table.
>>> A = working.SessionsByTicket
>>> obj = tickets.Ticket.objects.get(pk=59)
Here is how to simulate the content of this panel in a doctest.
>>> ses = rt.login('robin')
>>> ses.show(A, obj)
Total 64:54 hours.
Active sessions: `Luc since 09:00:00 <…>`__ **■**
In order to look at the href links generated by a JavaScript renderer, we
simulate a web session by specifying the default renderer, which is an instance
of lino.modlib.extjs.ext_renderer.ExtRenderer
, a subclass of
lino.core.renderer.JsRenderer
.
>>> settings.SITE.kernel.default_renderer
<lino.modlib.extjs.ext_renderer.ExtRenderer object at ...>
>>> ses = rt.login('robin', renderer=settings.SITE.kernel.default_renderer)
Now the lino.core.requests.BaseRequest.show()
method no longer prints
plain text to the stdout but a HTML string:
>>> ses.show(A, obj)
'<div class="htmlText"><p>Total 64:54 hours.</p><p>Active sessions: <span><a
href="javascript:Lino.working.SessionsByTicket.detail.run(null,{
"base_params": { "mk": 59, "mt": 43 },
"param_values": { "company": null,
"companyHidden": null, "end_date": null,
"observed_event": "Is active",
"observed_eventHidden": "20", "session_type":
null, "session_typeHidden": null, "start_date": null,
"ticket": "#59 (Misc optimizations in Baz)",
"ticketHidden": 59, "user": null, "userHidden":
null }, "record_id": 1579 })" style="text-decoration:none">Luc since
09:00:00</a> <a
href="javascript:Lino.working.Sessions.end_session(null,false,1579,{
"base_params": { }, "param_values": { "company":
null, "companyHidden": null, "end_date": null,
"observed_event": "Is active",
"observed_eventHidden": "20", "session_type":
null, "session_typeHidden": null, "start_date": null,
"ticket": null, "ticketHidden": null, "user":
null, "userHidden": null } })" title="Tell Lino that you stop this
session for now. This will simply set the end_time to the current time."
style="text-decoration:none">■</a></span></p></div>'
>>> ses.is_on_main_actor
True
>>> ar = rt.models.tickets.Tickets.request(parent=ses)
>>> ar.is_on_main_actor
True
>>> ar.actor
lino_xl.lib.tickets.ui.Tickets
>>> # ar.request = 123
>>> html = A.get_table_summary(obj, ar)
The href links in this html must be javascript links, not external ones.
>>> print(tostring(html))
<div class="htmlText"><p>Total 64:54 hours.</p><p>Active sessions: <span><a
href="javascript:Lino.working.SessionsByTicket.detail.run(null,{
"base_params": { "mk": 59, "mt": 43 },
"param_values": { "company": null,
"companyHidden": null, "end_date": null,
"observed_event": "Is active",
"observed_eventHidden": "20", "session_type":
null, "session_typeHidden": null, "start_date": null,
"ticket": "#59 (Misc optimizations in Baz)",
"ticketHidden": 59, "user": null, "userHidden":
null }, "record_id": 1579 })" style="text-decoration:none">Luc since
09:00:00</a> <a
href="javascript:Lino.working.Sessions.end_session(null,false,1579,{
"base_params": { }, "param_values": { "company":
null, "companyHidden": null, "end_date": null,
"observed_event": "Is active",
"observed_eventHidden": "20", "session_type":
null, "session_typeHidden": null, "start_date": null,
"ticket": null, "ticketHidden": null, "user":
null, "userHidden": null } })" title="Tell Lino that you stop this
session for now. This will simply set the end_time to the current time."
style="text-decoration:none">■</a></span></p></div>
Let’s make this more readable:
>>> soup = BeautifulSoup(tostring(html), 'lxml')
>>> # print(soup.body.prettify())
>>> links = soup.body.find_all('a')
>>> len(links)
2
>>> for lnk in links:
... print(lnk['href'])
javascript:Lino.working.SessionsByTicket.detail.run(null,{ "base_params": { "mk": 59, "mt": 43 }, "param_values": { "company": null, "companyHidden": null, "end_date": null, "observed_event": "Is active", "observed_eventHidden": "20", "session_type": null, "session_typeHidden": null, "start_date": null, "ticket": "#59 (Misc optimizations in Baz)", "ticketHidden": 59, "user": null, "userHidden": null }, "record_id": 1579 })
javascript:Lino.working.Sessions.end_session(null,false,1579,{ "base_params": { }, "param_values": { "company": null, "companyHidden": null, "end_date": null, "observed_event": "Is active", "observed_eventHidden": "20", "session_type": null, "session_typeHidden": null, "start_date": null, "ticket": null, "ticketHidden": null, "user": null, "userHidden": null } })