admin Posts (NOTE_UNLOCK): readonly input + 'No response needed' placeholder + secUser focus glow + buddy btn suppressed + view POST 403 + Line.admin_solicited listener nukes errant writes; share Lines: drop ts suffix, author = sharer (adman fallback for anon legacy), silent no-op on re-share — TDD
- billboard/0005 adds Line.admin_solicited (BooleanField default False); RunPython backfills existing note_unlock Lines to True. Note.grant_if_new sets admin_solicited=True on its system prose.
- billboard.models post_save signal: any Line saved on a Post.kind=NOTE_UNLOCK without admin_solicited=True is deleted (defense-in-depth alongside the view guard).
- billboard.views.view_post hard-rejects POST on NOTE_UNLOCK kind (HTTP 403) — clean view-level contract; the post_save listener is the safety net for ORM/API paths that bypass it.
- templates/apps/billboard/post.html: NOTE_UNLOCK branch renders the input as readonly w. 'No response needed at this time' placeholder + no method/action; user_post branch keeps the regular composer. Buddy panel include guarded behind `{% if post.kind != 'note_unlock' %}` — friend invites don't apply to admin threads.
- SCSS: .post-line-form input.form-control[readonly]:focus uses --secUser glow (cooler than the regular --terUser composer focus).
- share_post: drop the iso-timestamp suffix on Line.text (just 'Shared with {email}'); author = request.user (anon legacy fallback to adman so AnonymousUser doesn't break the FK); re-share of an already-in-shared_with recipient is a silent no-op (no second Line, brief: null in JSON response). Buddy panel JS now reads data-sharer-name from server-rendered display_name so the optimistic _appendLine matches the post-refresh state.
- new ITs: test_admin_posts (PostRejectsAdminWritesTest, UnsolicitedLineListenerTest, NoteGrantSetsAdminSolicitedTest) — 7 tests; share_post tests rewritten for the new contract (drop ts, author=sharer, silent re-share dedup) — 12 tests; new FT test_admin_post_readonly w. AdminPostInputReadonlyTest + AdminPostHasNoBuddyBtnTest + UserPostInputUnaffectedTest — 4 tests. 827 ITs + 18 buddy/sharing FTs green.
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
{% load static %}
|
||||
{% load lyric_extras %}
|
||||
{# ─────────────────────────────────────────────────────────────────────── #}
|
||||
{# _buddy_panel.html — bottom-left handshake btn + slide-out recipient #}
|
||||
{# field for the share-post async flow. Mirror of #id_kit_btn (bottom- #}
|
||||
@@ -13,7 +14,9 @@
|
||||
<i class="fa-solid fa-handshake"></i>
|
||||
</button>
|
||||
|
||||
<div id="id_buddy_panel" data-share-url="{% url 'billboard:share_post' post.id %}">
|
||||
<div id="id_buddy_panel"
|
||||
data-share-url="{% url 'billboard:share_post' post.id %}"
|
||||
data-sharer-name="{% if request.user.is_authenticated %}{{ request.user|display_name }}{% endif %}">
|
||||
<input id="id_recipient"
|
||||
name="recipient"
|
||||
type="email"
|
||||
@@ -76,15 +79,17 @@
|
||||
// OK → POST share-post async; reuses the C3.b response handling so the
|
||||
// recipient chip + brief banner + post-line append all light up.
|
||||
// Post-May08b layout: #id_post_table is a <ul> of <li class="post-line">
|
||||
// rows; share-invite Lines are adman-authored (system prose, italic).
|
||||
// rows. Author = the sharer (rendered server-side as data-sharer-name on
|
||||
// the panel) so the appended Line matches the post-refresh state, where
|
||||
// the persisted Line.author is request.user.
|
||||
function _appendLine(text) {
|
||||
var list = document.getElementById('id_post_table');
|
||||
if (!list) return;
|
||||
var li = document.createElement('li');
|
||||
li.className = 'post-line post-line--system';
|
||||
li.className = 'post-line';
|
||||
var author = document.createElement('span');
|
||||
author.className = 'post-line-author';
|
||||
author.textContent = 'adman';
|
||||
author.textContent = panel.dataset.sharerName || '';
|
||||
var body = document.createElement('span');
|
||||
body.className = 'post-line-text';
|
||||
body.textContent = text;
|
||||
|
||||
Reference in New Issue
Block a user