Make projects private by default with a single is_visible flag (#1300) - #1302
Merged
Merged
Conversation
Public project visibility was an implicit "has a thumbnail AND a
publication" heuristic duplicated across views and templates. Replace it
with a single editor-controlled Project.is_visible flag so the team can
create a project the moment it begins, add people while working, and keep
it hidden until it's ready to go live.
- Model: add nullable is_visible field; Project.save() defaults new
projects to private (False); can_show_online() now returns
bool(is_visible). The field is intentionally nullable with no DB
default so the migration adds existing rows as NULL rather than
silently hiding every current project.
- backfill_project_visibility one-shot command (wired into
docker-entrypoint.sh) resolves legacy NULL rows to their previous
visibility (thumbnail+pub). Keyed on is_visible__isnull=True, so it's
idempotent and never clobbers a later manual admin choice.
- Replace the scattered checks with is_visible=True in index,
project_listing (active+completed), and member views, and drop the
now-redundant per-item guards in project_listing.html. Order by
most-recent-pub with nulls_last so a pub-less visible project doesn't
sort to the top.
- Individual project page: private projects 404 for the public but
remain previewable by logged-in staff.
- Admin: is_visible in fieldsets/list_display/list_filter, rendered as a
clean checkbox ("Visible on website").
- data-health check surfaces is_visible; seed_demo_projects marks demos
visible.
- Tests: new test_project_visibility.py (default, backfill idempotency,
listing/page filtering, staff-preview gate) + make_project helper.
- Bump version to 2.6.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member
Author
Follow-up: full visibility coverage (commit 281fe1b)After an audit of every place a project can be mentioned, found six surfaces beyond the gallery/landing/member/chip set that still referenced a private project. All now route through
Intentionally not changed: Each surface has a regression test in |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1300.
Summary
Public project visibility was a hodgepodge: an implicit "has a thumbnail AND a publication" check duplicated across views and templates. This replaces it with a single editor-controlled
Project.is_visibleflag so we can:What changed
models/project.py): newis_visiblefield.Project.save()defaults new projects to private (False);can_show_online()now returnsbool(is_visible). The field is intentionally nullable with no DB default so the migration adds existing rows asNULLrather than silently hiding every current project on first deploy.backfill_project_visibility, wired intodocker-entrypoint.sh): resolves legacyNULLrows to their previous visibility (thumbnail + publication). Keyed onis_visible__isnull=True, so it's idempotent and never clobbers a later manual admin choice. Same pattern asbackfill_num_pages.is_visible=Truein the landing page (index), project gallery (project_listing, active + completed), and member views; dropped the now-redundant per-item guards inproject_listing.html. Ordering usesnulls_lastso a visible project with no publication yet doesn't sort to the top.is_visibleadded to fieldsets /list_display/list_filter, rendered as a clean checkbox ("Visible on website").is_visible;seed_demo_projectsmarks demo projects visible. Version bumped to 2.6.0.Testing
python manage.py test website --settings=makeabilitylab.settings_test), including 16 new ones intest_project_visibility.pycovering the private-by-default behavior, backfill idempotency, gallery/landing filtering, and the staff-preview gate. Added amake_projectfixture helper.404for anonymous, visible →200.UI / accessibility note
No markup changed — the project gallery renders the same unchanged snippet; only which projects appear is different (driven by the queryset). The one visible UI addition is a checkbox on the admin Project form. Pa11y shows no new violations (only the site's pre-existing global footer/color-contrast baseline).
Deploy plan
Merging to
masterdeploys to -test only; production is intentionally not tagged yet so we can validate onmakeabilitylab-test.cs.washington.edufirst. The entrypoint backfill will preserve existing projects' visibility there.🤖 Generated with Claude Code