wagtail-developer-reference 0.1.1__tar.gz → 0.1.3__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.
Files changed (24) hide show
  1. {wagtail_developer_reference-0.1.1/wagtail_developer_reference.egg-info → wagtail_developer_reference-0.1.3}/PKG-INFO +30 -9
  2. wagtail_developer_reference-0.1.3/README.md +48 -0
  3. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3}/pyproject.toml +7 -5
  4. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3}/setup.py +3 -3
  5. wagtail_developer_reference-0.1.3/wagtail_developer_reference/__init__.py +1 -0
  6. wagtail_developer_reference-0.1.3/wagtail_developer_reference/apps.py +9 -0
  7. wagtail_developer_reference-0.1.3/wagtail_developer_reference/migrations/0001_initial.py +38 -0
  8. wagtail_developer_reference-0.1.3/wagtail_developer_reference/migrations/__init__.py +1 -0
  9. wagtail_developer_reference-0.1.3/wagtail_developer_reference/models.py +17 -0
  10. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3}/wagtail_developer_reference/templates/detail.html +60 -3
  11. wagtail_developer_reference-0.1.3/wagtail_developer_reference/templates/index.html +313 -0
  12. wagtail_developer_reference-0.1.3/wagtail_developer_reference/wagtail_hooks.py +358 -0
  13. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3/wagtail_developer_reference.egg-info}/PKG-INFO +30 -9
  14. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3}/wagtail_developer_reference.egg-info/SOURCES.txt +3 -0
  15. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3}/wagtail_developer_reference.egg-info/requires.txt +1 -1
  16. wagtail_developer_reference-0.1.1/README.md +0 -29
  17. wagtail_developer_reference-0.1.1/wagtail_developer_reference/__init__.py +0 -0
  18. wagtail_developer_reference-0.1.1/wagtail_developer_reference/apps.py +0 -4
  19. wagtail_developer_reference-0.1.1/wagtail_developer_reference/templates/index.html +0 -164
  20. wagtail_developer_reference-0.1.1/wagtail_developer_reference/wagtail_hooks.py +0 -192
  21. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3}/MANIFEST.in +0 -0
  22. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3}/setup.cfg +0 -0
  23. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3}/wagtail_developer_reference.egg-info/dependency_links.txt +0 -0
  24. {wagtail_developer_reference-0.1.1 → wagtail_developer_reference-0.1.3}/wagtail_developer_reference.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wagtail-developer-reference
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: A visual auditing tool for Wagtail developers to track Page models and StreamField blocks.
5
5
  Author-email: Four Digits <info@fourdigits.nl>
6
6
  Project-URL: Homepage, https://github.com/fourdigits/wagtail-developer-reference
@@ -14,9 +14,11 @@ Classifier: Programming Language :: Python :: 3.9
14
14
  Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
- Requires-Python: >=3.10
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Requires-Python: >=3.9
18
20
  Description-Content-Type: text/markdown
19
- Requires-Dist: wagtail>=4.1
21
+ Requires-Dist: wagtail<7.5,>=4.1
20
22
  Provides-Extra: dev
21
23
  Requires-Dist: ruff; extra == "dev"
22
24
  Requires-Dist: pytest; extra == "dev"
@@ -30,13 +32,17 @@ Requires-Dist: pytest-django; extra == "dev"
30
32
  In large Wagtail projects, it’s easy to lose track of where specific blocks are used or which templates are being rendered. This tool gives you a "God-view" of your components without needing to dig through the database or shell.
31
33
 
32
34
  ## Features
33
- * **Usage Tracking:** See exactly how many times a Page type or StreamField block is used across the site.
34
- * **Template Discovery:** Instantly see the file path for the template associated with every component.
35
- * **Interactive Audit:** Filter by type or search for specific field names to find where logic is implemented.
36
- * **Zero-Config:** No extra database tables or complex settings. It inspects your models and content on the fly.
35
+ * **On-demand usage tracking:** Apply filters before calculating page and block usage, keeping the registry quick to open.
36
+ * **Interactive registry:** Combine text, PAGE/BLOCK, site and total-usage-range filters to find exactly the components you need.
37
+ * **Nested block discovery:** Browse visible block labels and full nested definition paths, with safe fallbacks for unlabeled blocks.
38
+ * **Usage inspection:** Search and paginate matching pages, then copy the visible usage table in one click.
39
+ * **Template discovery:** See the template path associated with every component.
37
40
 
