Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More

tickets in Noi

The lino_noi.lib.tickets plugin extends lino_xl.lib.tickets to make it collaborate with lino_noi.lib.working.

In Lino Noi the site of a ticket also indicates “who is going to pay” for our work. Lino Noi uses this information when generating a service report.

This page contains code snippets (lines starting with >>>), which are being tested during our development workflow. The following snippet initializes the demo project used throughout this page.

>>> from lino_book.projects.noi1e.startup import *

Tickets

Here is a textual description of the fields and their layout used in the detail window of a ticket.

>>> from lino.utils.diag import py2rst
>>> print(py2rst(tickets.AllTickets.detail_layout, True))
...
(main) [visible for all]:
- **General** (general_tab_1):
  - **None** (overview)
  - (general3):
    - (general3_1): **Workflow** (workflow_buttons), **Assign to** (quick_assign_to) [visible for developer admin]
    - **Comments** (comments.CommentsByRFC)
- **Request** (post_tab_1):
  - (post1):
    - (post1_1): **ID** (id), **Author** (user)
    - **Summary** (summary)
    - **Description** (description)
  - (post2):
    - (post2_1): **Subscription** (order), **End user** (end_user)
    - (post2_2): **Confidential** (private), **Urgent** (urgent)
    - **Upload files** (uploads.UploadsByController) [visible for customer contributor developer admin]
- **Triage** (triage_tab_1):
  - (triage1):
    - (triage1_1): **Team** (group), **Ticket type** (ticket_type)
    - **Parent** (parent)
    - **Children** (tickets.TicketsByParent)
  - (triage2): **Assign to** (quick_assign_to) [visible for developer admin], **Add tag** (add_tag), **Tags** (topics.TagsByOwner) [visible for customer contributor developer admin]
- **Work** (work_tab_1):
  - (work1):
    - **Workflow** (workflow_buttons)
    - (work1_2): **Priority** (priority), **My nickname** (my_nickname)
    - **Mentioned in** (comments.CommentsByMentioned)
  - (work2):
    - **Working sessions** (working.SessionsByTicket) [visible for contributor developer admin]
    - (work2_2): **Regular** (regular_hours), **Free** (free_hours)
- **More** (more_tab_1):
  - (more1):
    - (more1_1): **Created** (created), **Modified** (modified)
    - **Reference** (ref)
    - **Resolution** (upgrade_notes)
  - (more2):
    - (more2_1): **State** (state), **Assigned to** (assigned_to)
    - (more2_2): **Planned time** (planned_time), **Deadline** (deadline)
    - **Duplicate of** (duplicate_of)
    - **Duplicates** (tickets.DuplicatesByTicket)
class lino_noi.lib.tickets.Ticket

The Django model used to represent a ticket in Noi. Adds some fields and methods.

assigned_to

The user who is working on this ticket.

site

The site this ticket belongs to. You can select only sites you are subscribed to.

Screenshots

../../_images/tickets.Ticket.merge.png

The life cycle of a ticket

In Lino Noi we use the default tickets workflow defined in lino_xl.lib.tickets.TicketStates.

Subscriptions

The Ticket.order field in Noi points to a lino_xl.lib.subscriptions.Subscription.

>>> rt.show(subscriptions.Subscriptions)
==== ============ =========== ===================== ========= ================
 ID   Start date   Reference   Partner               Subject   Workflow
---- ------------ ----------- --------------------- --------- ----------------
 1    07/01/2014   welket      Rumma & Ko OÜ                   **Registered**
 2    27/01/2014   welsch      Bäckerei Ausdemwald             **Registered**
 3    16/02/2014   aab         Bäckerei Mießen                 **Registered**
 4    08/03/2014   bcc         Bäckerei Schmitz                **Registered**
 5    28/03/2014   dde         Garage Mergelsberg              **Registered**
==== ============ =========== ===================== ========= ================

Ticket types

The demo fixture defines the following ticket types.

>>> rt.show(tickets.TicketTypes)
============= ================== ================== ================
 Designation   Designation (de)   Designation (fr)   Reporting type
