diff --git a/src/apps/dashboard/static/apps/dashboard/note.js b/src/apps/dashboard/static/apps/dashboard/note.js
index efe838b..1b5fc27 100644
--- a/src/apps/dashboard/static/apps/dashboard/note.js
+++ b/src/apps/dashboard/static/apps/dashboard/note.js
@@ -44,9 +44,15 @@ const Brief = (() => {
banner.remove();
});
- var h2 = document.querySelector('h2');
- if (h2 && h2.parentNode) {
- h2.parentNode.insertBefore(banner, h2.nextSibling);
+ // Prefer the explicit anchor (set in base.html under the messages
+ // block, before {% block content %}) — keeps the banner in the
+ // visible content flow on pages where the first
is
+ // position:absolute (e.g. post.html's rotated navbar header).
+ // Falls back to for pages that pre-date the anchor.
+ var anchor = document.getElementById('id_brief_banner_anchor')
+ || document.querySelector('h2');
+ if (anchor && anchor.parentNode) {
+ anchor.parentNode.insertBefore(banner, anchor.nextSibling);
} else {
document.body.insertBefore(banner, document.body.firstChild);
}
@@ -67,3 +73,9 @@ const Brief = (() => {
// Backwards-compat shim — to be removed once the codebase uniformly uses Brief.
const Note = Brief;
+
+// `const Brief = (...)` at script-tag scope is reachable as a bare name but
+// is NOT auto-attached to window — explicit assignment so callers that gate
+// on `if (window.Brief)` (e.g. _buddy_panel.html's OK handler) succeed.
+window.Brief = Brief;
+window.Note = Note;
diff --git a/src/functional_tests/post_page.py b/src/functional_tests/post_page.py
index 846a27b..ab419ec 100644
--- a/src/functional_tests/post_page.py
+++ b/src/functional_tests/post_page.py
@@ -40,8 +40,19 @@ class PostPage:
)
def share_post_with(self, email):
- self.get_share_box().send_keys(email)
- self.get_share_box().send_keys(Keys.ENTER)
+ # Buddy-btn flow (post-Brief sprint): click bottom-left handshake,
+ # type the email in the slide-out, click the .btn-confirm OK, wait
+ # for the recipient chip.
+ buddy_btn = self.test.browser.find_element(By.ID, "id_buddy_btn")
+ buddy_btn.click()
+ recipient = self.test.wait_for(
+ lambda: self.test.browser.find_element(By.ID, "id_recipient")
+ )
+ recipient.send_keys(email)
+ ok = self.test.browser.find_element(
+ By.CSS_SELECTOR, "#id_buddy_panel .btn.btn-confirm"
+ )
+ ok.click()
self.test.wait_for(
lambda: self.test.assertIn(
email, [item.text for item in self.get_shared_with_list()]
diff --git a/src/static/tests/NoteSpec.js b/src/static/tests/NoteSpec.js
index d409fb6..97186e8 100644
--- a/src/static/tests/NoteSpec.js
+++ b/src/static/tests/NoteSpec.js
@@ -118,9 +118,17 @@ describe('Brief.showBanner', () => {
expect(document.querySelector('.note-banner')).toBeNull();
});
- // ── T10 ── placement after h2 ─────────────────────────────────────────────
+ // ── T10 ── placement: anchor preferred over h2 ───────────────────────────
- it('T10: banner is inserted immediately after the first h2 in the document', () => {
+ it('T10a: banner is inserted as nextSibling of #id_brief_banner_anchor when present', () => {
+ const anchor = document.createElement('div');
+ anchor.id = 'id_brief_banner_anchor';
+ fixture.appendChild(anchor);
+ Brief.showBanner(SAMPLE_BRIEF);
+ expect(anchor.nextElementSibling.classList.contains('note-banner')).toBeTrue();
+ });
+
+ it('T10b: falls back to inserting after the first h2 when anchor is absent', () => {
Brief.showBanner(SAMPLE_BRIEF);
const h2 = fixture.querySelector('h2');
expect(h2.nextElementSibling.classList.contains('note-banner')).toBeTrue();
diff --git a/src/static_src/tests/NoteSpec.js b/src/static_src/tests/NoteSpec.js
index d409fb6..97186e8 100644
--- a/src/static_src/tests/NoteSpec.js
+++ b/src/static_src/tests/NoteSpec.js
@@ -118,9 +118,17 @@ describe('Brief.showBanner', () => {
expect(document.querySelector('.note-banner')).toBeNull();
});
- // ── T10 ── placement after h2 ─────────────────────────────────────────────
+ // ── T10 ── placement: anchor preferred over h2 ───────────────────────────
- it('T10: banner is inserted immediately after the first h2 in the document', () => {
+ it('T10a: banner is inserted as nextSibling of #id_brief_banner_anchor when present', () => {
+ const anchor = document.createElement('div');
+ anchor.id = 'id_brief_banner_anchor';
+ fixture.appendChild(anchor);
+ Brief.showBanner(SAMPLE_BRIEF);
+ expect(anchor.nextElementSibling.classList.contains('note-banner')).toBeTrue();
+ });
+
+ it('T10b: falls back to inserting after the first h2 when anchor is absent', () => {
Brief.showBanner(SAMPLE_BRIEF);
const h2 = fixture.querySelector('h2');
expect(h2.nextElementSibling.classList.contains('note-banner')).toBeTrue();
diff --git a/src/templates/core/base.html b/src/templates/core/base.html
index e829894..a0ffefb 100644
--- a/src/templates/core/base.html
+++ b/src/templates/core/base.html
@@ -44,6 +44,11 @@
{% endfor %}
{% endif %}
+ {# Anchor for Brief.showBanner — banner inserts as nextSibling so #}
+ {# it lands at the top of page content on every base.html-extending #}
+ {# page, regardless of where (or whether) is positioned. #}
+
+
{% block content %}
{% endblock content %}