38
41
  ## Installation
39
42
 
43
+ Compatibility: Python 3.9+ and Wagtail 4.1 through 7.4.2 LTS (the latest
44
+ stable Wagtail release at v0.1.3). Wagtail 7.4 itself requires Python 3.10+.
45
+
40
46
  1. Add \`wagtail_developer_reference\` to your \`INSTALLED_APPS\`:
41
47
  \`\`\`python
42
48
  INSTALLED_APPS = [
@@ -45,9 +51,24 @@ In large Wagtail projects, it’s easy to lose track of where specific blocks ar
45
51
  ]
46
52
  \`\`\`
47
53
 
48
- 2. **Usage:**
49
- * Login to the Wagtail Admin as a **superuser**.
54
+ 2. Run migrations so Django creates the package permission:
55
+ ```bash
56
+ python manage.py migrate
57
+ ```
58
+
59
+ 3. Grant access in the Django admin:
60
+ * Open a user or group in the Django admin.
61
+ * Assign **Wagtail developer reference | developer reference access | Can access the
62
+ Wagtail developer reference**.
63
+
64
+ 4. **Usage:**
65
+ * Login to the Wagtail Admin with an account that has that permission explicitly
66
+ assigned.
50
67
  * Find the **"System Registry"** item in the sidebar menu.
51
68
 
69
+ By default, no account can see the menu item or access the URLs. Superusers are not
70
+ granted access automatically by this package; assign the permission directly or
71
+ through a group.
72
+
52
73
  ## License
53
74
  **Internal Use Only** - Copyright © 2026 Fourdigits. All rights reserved.
@@ -0,0 +1,48 @@
1
+ # Wagtail Developer Reference
2
+
3
+ **A visual auditing tool for Wagtail developers.** This package provides a live registry of your project's architecture, making it easy to track Page models and StreamField blocks across complex, multi-site setups.
4
+
5
+ ## Why use this?
6
+ In large Wagtail projects, it’s easy to lose track of where specific blocks are used or which templates are being rendered. This tool gives you a "God-view" of your components without needing to dig through the database or shell.
7
+
8
+ ## Features
9
+ * **On-demand usage tracking:** Apply filters before calculating page and block usage, keeping the registry quick to open.
10
+ * **Interactive registry:** Combine text, PAGE/BLOCK, site and total-usage-range filters to find exactly the components you need.
11
+ * **Nested block discovery:** Browse visible block labels and full nested definition paths, with safe fallbacks for unlabeled blocks.
12
+ * **Usage inspection:** Search and paginate matching pages, then copy the visible usage table in one click.
13
+ * **Template discovery:** See the template path associated with every component.
14
+
15
+ ## Installation
16
+
17
+ Compatibility: Python 3.9+ and Wagtail 4.1 through 7.4.2 LTS (the latest
18
+ stable Wagtail release at v0.1.3). Wagtail 7.4 itself requires Python 3.10+.
19
+
20
+ 1. Add \`wagtail_developer_reference\` to your \`INSTALLED_APPS\`:
21
+ \`\`\`python
22
+ INSTALLED_APPS = [
23
+ ...,
24
+ "wagtail_developer_reference",
25
+ ]
26
+ \`\`\`
27
+
28
+ 2. Run migrations so Django creates the package permission:
29
+ ```bash
30
+ python manage.py migrate
31
+ ```
32
+
33
+ 3. Grant access in the Django admin:
34
+ * Open a user or group in the Django admin.
35
+ * Assign **Wagtail developer reference | developer reference access | Can access the
36
+ Wagtail developer reference**.
37
+
38
+ 4. **Usage:**
39
+ * Login to the Wagtail Admin with an account that has that permission explicitly
40
+ assigned.
41
+ * Find the **"System Registry"** item in the sidebar menu.
42
+
43
+ By default, no account can see the menu item or access the URLs. Superusers are not
44
+ granted access automatically by this package; assign the permission directly or
45
+ through a group.
46
+
47
+ ## License
48
+ **Internal Use Only** - Copyright © 2026 Fourdigits. All rights reserved.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "wagtail-developer-reference"
3
- version = "0.1.1"
3
+ version = "0.1.3"
4
4
  description = "A visual auditing tool for Wagtail developers to track Page models and StreamField blocks."
5
5
  readme = "README.md"
6
6
  authors = [{name = "Four Digits", email = "info@fourdigits.nl" }]
@@ -14,13 +14,15 @@ classifiers = [
14
14
  "Programming Language :: Python :: 3.9",
15
15
  "Programming Language :: Python :: 3.10",
16
16
  "Programming Language :: Python :: 3.11",
17
- "Programming Language :: Python :: 3.12"
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Programming Language :: Python :: 3.14"
18
20
  ]
19
21
  keywords = ["django", "wagtail", "audit", "streamfield"]
20
22
  dependencies = [
21
- "wagtail>=4.1",
23
+ "wagtail>=4.1,<7.5",
22
24
  ]
23
- requires-python = ">=3.10"
25
+ requires-python = ">=3.9"
24
26
 
25
27
  [project.optional-dependencies]
26
28
  dev = [
@@ -44,7 +46,7 @@ include = ["wagtail_developer_reference*"]
44
46
 
45
47
  [tool.ruff]
46
48
  line-length = 88
47
- target-version = "py310"
49
+ target-version = "py39"
48
50
 
49
51
  [tool.ruff.lint]
50
52
  select = ["E", "F", "W", "I"]
@@ -1,11 +1,11 @@
1
- from setuptools import setup, find_packages
1
+ from setuptools import find_packages, setup
2
2
 
3
3
  setup(
4
4
  name="wagtail-developer-reference",
5
- version="0.1.1",
5
+ version="0.1.3",
6
6
  packages=find_packages(),
7
7
  include_package_data=True,
8
8
  install_requires=[
9
- "wagtail>=4.1",
9
+ "wagtail>=4.1,<7.5",
10
10
  ],
11
11
  )
@@ -0,0 +1 @@
1
+ __version__: str = "0.1.2"
@@ -0,0 +1,9 @@
1
+ from __future__ import annotations
2
+
3
+ from django.apps import AppConfig
4
+
5
+
6
+ class WagtailDeveloperReferenceConfig(AppConfig):
7
+ default_auto_field: str = "django.db.models.BigAutoField"
8
+ name: str = "wagtail_developer_reference"
9
+ verbose_name: str = "Wagtail developer reference"
@@ -0,0 +1,38 @@
1
+ # Generated manually for wagtail-developer-reference.
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+ initial = True
8
+
9
+ dependencies = []
10
+
11
+ operations = [
12
+ migrations.CreateModel(
13
+ name="DeveloperReferencePermission",
14
+ fields=[
15
+ (
16
+ "id",
17
+ models.BigAutoField(
18
+ auto_created=True,
19
+ primary_key=True,
20
+ serialize=False,
21
+ verbose_name="ID",
22
+ ),
23
+ ),
24
+ ],
25
+ options={
26
+ "verbose_name": "developer reference access",
27
+ "verbose_name_plural": "developer reference access",
28
+ "permissions": (
29
+ (
30
+ "access_developer_reference",
31
+ "Can access the Wagtail developer reference",
32
+ ),
33
+ ),
34
+ "default_permissions": (),
35
+ "managed": False,
36
+ },
37
+ ),
38
+ ]
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ from django.db import models
4
+
5
+
6
+ class DeveloperReferencePermission(models.Model):
7
+ class Meta:
8
+ default_permissions: tuple[str, ...] = ()
9
+ managed: bool = False
10
+ permissions: tuple[tuple[str, str], ...] = (
11
+ (
12
+ "access_developer_reference",
13
+ "Can access the Wagtail developer reference",
14
+ ),
15
+ )
16
+ verbose_name: str = "developer reference access"
17
+ verbose_name_plural: str = "developer reference access"
@@ -98,6 +98,25 @@
98
98
 
99
99
  .empty-state p { font-size: 1.2rem; }
100
100
 
101
+ .registry-controls {
102
+ display: flex;
103
+ gap: 1rem;
104
+ margin-bottom: 1.5rem;
105
+ align-items: end;
106
+ }
107
+
108
+ .registry-controls {
109
+ background: #333; border-left: 0.3125rem solid #dcbd3d; padding: 1rem;
110
+ }
111
+ .registry-controls div:first-of-type { flex: 1; }
112
+ .registry-controls label { color: white; display: block; font-weight: bold; margin-bottom: 0.5rem; }
113
+ .registry-controls input {
114
+ background: #222; border: 0.0625rem solid #dcbd3d; box-sizing: border-box;
115
+ color: white; min-height: 2.5rem; padding: 0.6rem; width: 100%;
116
+ }
117
+ .usage-table-actions { display: flex; justify-content: flex-end; margin-top: 1rem; }
118
+ .copy-table-button { border-radius: 0; }
119
+
101
120
  [data-wagtail-theme="dark"] .listing tbody tr:hover {
102
121
  background-color: #333 !important;
103
122
  }
@@ -111,11 +130,21 @@
111
130
  <a href="{% url 'dev_reference' %}">&larr; Back to System Registry</a>
112
131
  </div>
113
132
  <h1>Locations for: <strong>{{ component_name }}</strong></h1>
114
- <p>Found in {{ pages|length }} location{{ pages|length|pluralize }}</p>
133
+ <p>{{ page_obj.paginator.count }} location{{ page_obj.paginator.count|pluralize }} found</p>
115
134
  </div>
116
135
  </header>
117
136
 
118
137
  <div class="nice-padding">
138
+ <form method="get" class="registry-controls" role="search">
139
+ <input type="hidden" name="site" value="{{ site_filter }}">
140
+ <div>
141
+ <label for="usage-search">Search pages</label>
142
+ <input id="usage-search" type="search" name="q" value="{{ search_query }}" placeholder="Filter by page title or slug...">
143
+ </div>
144
+ <div>
145
+ <button type="submit" class="button">Search</button>
146
+ </div>
147
+ </form>
119
148
  <table class="listing" id="usage-table">
120
149
  <thead>
121
150
  <tr>
@@ -151,12 +180,38 @@
151
180
  {% endfor %}
152
181
  </tbody>
153
182
  </table>
183
+ <div class="usage-table-actions">
184
+ <button id="copy-usage-table" type="button" class="button button-secondary copy-table-button">Copy displayed table</button>
185
+ </div>
186
+ {% if page_obj.paginator.num_pages > 1 %}
187
+ <nav class="pagination" aria-label="Usage result pages">
188
+ {% if page_obj.has_previous %}
189
+ <a class="button" href="?site={{ site_filter|urlencode }}&amp;q={{ search_query|urlencode }}&amp;page={{ page_obj.previous_page_number }}">Previous</a>
190
+ {% endif %}
191
+ <span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>
192
+ {% if page_obj.has_next %}
193
+ <a class="button" href="?site={{ site_filter|urlencode }}&amp;q={{ search_query|urlencode }}&amp;page={{ page_obj.next_page_number }}">Next</a>
194
+ {% endif %}
195
+ </nav>
196
+ {% endif %}
154
197
  </div>
155
198
 
156
199
  <script>
157
200
  let currentSortCol = -1;
158
201
  let sortAsc = true;
159
202
 
203
+ function copyUsageTable() {
204
+ const headers = ["Page Title", "Status", "URL Path"];
205
+ const rows = Array.from(document.querySelectorAll("#usage-body .usage-row"));
206
+ const values = rows.map(row => [0, 1, 2].map(index => row.cells[index].innerText.trim().replace(/\s+/g, " ")));
207
+ const text = [headers, ...values].map(row => row.join("\t")).join("\n");
208
+ const button = document.getElementById("copy-usage-table");
209
+ navigator.clipboard.writeText(text).then(() => {
210
+ button.textContent = "Copied";
211
+ window.setTimeout(() => { button.textContent = "Copy displayed table"; }, 1500);
212
+ });
213
+ }
214
+
160
215
  function sortTable(colIdx) {
161
216
  const tbody = document.getElementById("usage-body");
162
217
  const rows = Array.from(tbody.querySelectorAll(".usage-row"));
@@ -173,12 +228,14 @@
173
228
  if (colIdx === 1) {
174
229
  valA = parseInt(a.cells[colIdx].getAttribute('data-sort'));
175
230
  valB = parseInt(b.cells[colIdx].getAttribute('data-sort'));
176
- return sortAsc ? valA - valB : valB - valueA;
231
+ return sortAsc ? valA - valB : valB - valA;
177
232
  }
178
233
  valA = a.cells[colIdx].textContent.trim().toLowerCase();
179
234
  valB = b.cells[colIdx].textContent.trim().toLowerCase();
180
235
  return sortAsc ? valA.localeCompare(valB) : valB.localeCompare(valA);
181
236
  }).forEach(row => tbody.appendChild(row));
182
237
  }
238
+
239
+ document.getElementById("copy-usage-table").addEventListener("click", copyUsageTable);
183
240
  </script>
184
- {% endblock %}
241
+ {% endblock %}