------------- ------------------ ------------------ ----------------
 Bugfix        Bugfix             Bugfix             Regular
 Enhancement   Enhancement        Enhancement        Regular
 Upgrade       Upgrade            Upgrade            Regular
 Regression    Regression         Regression         Free
============= ================== ================== ================

Deciding what to do next

Show all active tickets reported by me.

>>> rt.login('marc').get_user().user_type
<users.UserTypes.customer:100>

Marc is a customer, so he has permission to modify the workflow state of his own tickets but not of those owned by other users. He can have tickets to do, i.e. that are assiged to him.

TODO: The following 2 snippets are skipped because MyTicketsToWork sorts on [“-priority”, “-modified”], and the value of modified is unreliable. Seems that it gets modified by some other test cases, which is not detected by lino.utils.dbhash.check_virgin().

>>> rt.login('marc').show(tickets.MyTicketsToWork, max_width=40, display_mode="grid")
...
+----------+------------------------------------------+------------------------------------------+
| Priority | Ticket                                   | Workflow                                 |
+==========+==========================================+==========================================+
| 50       | `#2 (Bar is not always baz) <…>`__ ( 50  | **🗪 Talk** → [⚹] [☾] [☉] [⚒] [☐] [☑] [☒] |
|          | by `Marc <…>`__ in `Sales team <…>`__    | [⧖]                                      |
|          | assigned to `Marc <…>`__)                |                                          |
+----------+------------------------------------------+------------------------------------------+
| 50       | `#11 (Class-based Foos and Bars?) <…>`__ | **🗪 Talk**                               |
|          | ( 50 by `Rolf Rompen <…>`__ in `Sales    |                                          |
|          | team <…>`__ assigned to `Marc <…>`__)    |                                          |
+----------+------------------------------------------+------------------------------------------+
| 30       | `#92 (Why <p> tags are so bar) <…>`__    | **🗪 Talk** → [⚹] [☾] [☉] [⚒] [☐] [☑] [☒] |
|          | (by `Marc <…>`__ in `Sales team <…>`__   | [⧖]                                      |
|          | assigned to `Marc <…>`__)                |                                          |
+----------+------------------------------------------+------------------------------------------+
| 30       | `#74 (Bar cannot baz) <…>`__ (by `Marc   | **🗪 Talk** → [⚹] [☾] [☉] [⚒] [☐] [☑] [☒] |
|          | <…>`__ in `Sales team <…>`__ assigned to | [⧖]                                      |
|          | `Marc <…>`__)                            |                                          |
+----------+------------------------------------------+------------------------------------------+
| 30       | `#83 (Misc optimizations in Baz) <…>`__  | **🗪 Talk**                               |
|          | (by `Rolf Rompen <…>`__ in `Sales team   |                                          |
|          | <…>`__ assigned to `Marc <…>`__)         |                                          |
+----------+------------------------------------------+------------------------------------------+
| 30       | `#20 (Why <p> tags are so bar) <…>`__    | **🗪 Talk** → [⚹] [☾] [☉] [⚒] [☐] [☑] [☒] |
|          | (by `Marc <…>`__ in `Sales team <…>`__   | [⧖]                                      |
|          | assigned to `Marc <…>`__)                |                                          |
+----------+------------------------------------------+------------------------------------------+
>>> rt.login('jean').show(tickets.MyTickets, max_width=30, display_mode="grid")
...
+----------+--------------------------------+-------------+--------------------------------+
| Priority | Ticket                         | Assigned to | Workflow                       |
+==========+================================+=============+================================+
| 50       | `#12 (Foo cannot bar) <…>`__ ( | Robin Rood  | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | 50 in `Developers <…>`__       |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | assigned to `Robin Rood        |             |                                |
|          | <…>`__) [▶] **☉ Open** → [⚹]   |             |                                |
|          | [☾] [🗪] [⚒] [☐] [☑] [☒] [⧖]    |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 40       | `#3 (Baz sucks) <…>`__ ( 40 in | Jean        | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | `Developers <…>`__ assigned to |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | `Jean <…>`__) [▶] **☉ Open** → |             |                                |
|          | [⚹] [☾] [🗪] [⚒] [☐] [☑] [☒]    |             |                                |
|          | [⧖]                            |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#111 (Bars have no foo)       | Jean        | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | <…>`__ (in `Developers <…>`__  |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | assigned to `Jean <…>`__) [▶]  |             |                                |
|          | **☉ Open** → [⚹] [☾] [🗪] [⚒]   |             |                                |
|          | [☐] [☑] [☒] [⧖]                |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#102 (No more foo when bar is | Mathieu     | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | gone) <…>`__ (in `Developers   |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | <…>`__ assigned to `Mathieu    |             |                                |
|          | <…>`__) [▶] **☉ Open** → [⚹]   |             |                                |
|          | [☾] [🗪] [⚒] [☐] [☑] [☒] [⧖]    |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#93 (Irritating message when  |             | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | bar) <…>`__ (in `Developers    |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | <…>`__) [▶] **☉ Open** → [⚹]   |             |                                |
|          | [☾] [🗪] [⚒] [☐] [☑] [☒] [⧖]    |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#84 (Default account in       | Robin Rood  | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | invoices per partner) <…>`__   |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | (in `Developers <…>`__         |             |                                |
|          | assigned to `Robin Rood        |             |                                |
|          | <…>`__) [▶] **☉ Open** → [⚹]   |             |                                |
|          | [☾] [🗪] [⚒] [☐] [☑] [☒] [⧖]    |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#75 (Bars have no foo) <…>`__ | Jean        | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | (in `Developers <…>`__         |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | assigned to `Jean <…>`__) [▶]  |             |                                |
|          | **☉ Open** → [⚹] [☾] [🗪] [⚒]   |             |                                |
|          | [☐] [☑] [☒] [⧖]                |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#66 (No more foo when bar is  | Mathieu     | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | gone) <…>`__ (in `Developers   |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | <…>`__ assigned to `Mathieu    |             |                                |
|          | <…>`__) [▶] **☉ Open** → [⚹]   |             |                                |
|          | [☾] [🗪] [⚒] [☐] [☑] [☒] [⧖]    |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#57 (Irritating message when  |             | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | bar) <…>`__ (in `Developers    |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | <…>`__) [▶] **☉ Open** → [⚹]   |             |                                |
|          | [☾] [🗪] [⚒] [☐] [☑] [☒] [⧖]    |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#48 (Default account in       | Robin Rood  | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | invoices per partner) <…>`__   |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | (in `Developers <…>`__         |             |                                |
|          | assigned to `Robin Rood        |             |                                |
|          | <…>`__) [▶] **☉ Open** → [⚹]   |             |                                |
|          | [☾] [🗪] [⚒] [☐] [☑] [☒] [⧖]    |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#39 (Bars have no foo) <…>`__ | Jean        | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | (in `Developers <…>`__         |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | assigned to `Jean <…>`__) [▶]  |             |                                |
|          | **☉ Open** → [⚹] [☾] [🗪] [⚒]   |             |                                |
|          | [☐] [☑] [☒] [⧖]                |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#30 (No more foo when bar is  | Mathieu     | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | gone) <…>`__ (in `Developers   |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | <…>`__ assigned to `Mathieu    |             |                                |
|          | <…>`__) [▶] **☉ Open** → [⚹]   |             |                                |
|          | [☾] [🗪] [⚒] [☐] [☑] [☒] [⧖]    |             |                                |
+----------+--------------------------------+-------------+--------------------------------+
| 30       | `#21 (Irritating message when  |             | [▶] **☉ Open** → [⚹] [☾] [🗪]   |
|          | bar) <…>`__ (in `Developers    |             | [⚒] [☐] [☑] [☒] [⧖]            |
|          | <…>`__) [▶] **☉ Open** → [⚹]   |             |                                |
|          | [☾] [🗪] [⚒] [☐] [☑] [☒] [⧖]    |             |                                |
+----------+--------------------------------+-------------+--------------------------------+

The backlog

The TicketsByOrder panel shows all the tickets for a given subscription. It is a scrum backlog.

>>> pypi = subscriptions.Subscription.objects.get(ref="welket")
>>> rt.login("robin").show(
...     tickets.TicketsByOrder, pypi, max_width=40, display_mode="grid")
...
+--------------------+------------------------------------------+--------------+------------+-----------+
| Priority           | Ticket                                   | Planned time | Regular    | Free      |
+====================+==========================================+==============+============+===========+
| 50                 | `#1 (Föö fails to bar when baz) <…>`__ ( |              | 34:44      |           |
|                    | 50 by `Luc <…>`__ in `Managers <…>`__)   |              |            |           |
|                    | [▶] **⚹ New** → [☾] [🗪] [☉] [⚒] [☐] [☑]  |              |            |           |
|                    | [⧖]                                      |              |            |           |
+--------------------+------------------------------------------+--------------+------------+-----------+
| 30                 | `#91 (Cannot delete foo) <…>`__ (by `Luc |              | 31:23      |           |
|                    | <…>`__ in `Managers <…>`__ assigned to   |              |            |           |
|                    | `Luc <…>`__) [▶] **⚹ New** → [☾] [🗪] [☉] |              |            |           |
|                    | [⚒] [☐] [☑] [⧖]                          |              |            |           |
+--------------------+------------------------------------------+--------------+------------+-----------+
| 30                 | `#83 (Misc optimizations in Baz) <…>`__  |              |            |           |
|                    | (by `Rolf Rompen <…>`__ in `Sales team   |              |            |           |
|                    | <…>`__ assigned to `Marc <…>`__) [▶] **🗪 |              |            |           |
|                    | Talk** → [⚹] [☾] [☉] [⚒] [☐] [☑] [☒] [⧖] |              |            |           |
+--------------------+------------------------------------------+--------------+------------+-----------+
| 30                 | `#76 (How to get bar from foo) <…>`__    |              |            | 34:05     |
|                    | (by `Romain Raffault <…>`__ in `Managers |              |            |           |
|                    | <…>`__ assigned to `Luc <…>`__) [▶] **⚒  |              |            |           |
|                    | Working** → [⚹] [☾] [🗪] [☉] [☐] [☑] [☒]  |              |            |           |
|                    | [⧖]                                      |              |            |           |
+--------------------+------------------------------------------+--------------+------------+-----------+
| 30                 | `#46 (How can I see where bar?) <…>`__   |              | 31:44      |           |
|                    | (by `Romain Raffault <…>`__ in `Managers |              |            |           |
|                    | <…>`__ assigned to `Romain Raffault      |              |            |           |
|                    | <…>`__) [▶] **⚹ New** → [☾] [🗪] [☉] [⚒]  |              |            |           |
|                    | [☐] [☑] [⧖]                              |              |            |           |
+--------------------+------------------------------------------+--------------+------------+-----------+
| 30                 | `#38 (Bar cannot baz) <…>`__ (by `Marc   |              |            |           |
|                    | <…>`__ in `Sales team <…>`__ assigned to |              |            |           |
|                    | `Rolf Rompen <…>`__) [▶] **🗪 Talk** →    |              |            |           |
|                    | [⚹] [☾] [☉] [⚒] [☐] [☑] [☒] [⧖]          |              |            |           |
+--------------------+------------------------------------------+--------------+------------+-----------+
| 30                 | `#31 (Cannot delete foo) <…>`__ (by `Luc |              | 32:22      |           |
|                    | <…>`__ in `Managers <…>`__ assigned to   |              |            |           |
|                    | `Romain Raffault <…>`__) [▶] **⚒         |              |            |           |
|                    | Working** → [⚹] [☾] [🗪] [☉] [☐] [☑] [☒]  |              |            |           |
|                    | [⧖]                                      |              |            |           |
+--------------------+------------------------------------------+--------------+------------+-----------+
| **Total (7 rows)** |                                          |              | **130:13** | **34:05** |
+--------------------+------------------------------------------+--------------+------------+-----------+

