.. ==================================================
.. Header hierarchy
.. ==
.. --
.. ^^
.. ""
.. ;;
.. ,,
..
.. --------------------------------------------used to the update the records specified ------
.. Best Practice T3 reST: https://docs.typo3.org/m/typo3/docs-how-to-document/master/en-us/WritingReST/CheatSheet.html
.. Reference: https://docs.typo3.org/m/typo3/docs-how-to-document/master/en-us/WritingReST/Index.html
.. Italic *italic*
.. Bold **bold**
.. Code ``text``
.. External Links: `Bootstrap `__
.. Internal Link: :ref:`downloadButton` (default url text) or :ref:`Download Button` (explicit url text)
.. Anker for internal link: .. _`download`:
.. Add Image: .. image:: ./Images/a4.jpg
..
.. Add image with caption: .. figure:: ./Images/black_dot.png
.. :class: with-border
.. :width: 20px
.. Add Attachment (place in Documentation/_static): `Download CSV <_static/yourfile.csv>`__
..
.. Admonitions
.. .. note:: .. important:: .. tip:: .. warning::
.. Color: (blue) (orange) (green) (red)
..
.. Definition:
.. some text becomes strong (only one line)
.. description has to indented
..
.. Code Block: .. code-block:: sql
..
.. -*- coding: utf-8 -*- with BOM.
.. include:: Includes.txt
.. _`issue`:
Issue
=====
The **Issue** feature is a ticket management tool integrated within the QFQ framework. It handles issue tracking, permissions, notifications, and comment management.
How to get started
------------------
* Create a new page in your Typo3 backend.
* Set the ‘URL slug’ to ``/issue``.
* Create a content element of type 'QFQ Element'.
* Insert ``file=_issue``.
Configuration
-------------
To use the Issue feature, the following configuration steps are required:
Database tables
^^^^^^^^^^^^^^^
Ensure the following tables exist in your database:
* ``Grp``: Must include records with the following references:
* ``qfq_project_access_write``
* ``qfq_project_access_read``
* ``qfq_project_access_admin``
* ``qfq_upload_issue``
* ``qfq_upload_comment``
* ``qfq_upload_commentNew``
* ``qfq_status_issue``
* ``qfq_tag_issue``
* ``Project``
* ``Status``
* ``Comment``
* ``FileUpload``
* ``Issue``
System store variables
^^^^^^^^^^^^^^^^^^^^^^
Define the following variables in the **SYSTEM-STORE** (Dynamic/Custom) via QFQ configuration:
* ``pIdUser``: ID of the current user
* ``emailUser``: Email of the current user
* ``personTableName``: Table name for person records
* ``personFirstNameColumnName``: First name column in person table
* ``personLastNameColumnName``: Last name column in person table
* ``personEmailColumnName``: Email column in person table
* ``issueMailNotificationInterval`` *(optional)*: Notification delay interval in minutes (default: 2)
* ``issueWebsocketMessage`` *(optional)*: Message for form parameter ``message`` (websocket)
.. important::
The variables ``personTableName``, ``personFirstNameColumnName``, ``personLastNameColumnName`` and ``personEmailColumnName`` are always used together in the same query. Therefore, all referenced columns must exist in the specified table.
If your setup stores this information across multiple tables (e.g., email in a separate table), it is recommended to create a **database view** that consolidates all required fields into a single table-like structure.
Example::
CREATE VIEW PersonIssueView AS
SELECT p.id AS id
, p.firstName AS firstName
, p.lastName AS lastName
, ad.email AS email
FROM (Person AS p, Grp AS gr)
LEFT JOIN Address AS ad
ON ad.pId = p.id
AND ad.grId = gr.id
WHERE gr.reference = 'hr-addressWork'
AND ad.email != ''
GROUP BY p.id
Use
---
The core interface is accessible via the report at ``/issue``.
Functionality
^^^^^^^^^^^^^
* Displays a table of issues the current user has permission to access
* Fully filterable and sortable using *tablesorter*
* Can be embedded for integrations (:ref:`integration`)
Filter parameters
^^^^^^^^^^^^^^^^^
Issues can be filtered by passing parameters to the ``/issue`` page using either **SIP** or a **QFQ function** (see :ref:`embedded-view`).
Each parameter corresponds to a column in the ``Issue`` table and is applied as part of the query filter.
* By default, all parameters use the ``=`` operator.
* **Exceptions**:
* ``sea``: Applies a ``LIKE`` filter on both the ``title`` and ``description`` columns.
* ``tag``: Uses ``FIND_IN_SET()`` to filter tags stored in the ``Grp`` table.
* ``rem``: Filters for issues with overdue reminders. The actual value is ignored; the presence of the parameter triggers the check.
This mechanism allows for precise filtering when embedding issue views or linking to pre-filtered results.
+-----------+----------------------------------+
| Parameter | Column |
+===========+==================================+
| pro | prId |
+-----------+----------------------------------+
| sta | stId |
+-----------+----------------------------------+
| xid | xId |
+-----------+----------------------------------+
| fid | formId |
+-----------+----------------------------------+
| fna | formName |
+-----------+----------------------------------+
| cre | pIdCreator |
+-----------+----------------------------------+
| ass | pIdAssignee |
+-----------+----------------------------------+
| con | pIdContact |
+-----------+----------------------------------+
| mco | mailContact |
+-----------+----------------------------------+
| mws | mailWatcherSet |
+-----------+----------------------------------+
| mns | mailNotificationSet |
+-----------+----------------------------------+
| mno | mailNotification |
+-----------+----------------------------------+
| tit | title |
+-----------+----------------------------------+
| des | description |
+-----------+----------------------------------+
| str | start |
+-----------+----------------------------------+
| due | due |
+-----------+----------------------------------+
| del | deleted |
+-----------+----------------------------------+
| sea | title, description (LIKE) |
+-----------+----------------------------------+
| tag | Grp.name (FIND_IN_SET()) |
+-----------+----------------------------------+
| rem | reminder (< NOW() AND != "0") |
+-----------+----------------------------------+
.. note::
The default value for the ``del`` parameter is ``no``, meaning deleted issues are hidden unless explicitly requested.
Additional parameters
^^^^^^^^^^^^^^^^^^^^^
When using the embedded view or linking directly to ``/issue``, additional parameters can be passed to customize functionality and content filtering.
+-----------+-------------------------------+--------------------------------+-----------------------------------------------------------------+
| Parameter | Description | Value | Default |
+===========+===============================+================================+=================================================================+
| tso | Enable or disable tablesorter | ``yes``/``no`` | ``yes`` |
+-----------+-------------------------------+--------------------------------+-----------------------------------------------------------------+
| col | Displayed columns | Comma separated column headers | ``Project,Status,Title,Description,Assignee,Start,Due,Updated`` |
+-----------+-------------------------------+--------------------------------+-----------------------------------------------------------------+
| dnd | Drag and drop for table rows | ``yes``/``no`` | ``no`` |
+-----------+-------------------------------+--------------------------------+-----------------------------------------------------------------+
.. note::
When the ``dnd`` parameter is enabled, the CSS class ``table-draggable`` is added to the table.
Each table row will include the following attributes:
* ``id``: A combination of a random string and the record’s ``id``.
* ``data-record-id``: The record's ``id``.
* ``data-drop-zone-table-origin``: The name of the source table (e.g., ``Issue``).
These attributes enable JavaScript-based actions on records, such as closing an issue by dragging it into a designated drop zone and triggering an API call.
**Security Note:**
The ``id`` attribute is visible to the user, meaning API calls could be manipulated by replacing it with one the user is not authorized to access.
Always validate user permissions on the server side to prevent unauthorized changes.
Additionally, it is recommended to use **SIP** when possible — for example, in the drop zone — to obfuscate actions, involved tables, ids, and other sensitive data.
Form: issue
-----------
Most fields in this form are self-explanatory, but the following may require additional context:
* **Status**: Dropdown listing all records from the ``Status`` table where ``grId = qfq_status_issue``
* **Project**: Dropdown listing all records from the ``Project`` table
* **Assignee**: TypeAhead input listing all users with permissions on the selected project
* **Creator**: TypeAhead input listing all users. Only visible to users logged into the Typo3 backend or users with admin permissions on the selected project
* **Tags**: TypeAheadTag input listing all existing tags. A new tag is created automatically if no match is found
* **Contact person**: TypeAhead input listing all users
* **Contact person mail**: Optional email address when the contact person is not in the database
* **Watcher mail (list)**: Comma-separated list of email addresses
* **Notification**: See :ref:`notification`
* **Comment**: See :ref:`comments`
.. important::
QFQ provides Forms for configuring **Status** and **Project** via the Form definitions ``status.json`` and ``project.json``.
The ``issue.json`` Form includes buttons that link to the corresponding management pages at ``/status`` and ``/project``. These pages must be created manually in the **Typo3 backend**. On each page, add the necessary content to display the respective records incl. links to the mentioned Forms for editing.
Permissions
-----------
Access Control
^^^^^^^^^^^^^^
Access is automatically managed by QFQ:
1. **Project-Based Access**
Users gain access to issues by being assigned permissions on a project (the issue belongs to) via the ``Glue`` table. Available permission levels:
+--------+--------------------------+-----------------------------------------+
| Level | Reference | Description |
+========+==========================+=========================================+
| Write | qfq_project_access_write | View, create, edit, delete |
+--------+--------------------------+-----------------------------------------+
| Read | qfq_project_access_read | View only |
+--------+--------------------------+-----------------------------------------+
| Admin | qfq_project_access_admin | Like Write + extra options in form |
+--------+--------------------------+-----------------------------------------+
2. **Contact/Watcher-Based Access**
Even without project permissions, users may access an issue if they are:
* Listed as a **contact person** or **watcher**
* And **access contact/watcher** is enabled
Additional rules
^^^^^^^^^^^^^^^^
* **Creators** of an issue or comment always have access
* **Unassigned issues** (no project) can be accessed only by:
* The creator
* The assignee
* The contact person (if allowed)
* The watcher (if allowed)
.. _comments:
Comments
--------
There are two ways a user can add a comment to an issue:
1. **Edit Issue**
When editing an existing issue, a ``Comment`` tab (pill) is available. This allows users to add a new comment along with its permissions.
This method is ideal when the user needs to update the issue and leave a comment simultaneously — for example, when closing an issue and providing a reason.
2. **New Comment**
Use this option when no changes to the issue itself are required and only a comment needs to be added.
Each comment can have specific permissions:
* Comments can be restricted from **contact person** and **watchers**
* A badge beside the edit button indicates if a comment is restricted or not
.. _notification:
Notification
------------
The notification mechanism allows to alert involved parties via email when changes are made to an issue.
Recipients:
* Creator
* Contact person
* Watchers
* Assignee
Behavior:
* Upon saving an issue/comment, a timestamp (+2 minutes) is added if recipients are selected
* This 2-minute delay allows batching of quick consecutive changes
* If all recipients are removed, the timestamp is reset to ``0000-00-00 00:00:00``
.. note::
Use a cron job to regularly check timestamps and dispatch emails.
.. _integration:
Integration
-----------
Issue linked to a specific record
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Issues can be linked to a specific record (and form) by enabling the ``issue`` option under **Show button** in the form editor of the primary form.
When this option is enabled:
* An **Issue** button appears on the form
* The button displays the number of issues associated with the current record, including how many are still open
* Clicking the button redirects the user to ``/issue``
* When creating a new issue from this view, it is automatically assigned to the originating record (``xId``) and form (``formId``)
Link to filtered view
^^^^^^^^^^^^^^^^^^^^^
To create a link to the ``/issue`` page with pre-defined filters, use ``SIP`` to include parameters.
Example::
{
sql = SELECT 'p:/issue?ass=1&pro=1|s' AS _link
}
This generates a secure, parameterized link to the issue list, filtered by the specified parameters.
.. _embedded-view:
Embedded view
^^^^^^^^^^^^^
The ``/issue`` page can also be embedded using a **QFQ function**, which is especially useful for dashboards or integrating views in custom layouts.
.. important::
A **subheader** must be defined for ``/issue``, and the variable containing the query string **must** be set in the **RECORD-STORE** under the name ``queryString``.
Example::
{
sql = SELECT 'ass=1&pro=1' AS _queryString
}
{
function = issue(queryString)
sql = SELECT '{{_output:RE}}'
}
This renders the filtered issue list within another QFQ-managed page using the specified parameters.
Deleting issues/comments
------------------------
Issues and comments are never physically deleted; instead, they are marked as deleted by setting ``deleted = yes``.