Welcome | Get started | Dive into Lino | Contribute | Topics | Reference | More
About rendering action URLs¶
This document is about the is_on_main_actor
attribute of an action
request.
This page is a tested document and the following instructions are used for initialization:
>>> 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 #1 in the team demo. Here is how this window looks in ExtJS:
The "Sessions" panel in this screen (the SessionsByTicket
slave table, which has its
display_mode
set to 'summary')
shows that three 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 of SessionsByTicket
adds the total duration and a list of
the active sessions. In case you wonder how this summary is being generated,
please consult the source code.
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
non-window custom action. Such an action has no parameters and therefore does
not open any popup window before executing, so 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=9)
Here is how to simulate the content of this panel in a doctest.
>>> ses = rt.login('robin')
>>> ses.show(A, obj)
Total 68:49 hours.
Active sessions: `Luc since 09:00:00 <Detail>`__ **■**
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 68:49 hours.</p><p>Active sessions: <span><a
href="javascript:Lino.working.SessionsByTicket.detail.run(null,{
"base_params": { "mk": 9, "mt": 44 },
"param_values": { "company": null,
"companyHidden": null, "end_date": null,
"observed_event": "Is active",
"observed_eventHidden": "20", "session_type":
null, "session_typeHidden": null, "site": null,
"siteHidden": null, "start_date": null, "ticket":
"#9 (Foo never matches Bar)", "ticketHidden": 9,
"user": null, "userHidden": null }, "record_id":
1580 })" style="text-decoration:none">Luc since 09:00:00</a> <a
href="javascript:Lino.working.Sessions.end_session(null,false,1580,{
"base_params": { }, "param_values": { "company":
null, "companyHidden": null, "end_date": null,
"observed_event": "Is active",
"observed_eventHidden": "20", "session_type":
null, "session_typeHidden": null, "site": null,
"siteHidden": 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 68:49 hours.</p><p>Active sessions: <span><a
href="javascript:Lino.working.Sessions.detail.run(null,{
"base_params": { }, "param_values": {
"assigned_to": null, "assigned_toHidden": null,
"end_date": null, "end_user": null,
"end_userHidden": null, "has_ref": null,
"has_refHidden": null, "has_site": null,
"has_siteHidden": null, "interesting_for": null,
"interesting_forHidden": null, "last_commenter": null,
"last_commenterHidden": null, "not_assigned_to": null,
"not_assigned_toHidden": null, "not_last_commenter": null,
"not_last_commenterHidden": null, "observed_event": null,
"observed_eventHidden": null, "priority": null,
"show_active": null, "show_activeHidden": null,
"show_assigned": null, "show_assignedHidden": null,
"show_private": null, "show_privateHidden": null,
"show_todo": null, "show_todoHidden": null,
"site": null, "siteHidden": null, "start_date":
null, "state": null, "stateHidden": null,
"user": null, "userHidden": null }, "record_id":
1580 })" style="text-decoration:none">Luc since 09:00:00</a> <a
href="javascript:Lino.working.Sessions.end_session(null,false,1580,{
"base_params": { }, "param_values": { "company":
null, "companyHidden": null, "end_date": null,
"observed_event": "Is active",
"observed_eventHidden": "20", "session_type":
null, "session_typeHidden": null, "site": null,
"siteHidden": 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.Sessions.detail.run(null,{ "base_params": { }, "param_values": { "assigned_to": null, "assigned_toHidden": null, "end_date": null, "end_user": null, "end_userHidden": null, "has_ref": null, "has_refHidden": null, "has_site": null, "has_siteHidden": null, "interesting_for": null, "interesting_forHidden": null, "last_commenter": null, "last_commenterHidden": null, "not_assigned_to": null, "not_assigned_toHidden": null, "not_last_commenter": null, "not_last_commenterHidden": null, "observed_event": null, "observed_eventHidden": null, "priority": null, "show_active": null, "show_activeHidden": null, "show_assigned": null, "show_assignedHidden": null, "show_private": null, "show_privateHidden": null, "show_todo": null, "show_todoHidden": null, "site": null, "siteHidden": null, "start_date": null, "state": null, "stateHidden": null, "user": null, "userHidden": null }, "record_id": 1580 })
javascript:Lino.working.Sessions.end_session(null,false,1580,{ "base_params": { }, "param_values": { "company": null, "companyHidden": null, "end_date": null, "observed_event": "Is active", "observed_eventHidden": "20", "session_type": null, "session_typeHidden": null, "site": null, "siteHidden": null, "start_date": null, "ticket": null, "ticketHidden": null, "user": null, "userHidden": null } })