vinta-django-questionnaires 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of vinta-django-questionnaires might be problematic. Click here for more details.
- vinta_django_questionnaires-0.1.0/.gitignore +25 -0
- vinta_django_questionnaires-0.1.0/CHANGELOG.md +182 -0
- vinta_django_questionnaires-0.1.0/LICENSE +21 -0
- vinta_django_questionnaires-0.1.0/PKG-INFO +728 -0
- vinta_django_questionnaires-0.1.0/README.md +691 -0
- vinta_django_questionnaires-0.1.0/example/README.md +90 -0
- vinta_django_questionnaires-0.1.0/example/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/example/admin.py +31 -0
- vinta_django_questionnaires-0.1.0/example/api.py +203 -0
- vinta_django_questionnaires-0.1.0/example/apps.py +11 -0
- vinta_django_questionnaires-0.1.0/example/manage.py +17 -0
- vinta_django_questionnaires-0.1.0/example/management/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/example/management/commands/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/example/management/commands/demo_response.py +217 -0
- vinta_django_questionnaires-0.1.0/example/management/commands/seed_example.py +818 -0
- vinta_django_questionnaires-0.1.0/example/migrations/0001_initial.py +49 -0
- vinta_django_questionnaires-0.1.0/example/migrations/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/example/models.py +36 -0
- vinta_django_questionnaires-0.1.0/example/questionnaire_validators.py +83 -0
- vinta_django_questionnaires-0.1.0/example/settings.py +73 -0
- vinta_django_questionnaires-0.1.0/example/urls.py +99 -0
- vinta_django_questionnaires-0.1.0/pyproject.toml +199 -0
- vinta_django_questionnaires-0.1.0/tests/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/tests/conftest.py +50 -0
- vinta_django_questionnaires-0.1.0/tests/manage.py +17 -0
- vinta_django_questionnaires-0.1.0/tests/settings.py +57 -0
- vinta_django_questionnaires-0.1.0/tests/test_admin.py +563 -0
- vinta_django_questionnaires-0.1.0/tests/test_api.py +350 -0
- vinta_django_questionnaires-0.1.0/tests/test_app.py +22 -0
- vinta_django_questionnaires-0.1.0/tests/test_definition.py +387 -0
- vinta_django_questionnaires-0.1.0/tests/test_editor_api.py +176 -0
- vinta_django_questionnaires-0.1.0/tests/test_integrations.py +562 -0
- vinta_django_questionnaires-0.1.0/tests/test_models.py +333 -0
- vinta_django_questionnaires-0.1.0/tests/test_openapi.py +162 -0
- vinta_django_questionnaires-0.1.0/tests/test_plan.py +246 -0
- vinta_django_questionnaires-0.1.0/tests/test_reporting.py +313 -0
- vinta_django_questionnaires-0.1.0/tests/test_responses.py +394 -0
- vinta_django_questionnaires-0.1.0/tests/test_validators.py +109 -0
- vinta_django_questionnaires-0.1.0/tests/test_versioning.py +305 -0
- vinta_django_questionnaires-0.1.0/tests/testapp/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/tests/testapp/apps.py +9 -0
- vinta_django_questionnaires-0.1.0/tests/testapp/migrations/0001_initial.py +34 -0
- vinta_django_questionnaires-0.1.0/tests/testapp/migrations/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/tests/testapp/models.py +29 -0
- vinta_django_questionnaires-0.1.0/tests/urls.py +12 -0
- vinta_django_questionnaires-0.1.0/tox.ini +64 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/admin/__init__.py +203 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/admin/definition.py +522 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/admin/editing.py +92 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/admin/integrations.py +177 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/admin/reporting.py +230 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/admin/responses.py +217 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/admin/structure.py +440 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/apps.py +17 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/catalog.py +178 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/conditions.py +67 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/definition.py +627 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/editing.py +81 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/editor_urls.py +44 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/editor_views.py +355 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/filters.py +270 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/fingerprints.py +128 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/forms.py +83 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/integrations.py +503 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/management/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/management/commands/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/management/commands/dump_conformance_cases.py +79 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/management/commands/dump_validation_manifest.py +68 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/migrations/0001_initial.py +1314 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/migrations/0002_page_is_skippable_questionnaireresponse_pageresponse_and_more.py +279 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/migrations/0003_questionnaireversion_edit_policy_and_more.py +53 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/migrations/0004_acknowledgededit.py +135 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/migrations/0005_responsemapping_responsewebhook_mappingrun_and_more.py +557 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/migrations/__init__.py +0 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/__init__.py +119 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/base.py +79 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/editing.py +229 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/integrations.py +477 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/layout.py +290 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/questionnaires.py +221 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/questions.py +485 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/responses.py +329 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/structure.py +124 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/value_sets.py +239 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/models/widgets.py +125 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/plan.py +198 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/py.typed +0 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/question_types.py +169 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/reporting.py +291 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/schemas.py +57 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/static/vinta_django_questionnaires/admin.css +475 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/static/vinta_django_questionnaires/admin.js +111 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/submissions.py +386 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/_item.html +40 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/_rest.html +27 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/_summary.html +29 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/denied.html +6 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/questionnaire_change_form.html +18 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/response_change_list.html +17 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/response_table.html +131 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/structure.html +181 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/too_large.html +18 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/templates/admin/vinta_django_questionnaires/version_change_form.html +28 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/urls.py +40 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/__init__.py +54 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/base.py +325 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/builtins/__init__.py +20 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/builtins/files.py +131 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/builtins/logic.py +92 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/builtins/numbers.py +153 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/builtins/presence.py +40 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/builtins/sequences.py +154 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/builtins/strings.py +266 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/builtins/temporal.py +150 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/coercion.py +98 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/validators/registry.py +113 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/versioning.py +130 -0
- vinta_django_questionnaires-0.1.0/vinta_django_questionnaires/views.py +284 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
node_modules/
|
|
3
|
+
demo/.output/
|
|
4
|
+
demo/.tanstack/
|
|
5
|
+
demo/src/routeTree.gen.ts
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.egg-info/
|
|
8
|
+
.eggs/
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
.venv/
|
|
12
|
+
.tox/
|
|
13
|
+
.nox/
|
|
14
|
+
.mypy_cache/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.coverage
|
|
18
|
+
.coverage.*
|
|
19
|
+
coverage.xml
|
|
20
|
+
htmlcov/
|
|
21
|
+
*.sqlite3
|
|
22
|
+
example/db.sqlite3
|
|
23
|
+
.DS_Store
|
|
24
|
+
.idea/
|
|
25
|
+
.vscode/
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `publish-client.yml`, which releases the TypeScript client to npm through
|
|
13
|
+
trusted publishing on a `client-v*` tag -- type check, tests, build, a check
|
|
14
|
+
that the tag matches the version and that the version is not already there,
|
|
15
|
+
and a dry run mode that stops after `npm pack`. `publish.yml` now ignores
|
|
16
|
+
those tags, so the two packages release independently.
|
|
17
|
+
- The client package declares its `repository`, `homepage` and `bugs`, and
|
|
18
|
+
ships the licence. npm's provenance attestation names the source of a build,
|
|
19
|
+
so in a repository holding two packages it needs to know which directory this
|
|
20
|
+
one lives in.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## [0.1.0] - 2026-08-27
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Initial project scaffolding.
|
|
28
|
+
- Questionnaire definition models: versioned questionnaires, pages, sections,
|
|
29
|
+
questions, inline choices, value sets, widgets and the responsive column
|
|
30
|
+
grid, with conditions evaluated through JMESPath.
|
|
31
|
+
- A dynamic validation layer: a validator registry other apps extend with
|
|
32
|
+
`@register_validator`, and 24 built-in validators covering presence, text,
|
|
33
|
+
numbers, dates and ranges, collections, files and cross-field predicates.
|
|
34
|
+
- A validation plan emitted per question or questionnaire version, and the
|
|
35
|
+
`dump_validation_manifest` and `dump_conformance_cases` commands that write
|
|
36
|
+
the artifacts under `shared/`.
|
|
37
|
+
- `vinta-django-questionnaires-client`, the TypeScript client under
|
|
38
|
+
`client/`, which builds Zod 4 schemas from those plans and replays the same
|
|
39
|
+
conformance corpus the Python suite runs.
|
|
40
|
+
- Response models: `QuestionnaireResponse`, `PageResponse` and `Answer`. Pages
|
|
41
|
+
are recorded as filled or skipped -- by the respondent, or because their
|
|
42
|
+
condition did not hold -- so where a response stands is derived from what is
|
|
43
|
+
written down rather than tracked separately.
|
|
44
|
+
- `Page.is_skippable`, and a `submissions` service layer with `start_response`,
|
|
45
|
+
`submit_page`, `skip_page` and `sync_condition_skips`.
|
|
46
|
+
- An opt-in JSON API under `vinta_django_questionnaires.urls` for opening a
|
|
47
|
+
response, pushing one page's answers and skipping a page, plus
|
|
48
|
+
`buildPageSchema` and `validatePage` on the client for checking that page
|
|
49
|
+
before it is pushed.
|
|
50
|
+
- A React demo under `demo/` -- TanStack Start, Vite and the
|
|
51
|
+
vinta-schedule-design-system -- that renders and validates a questionnaire
|
|
52
|
+
entirely from the plan, including a client implementation of a custom
|
|
53
|
+
validator and a panel showing what only the server can check. It ships a
|
|
54
|
+
contrast audit script, and every text node in it passes WCAG 2.1 AA.
|
|
55
|
+
- The plan now carries what a client needs to render: each layer's resolved
|
|
56
|
+
column count and each question's minimum columns, the questionnaire's window
|
|
57
|
+
size ranges, titles, descriptions, and the widget and props the server
|
|
58
|
+
resolved.
|
|
59
|
+
- `GET value-sets/{key}/options/`, which resolves a static or model-backed
|
|
60
|
+
value set's options and hands back the endpoint descriptor for one the client
|
|
61
|
+
is meant to call itself.
|
|
62
|
+
- `ResponseCreateView.get_external_id()`, so a project can key a response on
|
|
63
|
+
something other than the request body -- the example uses the browser
|
|
64
|
+
session.
|
|
65
|
+
- A runnable example project under `example/`, with a `seed_example` command
|
|
66
|
+
that builds a four-page questionnaire exercising conditions, a skippable
|
|
67
|
+
page, a nested sub-questionnaire, a model-backed value set and two
|
|
68
|
+
project-specific validators, and a `demo_response` command that narrates a
|
|
69
|
+
whole response through the flow. CI runs both.
|
|
70
|
+
- Validators now receive the response and page being submitted under
|
|
71
|
+
`context.extra`, which is what a server-only validator needs to see anything
|
|
72
|
+
wider than the answer in front of it.
|
|
73
|
+
- `new_version_from()`, which deep-copies a version into a new draft: the
|
|
74
|
+
ordinary way to change a questionnaire that is already in use.
|
|
75
|
+
- An acknowledgement gate on editing a live definition in place. Once a version
|
|
76
|
+
has responses, saving or deleting one of its pages, sections, questions,
|
|
77
|
+
choices or validators raises `UnacknowledgedEdit` unless it happens inside
|
|
78
|
+
`acknowledged_edit()`, which records who did it, why, what changed field by
|
|
79
|
+
field, and how many responses were already in. `AcknowledgedEditForm` and
|
|
80
|
+
`AcknowledgedEditAdminMixin` put that in front of someone as a checkbox.
|
|
81
|
+
- Content fingerprints on questions and versions, and `compare_versions()`, for
|
|
82
|
+
telling which questions ask the same thing across versions and whose answers
|
|
83
|
+
can therefore be pooled.
|
|
84
|
+
- The editable definition document: `definition_document()` reads a version as
|
|
85
|
+
everything an author configured, and `apply_definition()` writes one back.
|
|
86
|
+
Keys are identity, so a rename is a delete and a create; a document that does
|
|
87
|
+
not hold up is refused whole, with one entry per node that would not go and
|
|
88
|
+
the paths the editor addresses its own state by.
|
|
89
|
+
- `editor_catalog()`, which tells an editor what there is to pick: the question
|
|
90
|
+
types, the widgets and their props schemas, the value sets, and every
|
|
91
|
+
registered validator with its params schema and error keys -- including the
|
|
92
|
+
ones other apps registered.
|
|
93
|
+
- An opt-in authoring API under `vinta_django_questionnaires.editor_urls` for
|
|
94
|
+
reading a version, applying a document, forking a draft and fetching the
|
|
95
|
+
catalog. Staff only by default, and `PUT` carries the acknowledgement that
|
|
96
|
+
editing a live version needs.
|
|
97
|
+
- `QuestionnaireEditor`, a React editor in the client package under the
|
|
98
|
+
`/editor` entry point, with `useQuestionnaireEditor` for a project that wants
|
|
99
|
+
its own interface and a reducer under that with no React in it at all. It
|
|
100
|
+
renders validator params from their own JSON Schema rather than a form per
|
|
101
|
+
validator, names the answers a renamed key would orphan, puts the server's
|
|
102
|
+
refusals under the field that caused them, and is styled entirely through
|
|
103
|
+
`vqe-` class names and custom properties. The demo grows an `/editor` route
|
|
104
|
+
that drops it in whole.
|
|
105
|
+
- An admin the package registers itself, arranged around what someone does
|
|
106
|
+
rather than around the model graph. A questionnaire lists its versions with a
|
|
107
|
+
way into each; a version's change form holds only the version's own settings;
|
|
108
|
+
and a **structure editor** puts every page, section, question, choice and
|
|
109
|
+
validator of a version on one form that saves together -- so a change across
|
|
110
|
+
three levels is one save and one acknowledgement rather than five page loads
|
|
111
|
+
and four of each. Rows show the key, title and type with the rest behind a
|
|
112
|
+
disclosure, lists reorder by dragging or with the arrow keys, and the
|
|
113
|
+
validator dropdown is the registry.
|
|
114
|
+
- The admin's response table: a column per question, a picker grouped by page,
|
|
115
|
+
a CSV export of exactly the columns on screen, and a changelist action that
|
|
116
|
+
exports a selection. It uses the same `reporting` module as the API and the
|
|
117
|
+
React demo, so the three cannot drift.
|
|
118
|
+
- Every response now shows what it wrote and what it set off -- its
|
|
119
|
+
`MappingRun`s with a link to the record each one created, and its
|
|
120
|
+
`WebhookDelivery`s with the status and the error -- as read-only inlines.
|
|
121
|
+
- `admin.py` became the `admin` package; `AcknowledgedEditAdminMixin`,
|
|
122
|
+
`AcknowledgedEditInlineMixin` and `signed_form` import from the same place as
|
|
123
|
+
before.
|
|
124
|
+
- Registering the admin is opt-out. `QUESTIONNAIRES_REGISTER_ADMIN = False` and
|
|
125
|
+
`register()`, which skips what is already registered -- so a project with an
|
|
126
|
+
admin of its own for any of these models no longer fails to start with
|
|
127
|
+
`AlreadyRegistered`. `register(model_admin_base=..., inline_base=...)` puts a
|
|
128
|
+
themed admin's base classes underneath, inlines included, which is all a
|
|
129
|
+
project on django-unfold needs.
|
|
130
|
+
- The admin stylesheet's colours became `--vqa-` tokens mapped onto the Django
|
|
131
|
+
admin's, each falling back to a value mixed out of `currentColor`. A theme
|
|
132
|
+
that replaces the admin's stylesheet defines none of Django's properties, and
|
|
133
|
+
an unguarded `var()` there is invalid at computed-value time -- which
|
|
134
|
+
collapsed every border in the structure editor to nothing. The editor now
|
|
135
|
+
styles its own controls too, rather than leaning on the admin to do it.
|
|
136
|
+
- The changelists whose columns render those links now ship the stylesheet, so
|
|
137
|
+
the shortcuts are buttons rather than bare text.
|
|
138
|
+
- `ResponseMapping` and `MappingField`: answers into a project's own models,
|
|
139
|
+
named through the content type framework so this package never imports them.
|
|
140
|
+
One JMESPath expression per target field, an operation of insert, update or
|
|
141
|
+
upsert, defaults for what is created, and lookup fields for what is found.
|
|
142
|
+
Every run is written down as a `MappingRun`, the target reachable from it.
|
|
143
|
+
- `ResponseWebhook`: a URL template with JMESPath-filled placeholders, and
|
|
144
|
+
headers and a body that are JSON trees with `{"$jmespath": "..."}` resolved
|
|
145
|
+
anywhere in them. Delivery goes through the standard library, is swappable
|
|
146
|
+
through `QUESTIONNAIRES_WEBHOOK_SENDER`, and is recorded either way as a
|
|
147
|
+
`WebhookDelivery`.
|
|
148
|
+
- Both run after the submission commits and neither can break one: a failure is
|
|
149
|
+
a record, not something the respondent sees. `QUESTIONNAIRES_RUN_INTEGRATIONS`
|
|
150
|
+
turns the inline run off for a project that would rather use a task queue.
|
|
151
|
+
- `reporting`: responses as a table. One column per question the version asks
|
|
152
|
+
plus the metadata anyone reading a table wants, the same column list driving
|
|
153
|
+
the JSON listing and a streamed CSV export, and one query for a whole page's
|
|
154
|
+
answers rather than one per row.
|
|
155
|
+
- `GET responses/` and `GET responses/export/` on the authoring API, filtered by
|
|
156
|
+
questionnaire, version, status and search, with the columns chosen per call.
|
|
157
|
+
- `POST questionnaires/new/`, `DELETE questionnaires/{key}/` and
|
|
158
|
+
`DELETE questionnaires/{key}/versions/{n}/`, so the whole lifecycle of a
|
|
159
|
+
questionnaire is reachable over HTTP. Deleting is refused once a version has
|
|
160
|
+
been answered.
|
|
161
|
+
- Drag to reorder in the editor -- pages, sections, questions, choices and the
|
|
162
|
+
validator chain -- on dnd-kit, an optional peer dependency. A `DndContext` per
|
|
163
|
+
list, so a drag cannot take a question out of its section, and dnd-kit's
|
|
164
|
+
keyboard sensor makes every list reorderable without a mouse.
|
|
165
|
+
- `AuthoringApi` in the client: `EditorApi` plus listing, creating and deleting
|
|
166
|
+
questionnaires and reading responses, with `cellText` and `groupColumns` for
|
|
167
|
+
rendering a table of them.
|
|
168
|
+
- The demo grows a back office: a sign-in page taking the Django admin's
|
|
169
|
+
credentials, the editor and a TanStack Table of responses behind a staff gate,
|
|
170
|
+
a column picker grouped by page, and a CSV button. The seed adds a mapping
|
|
171
|
+
that turns a finished onboarding response into a `Lead`.
|
|
172
|
+
- `openapi.yml`, describing both URL modules -- every path, method, parameter
|
|
173
|
+
and payload. The suite checks it against the URLconf, so an endpoint added
|
|
174
|
+
without an entry fails CI.
|
|
175
|
+
- `QuestionnaireVersion.edit_policy`, `responses_due_at` and `edits_due_at`.
|
|
176
|
+
Answering a page with nothing recorded and editing one that already has
|
|
177
|
+
answers are separate acts with their own deadline, enforced by the
|
|
178
|
+
submission layer and reported to the client as a `policy` block on every
|
|
179
|
+
response payload.
|
|
180
|
+
|
|
181
|
+
[Unreleased]: https://github.com/vintasoftware/vinta-django-questionnaires/compare/v0.1.0...HEAD
|
|
182
|
+
[0.1.0]: https://github.com/vintasoftware/vinta-django-questionnaires/releases/tag/v0.1.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vinta Software
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|