Metadata-Version: 2.4
Name: splent_feature_survey
Version: 0.2.0
License-Expression: LGPL-3.0-or-later
Requires-Python: >=3.13
Description-Content-Type: text/markdown
License-File: COPYING
License-File: COPYING.LESSER
Requires-Dist: splent_framework>=1.20.0
Dynamic: license-file

# splent_feature_survey

The `survey` feature of a [SPLENT](https://splent.io) product line.

Native questionnaires. The panel builds a survey out of questions (a scale
between two bounds, short or long text, single or multiple choice, yes or no,
an email address), visitors fill it at `/survey/<slug>` without an account,
and the panel reads the answers back, counted per option and averaged for a
scale. An unpublished survey answers 404 to everyone but the panel's
accounts, who preview it with a notice that it is a draft, and nobody can
answer it. A survey whose `closes_at` has passed says it is closed and takes
no more answers. The introduction and the thank you text are stored HTML,
and the form, its preview and the thank you page draw them through the
framework's `rich_text` filter, which keeps the formatting and drops
scripts, event handlers and `javascript:` links. It needs `auth`.

A SPLENT feature is a Python package that a product composes with others.
Its models, routes, services, templates and hooks are registered when the
product starts. What this feature provides and requires is listed in the
`[tool.splent.contract]` section of `pyproject.toml`, which
`splent feature:contract --write` keeps in sync with the source.

## Access

The screens under `/admin/surveys` and `/admin/questions`, where the surveys
are built, changed and deleted and their answers are read, open for the
accounts whose role is `admin` or `staff`, the same pair the admin dashboard
lets in. Any other signed-in account gets 403 and does not see the Surveys
link in the sidebar, and an anonymous visitor is sent to log in. The answers
hold whatever the respondents typed, email addresses included, so only the
panel reads them.

The form of a published survey at `/survey/<slug>` stays open to everyone,
signed in or not. An unpublished survey opens there only to the accounts the
admin screens let in, as a preview with a notice that it is a draft and the
submit button disabled, and nobody can answer it. Everyone else gets 404, as
for a survey that does not exist.

There is no setting for these roles, and a refinement cannot replace the
views that check them, because it may add routes to this feature but never
replace one of its own. Another feature can decide for these screens with an
access policy registered for the prefix `survey.admin`
(`register_access_policy`, splent_framework 1.20.0). The framework asks the
policy before the roles. It answers True to let an account in, False to
refuse it, or None to leave the decision to the roles, and the sidebar link
and the preview of an unpublished survey follow the same answer. For the
preview the policy is asked about `survey.admin_index` with the survey's
slug as `view_args`, `{"slug": "<slug>"}`, so it can let an account preview
some surveys and not others. That is the way to let a group of accounts
manage only this section, for example the people who run the
questionnaires, without giving them a panel role.
See [Access control](https://docs.splent.io/framework/access-control).

Without such a feature, give the person's account the staff role. Staff
opens every panel screen that asks for `PANEL_ROLES`, not only this one, so
a person who should run nothing but the surveys needs a policy instead.

```bash
splent feature:auth set-role someone@example.com staff
```

## Use it in a product

```bash
splent feature:add splent_feature_survey
```

## Develop

```bash
splent feature:test splent_feature_survey
splent feature:contract splent_feature_survey
```

## Release

```bash
splent feature:release splent_feature_survey --dry-run --bump patch
splent feature:release splent_feature_survey
```

The first command rehearses the release and changes nothing. The second
publishes it to the git forge and to PyPI, and a PyPI version is permanent.