Filtering tickets

Lino Noi modifies the list of the parameters you can use for filtering tickets by setting a custom params_layout.

>>> show_fields(tickets.AllTickets, all=True)
...
- Author (user) : The author or reporter of this ticket. The user who reported this
  ticket to the database and is responsible for managing it.
- End user (end_user) : Only rows concerning this end user.
- Assigned to (assigned_to) : Only tickets with this user assigned.
- Not assigned to (not_assigned_to) : Only that this user is not assigned to.
- Interesting for (interesting_for) : Only tickets interesting for this partner.
- Subscription (order) : The business document used by both partners as reference for invoicing this ticket.
- State (state) : Only rows having this state.
- Assigned (show_assigned) : Show only (or hide) tickets that are assigned to somebody.
- Active (show_active) : Show only (or hide) tickets which are active (i.e. state is Talk
  or ToDo).
- To do (show_todo) : Show only (or hide) tickets that are todo (i.e. state is New
  or ToDo).
- Private (show_private) : Show only (or hide) tickets that are marked private.
- Date from (start_date) : Start of observed date range
- until (end_date) : End of observed date range
- Observed event (observed_event) :
- Has reference (has_ref) :
- Commented Last (last_commenter) : Only tickets that have this use commenting last.
- Not Commented Last (not_last_commenter) : Only tickets where this use is not the last commenter.

