119 lines
5.4 KiB
HTML
119 lines
5.4 KiB
HTML
{% load static %}
|
|
{% load lyric_extras %}
|
|
{# ─────────────────────────────────────────────────────────────────────── #}
|
|
{# _bud_panel.html — bottom-left handshake btn + slide-out recipient #}
|
|
{# field for the share-post async flow. Skeleton (open/close/POST + auto- #}
|
|
{# complete) owned by bud-btn.js; this partial wires the share-post #}
|
|
{# success callback: appends a Line to #id_post_table, fires Brief.show- #}
|
|
{# Banner, and updates the .post-header shared-with prose. #}
|
|
{# Included by post.html only. #}
|
|
{# #}
|
|
{# Spec lives in functional_tests/test_bud_btn.py. #}
|
|
{# ─────────────────────────────────────────────────────────────────────── #}
|
|
|
|
<button id="id_bud_btn" type="button" aria-label="Share with a bud">
|
|
<i class="fa-solid fa-handshake"></i>
|
|
</button>
|
|
|
|
<div id="id_bud_panel"
|
|
data-sharer-name="{% if request.user.is_authenticated %}{{ request.user|at_handle }}{% endif %}">
|
|
<input id="id_recipient"
|
|
name="recipient"
|
|
type="text"
|
|
placeholder="friend@example.com or username"
|
|
autocomplete="off">
|
|
<button id="id_bud_ok" type="button" class="btn btn-confirm">OK</button>
|
|
</div>
|
|
|
|
{# Autocomplete suggestions — sibling of #id_bud_panel because the panel #}
|
|
{# has overflow:hidden for its scaleX slide animation. #}
|
|
<div id="id_bud_suggestions" class="bud-suggestions" hidden></div>
|
|
|
|
<script src="{% static 'apps/billboard/bud-autocomplete.js' %}"></script>
|
|
<script src="{% static 'apps/billboard/bud-btn.js' %}"></script>
|
|
<script>
|
|
(function () {
|
|
'use strict';
|
|
|
|
var panel = document.getElementById('id_bud_panel');
|
|
|
|
// Author = the sharer (rendered server-side as data-sharer-name) 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';
|
|
var author = document.createElement('span');
|
|
author.className = 'post-line-author';
|
|
author.textContent = panel.dataset.sharerName || '';
|
|
var body = document.createElement('span');
|
|
body.className = 'post-line-text';
|
|
body.textContent = text;
|
|
var time = document.createElement('time');
|
|
time.className = 'post-line-time';
|
|
var now = new Date();
|
|
time.dateTime = now.toISOString();
|
|
time.textContent = now.toLocaleTimeString([], {hour: 'numeric', minute: '2-digit'});
|
|
li.appendChild(author);
|
|
li.appendChild(body);
|
|
li.appendChild(time);
|
|
var buffer = list.querySelector('.post-line-buffer');
|
|
if (buffer) list.insertBefore(li, buffer);
|
|
else list.appendChild(li);
|
|
}
|
|
|
|
// The shared-with header lives outside #id_bud_panel — two <p> siblings
|
|
// under .post-header. State transitions:
|
|
// 0 → 1+ recipients : "just me, X" → "shared between {chip}" + "& me, X"
|
|
// ≥1 → +1 recipients: append chip + ", " separator before existing.
|
|
// `userId` is stamped onto the chip as data-user-id so a later duplicate-
|
|
// share attempt can highlight this same element via .bud-duplicate-flash.
|
|
function _appendRecipientChip(displayName, userId) {
|
|
if (!displayName) return;
|
|
var header = document.querySelector('.post-page .post-header');
|
|
if (!header) return;
|
|
var existingRecipients = header.querySelector('.post-shared-recipients');
|
|
var selfLine = header.querySelector('.post-shared-self');
|
|
|
|
var chip = document.createElement('span');
|
|
chip.className = 'post-recipient';
|
|
chip.textContent = displayName;
|
|
if (userId) chip.dataset.userId = userId;
|
|
|
|
if (existingRecipients) {
|
|
existingRecipients.appendChild(document.createTextNode(', '));
|
|
existingRecipients.appendChild(chip);
|
|
return;
|
|
}
|
|
|
|
var recipientsLine = document.createElement('p');
|
|
recipientsLine.className = 'post-shared-recipients';
|
|
recipientsLine.appendChild(document.createTextNode('shared between '));
|
|
recipientsLine.appendChild(chip);
|
|
if (selfLine) {
|
|
header.insertBefore(recipientsLine, selfLine);
|
|
selfLine.textContent = selfLine.textContent.replace(/^just me,/, '& me,');
|
|
} else {
|
|
header.appendChild(recipientsLine);
|
|
}
|
|
}
|
|
|
|
bindBudBtn({
|
|
submitUrl: '{% url "billboard:share_post" post.id %}',
|
|
autocompleteUrl: '{% url "billboard:search_buds" %}',
|
|
onSuccess: function (data) {
|
|
if (data.line_text) _appendLine(data.line_text);
|
|
if (window.Brief && data.brief) Brief.showBanner(data.brief);
|
|
if (data.recipient_display) {
|
|
_appendRecipientChip(data.recipient_display, data.recipient_user_id);
|
|
}
|
|
},
|
|
duplicateTargetSelector: function (data) {
|
|
return '.post-recipient[data-user-id="' + data.recipient_user_id + '"]';
|
|
},
|
|
});
|
|
}());
|
|
</script>
|