docbrown/app/javascript/previewCards/feedPreviewCards.jsx
Suzanne Aitchison 80096f63a7
Add author profile preview cards to feed (#14340)
* Add the preview card to logged out feed initial content

* initialise the initial dropdowns added on the logged out feed

* minor tweak to selector

* flip the follow button and the summary

* add minimal preview card to build article HTML

* WIP: data fetched an inserted into card on logged out feed

* WIP: cards added to logged in feed

* create separate profile preview card component

* small style tweak, import pack on each page that shows feed cards

* rename

* tweak some styling issues

* make sure follow buttons init in cards

* populate all matching metadata placeholders after fetch

* don't render full preview card upfront on logged out feed

* refactors from PR comments

* fix issue in person search results

* remove check for article author link that will be superseded by cypress test for preview card

* Revert "remove check for article author link that will be superseded by cypress test for preview card"

This reverts commit 9b42804ffd0f051891c87293d0b791ed2bb0367f.

* Revert "fix issue in person search results"

This reverts commit 04941e3520c0895212141193b60f2933faed5ca1.

* only show the preview cards on story cards for Posts (not users etc in search results)

* correct display on collections view

* remove link check that will be replaced by cypress test

* tweaks to small issues, add a test for the logged out feed

* add tests for logged in home feed, logged out tag index

* add search test and tag index logged in test

* fixes to preview profile spec

* tweak to followauthor spec

* add cypress test for preview on series page

* use a unique test user for series test

* correct the jsdoc comments

* tweaks following PR review

* allow feed preview cards to reposition

* move to separate file from pack
2021-08-13 10:55:43 +07:00

115 lines
3.5 KiB
JavaScript

import { h, render } from 'preact';
import { UserMetadata } from '../profilePreviewCards/UserMetadata';
import {
initializeDropdown,
getDropdownRepositionListener,
} from '@utilities/dropdownUtils';
import { request } from '@utilities/http/request';
const cachedAuthorMetadata = {};
async function populateMissingMetadata(metadataPlaceholder) {
const { authorId, fetched } = metadataPlaceholder.dataset;
// If the metadata is already being fetched, do nothing
if (fetched) {
return;
}
metadataPlaceholder.dataset.fetched = 'true';
const previouslyFetchedAuthorMetadata = cachedAuthorMetadata[authorId];
if (previouslyFetchedAuthorMetadata) {
renderMetadata(previouslyFetchedAuthorMetadata, metadataPlaceholder);
} else {
const response = await request(`/profile_preview_cards/${authorId}`);
const authorMetadata = await response.json();
cachedAuthorMetadata[authorId] = authorMetadata;
renderMetadata(authorMetadata, metadataPlaceholder);
}
}
function renderMetadata(metadata, placeholder) {
const container = placeholder.parentElement;
render(<UserMetadata {...metadata} />, container, placeholder);
container
.closest('.profile-preview-card__content')
.style.setProperty('--card-color', metadata.card_color);
}
function checkForPreviewCardDetails(event) {
const { target } = event;
if (target.classList.contains('profile-preview-card__trigger')) {
const metadataPlaceholder = target.parentElement.getElementsByClassName(
'author-preview-metadata-container',
)[0];
if (metadataPlaceholder) {
// User is within one of the story cards - and the metadata has not been fetched yet
populateMissingMetadata(metadataPlaceholder);
}
}
}
export function listenForHoveredOrFocusedStoryCards() {
const mainContent = document.getElementById('main-content');
mainContent.addEventListener('mouseover', checkForPreviewCardDetails);
mainContent.addEventListener('focusin', checkForPreviewCardDetails);
}
export function initializeFeedPreviewCards() {
// Select all preview card triggers that haven't already been initialized
const allPreviewCardTriggers = document.querySelectorAll(
'button[id^=story-author-preview-trigger]:not([data-initialized])',
);
for (const previewTrigger of allPreviewCardTriggers) {
const dropdownContentId = previewTrigger.getAttribute('aria-controls');
const dropdownElement = document.getElementById(dropdownContentId);
if (dropdownElement) {
initializeDropdown({
triggerElementId: previewTrigger.id,
dropdownContentId,
onOpen: () => dropdownElement?.classList.add('showing'),
onClose: () => dropdownElement?.classList.remove('showing'),
});
previewTrigger.dataset.initialized = true;
}
}
}
const observer = new MutationObserver((mutationsList) => {
mutationsList.forEach((mutation) => {
if (mutation.type === 'childList') {
initializeFeedPreviewCards();
}
});
});
if (document.getElementById('index-container')) {
observer.observe(document.getElementById('index-container'), {
childList: true,
subtree: true,
});
}
// Preview card dropdowns reposition on scroll
const dropdownRepositionListener = getDropdownRepositionListener();
document.addEventListener('scroll', dropdownRepositionListener);
InstantClick.on('change', () => {
observer.disconnect();
document.removeEventListener('scroll', dropdownRepositionListener);
});
window.addEventListener('beforeunload', () => {
observer.disconnect();
document.removeEventListener('scroll', dropdownRepositionListener);
});