Change observers

A comment is a ChangeNotifier that forwards its owner’s change observers:

>>> ar = rt.login('robin')
>>> from lino.modlib.notify.mixins import ChangeNotifier
>>> # Uncomment to find pk of comments having a Group/Company as owner:
>>> # pprint({o.owner:o.pk for o in comments.Comment.objects.order_by('id')})
>>> obj = comments.Comment.objects.get(pk=322)
>>> obj.owner
Group #3 ('Sales team')
>>> isinstance(obj.owner, ChangeNotifier)
True
>>> list(obj.get_change_observers())
...
[(User #4 ('Marc'), <notify.MailModes.often:often>), (User #2 ('Rolf Rompen'),
<notify.MailModes.often:often>)]
>>> list(obj.get_change_observers()) == list(obj.owner.get_change_observers())
True

When the owner of a comment is not a ChangeNotifier, the comment has no change observers:

>>> obj = comments.Comment.objects.get(pk=7)
>>> obj.owner
Company #95 ('Number Three')
>>> isinstance(obj.owner, ChangeNotifier)
False
>>> list(obj.get_change_observers())
[]
>>> list(obj.owner.get_change_observers())
Traceback (most recent call last):
...
AttributeError: 'Company' object has no attribute 'get_change_observers'
>>> list(comments.Comment.objects.get(pk=155).get_change_observers())
...
[]

Don’t read on

>>> print(tickets.Ticket.objects.get(pk=45))
#45 (Irritating message when bar)
>>> test_client.force_login(rt.login('robin').user)
>>> def mytest(k):
...     url = '/api/tickets/Tickets/{}?dm=list&fmt=json&lv=1697917143.868&mjsts=1695264043.076&mk=0&pv=1&pv&pv&pv&pv&pv&pv&pv&pv&pv&pv&pv=24.10.2023&pv=24.10.2023&pv=10&pv&pv&pv&rp=weak-key-4&ul=en&wt=d'.format(k)
...     res = test_client.get(url)
...     print(res)
>>> settings.SITE.catch_layout_exceptions = True
>>> mytest("45")
Error during ApiElement.get(): Invalid request for '45' on tickets.Tickets (Unresolved value '10' (<class 'str'>) for tickets.TicketEvents (set Site.strict_choicelist_values to False to ignore this))
Unresolved value '10' (<class 'str'>) for tickets.TicketEvents (set Site.strict_choicelist_values to False to ignore this)
Traceback (most recent call last):
...
lino.core.exceptions.UnresolvedChoice: Unresolved value '10' (<class 'str'>) for tickets.TicketEvents (set Site.strict_choicelist_values to False to ignore this)
Not Found: /api/tickets/Tickets/45
<HttpResponseNotFound status_code=404, "text/html; charset=utf-8">
>>> settings.SITE.catch_layout_exceptions = False
>>> obj = tickets.Ticket.objects.get(pk=115)
>>> obj.state
<tickets.TicketStates.closed:50>
>>> url = f"/api/tickets/ActiveTickets/{obj.pk}?dm=detail&fmt=json"
>>> test_client.force_login(rt.login('robin').user)
>>> res = test_client.get(url)
>>> d = json.loads(res.content.decode())
>>> pprint(d)
{'alert': False,
 'message': 'Row 115 is not visible here.<br>But you can see it in <a '
            'href="javascript:Lino.tickets.Tickets.detail.run(null,{ '
            '&quot;base_params&quot;: {  }, &quot;param_values&quot;: { '
            '&quot;assigned_to&quot;: null, &quot;assigned_toHidden&quot;: '
            'null, &quot;end_date&quot;: null, &quot;end_user&quot;: null, '
            '&quot;end_userHidden&quot;: null, &quot;has_ref&quot;: null, '
            '&quot;has_refHidden&quot;: null, &quot;interesting_for&quot;: '
            'null, &quot;interesting_forHidden&quot;: null, '
            '&quot;last_commenter&quot;: null, '
            '&quot;last_commenterHidden&quot;: null, '
            '&quot;not_assigned_to&quot;: null, '
            '&quot;not_assigned_toHidden&quot;: null, '
            '&quot;not_last_commenter&quot;: null, '
            '&quot;not_last_commenterHidden&quot;: null, '
            '&quot;observed_event&quot;: null, '
            '&quot;observed_eventHidden&quot;: null, &quot;order&quot;: null, '
            '&quot;orderHidden&quot;: null, &quot;show_active&quot;: null, '
            '&quot;show_activeHidden&quot;: null, &quot;show_assigned&quot;: '
            'null, &quot;show_assignedHidden&quot;: null, '
            '&quot;show_private&quot;: null, &quot;show_privateHidden&quot;: '
            'null, &quot;show_todo&quot;: null, &quot;show_todoHidden&quot;: '
            'null, &quot;start_date&quot;: null, &quot;state&quot;: null, '
            '&quot;stateHidden&quot;: null, &quot;user&quot;: null, '
            '&quot;userHidden&quot;: null }, &quot;record_id&quot;: 115 })" '
            'style="text-decoration:none">Tickets</a>.',
 'success': False,
 'title': '<a href="javascript:Lino.tickets.ActiveTickets.grid.run(null,{ '
          '&quot;base_params&quot;: {  }, &quot;param_values&quot;: { '
          '&quot;assigned_to&quot;: null, &quot;assigned_toHidden&quot;: null, '
          '&quot;end_date&quot;: null, &quot;end_user&quot;: null, '
          '&quot;end_userHidden&quot;: null, &quot;has_ref&quot;: null, '
          '&quot;has_refHidden&quot;: null, &quot;interesting_for&quot;: null, '
          '&quot;interesting_forHidden&quot;: null, '
          '&quot;last_commenter&quot;: null, &quot;last_commenterHidden&quot;: '
          'null, &quot;not_assigned_to&quot;: null, '
          '&quot;not_assigned_toHidden&quot;: null, '
          '&quot;not_last_commenter&quot;: null, '
          '&quot;not_last_commenterHidden&quot;: null, '
          '&quot;observed_event&quot;: null, &quot;observed_eventHidden&quot;: '
          'null, &quot;order&quot;: null, &quot;orderHidden&quot;: null, '
          '&quot;show_active&quot;: &quot;Yes&quot;, '
          '&quot;show_activeHidden&quot;: &quot;y&quot;, '
          '&quot;show_assigned&quot;: null, &quot;show_assignedHidden&quot;: '
          'null, &quot;show_private&quot;: null, '
          '&quot;show_privateHidden&quot;: null, &quot;show_todo&quot;: null, '
          '&quot;show_todoHidden&quot;: null, &quot;start_date&quot;: null, '
          '&quot;state&quot;: null, &quot;stateHidden&quot;: null, '
          '&quot;user&quot;: null, &quot;userHidden&quot;: null } })" '
          'style="text-decoration:none">Active tickets</a>'}