* feat: fix of there is no article * feat: set the feed order in a data structure rather than in a view * feat: update yarn.lock * feat: push the items to the array * feat: update feed to only show billboards if we have the correct length of items in the feed * fix: organizedFeedItems.legth * feat: rename 'featured' to 'image' * feat: rename 'featured' to 'image' * feat: rename 'featured' to 'image' * feat: add some utilities for the feed that we can use in the FeedTest * feat/WIP: the setup for the feed tests and a first working test * test: imageItem * fix: the podcasts can be passed through as an array of objects in the feedItems so that they can be grouped in one card * feat: remove podcastEpisode state and the attribute in the object * fix: check that the items exist before trying to slice them * feat: setup the userdata and the podcast data in the test * whoops - commit the podcast episodes * feat: write soem more tests for the feed and including the podcasts * feat: add some more tests * feat: add more billboards tests to chcek the order of stuff * feat: set the timeframe not empty * feat: update the logic for organizaed feed by inserting the last on first * doc: jsdoc for functions * refactor: break the code up into smaller functions * refactor: make the code more readable and easier to follow * refactor: pull function out into a utlity * feat: add specs to utility * feat: chcek if pinned post * test the latest timeframe correctly * chore: update var name * move the podcast items out of the object clause * feat: update text * feat: add a pack file that duplicates initializeDisplayAdVisibility * feat: create callbacks that will help us to determine when the feed has been rendered so that we can observe the dsplay ads accordingly * chore: rename to billboards instead of display ad * feat: abstract out a function that will work for any tagged resource and also limit the article tags within a scope of the article_id * feat: update the spec for the previous changes * feat: write tests for the user_tags * feat: add user_tags to for_display adn the query * feat: add user_tags to the endpoint where we query the tags to send it through to for_display * feat: pass through the suer tags to the async request * feat: update the user_tags fiter query + tests * feat: update the admin view to show targeted tags on the new feed option billboards too * feat: add tests for targeted tags field on admin * refactor: consolidate all of the options into one * feat: move comment close to attribute * feat: use a helper method * feat: include helper on ads query * feat: move the query from the frontend to live on the backend * feat: first pass at some error handling whilst maintaining the order of the items * test: for feed error * feat: abstract out some code * update the feed items for errors * chore: comment * feat: update the variable names * feat: update honeybadger message * feat: update the name of the variable * refactor: do not conflate the duty of the untagged_ads * refactor: rename the variables + add note for clarity * fix: update var
189 lines
4.6 KiB
JavaScript
189 lines
4.6 KiB
JavaScript
import { h, render } from 'preact';
|
|
import { Tags } from '../../display-ad/tags';
|
|
|
|
Document.prototype.ready = new Promise((resolve) => {
|
|
if (document.readyState !== 'loading') {
|
|
return resolve();
|
|
}
|
|
document.addEventListener('DOMContentLoaded', () => resolve());
|
|
return null;
|
|
});
|
|
|
|
/**
|
|
* A callback that sets the hidden 'js-tags-textfield' with the selection string that was chosen via the
|
|
* MultiSelectAutocomplete component.
|
|
*
|
|
* @param {String} selectionString The selected tags represented as a string (e.g. "webdev, git, career")
|
|
*/
|
|
function saveTags(selectionString) {
|
|
document.getElementsByClassName('js-tags-textfield')[0].value =
|
|
selectionString;
|
|
}
|
|
|
|
/**
|
|
* Shows and Renders a Tags preact component for the Targeted Tag(s) field
|
|
*/
|
|
function showTagsField() {
|
|
const displayAdsTargetedTags = document.getElementById(
|
|
'display-ad-targeted-tags',
|
|
);
|
|
|
|
if (displayAdsTargetedTags) {
|
|
displayAdsTargetedTags.classList.remove('hidden');
|
|
render(
|
|
<Tags onInput={saveTags} defaultValue={defaultTagValues()} />,
|
|
displayAdsTargetedTags,
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Hides the Targeted Tag(s) field
|
|
*/
|
|
function hideTagsField() {
|
|
const displayAdsTargetedTags = document.getElementById(
|
|
'display-ad-targeted-tags',
|
|
);
|
|
|
|
displayAdsTargetedTags?.classList.add('hidden');
|
|
}
|
|
|
|
/**
|
|
* Clears the content (i.e. value) of the hidden tags textfield
|
|
*/
|
|
function clearTagList() {
|
|
const hiddenTagsField =
|
|
document.getElementsByClassName('js-tags-textfield')[0];
|
|
|
|
hiddenTagsField.value = ' ';
|
|
}
|
|
|
|
/**
|
|
* Returns the value of the hidden text field to eventually pass as
|
|
* default values to the MultiSelectAutocomplete component.
|
|
*/
|
|
function defaultTagValues() {
|
|
let defaultValue = '';
|
|
const hiddenTagsField =
|
|
document.getElementsByClassName('js-tags-textfield')[0];
|
|
|
|
if (hiddenTagsField) {
|
|
defaultValue = hiddenTagsField.value.trim();
|
|
}
|
|
|
|
return defaultValue;
|
|
}
|
|
|
|
function displayUserTargets() {
|
|
const userTargetField = document.getElementsByClassName(
|
|
'js-audience-segment',
|
|
)[0].parentElement;
|
|
if (userTargetField) {
|
|
userTargetField.classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
function hideUserTargets() {
|
|
const userTargetField = document.getElementsByClassName(
|
|
'js-audience-segment',
|
|
)[0].parentElement;
|
|
if (userTargetField) {
|
|
userTargetField.classList.add('hidden');
|
|
}
|
|
}
|
|
|
|
function clearUserTargetSelection() {
|
|
const userTargetSelect = document.getElementsByClassName(
|
|
'js-audience-segment',
|
|
)[0];
|
|
if (userTargetSelect) {
|
|
userTargetSelect.value = '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shows and Renders Exclude Article IDs group
|
|
*/
|
|
function showExcludeIds() {
|
|
const excludeField = document.getElementsByClassName(
|
|
'js-exclude-ids-textfield',
|
|
)[0].parentElement;
|
|
excludeField?.classList.remove('hidden');
|
|
}
|
|
|
|
/**
|
|
* Hides the Exclude Article IDs group
|
|
*/
|
|
function hideExcludeIds() {
|
|
const excludeField = document.getElementsByClassName(
|
|
'js-exclude-ids-textfield',
|
|
)[0].parentElement;
|
|
excludeField?.classList.add('hidden');
|
|
}
|
|
|
|
/**
|
|
* Clears the content (i.e. value) of the Exclude Article IDs group
|
|
*/
|
|
function clearExcludeIds() {
|
|
const excludeField = document.getElementsByClassName(
|
|
'js-exclude-ids-textfield',
|
|
)[0];
|
|
if (excludeField) {
|
|
excludeField.value = '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shows and sets up the Targeted Tag(s) field if the placement area value is "post_comments".
|
|
* Listens for change events on the select placement area dropdown
|
|
* and shows and hides the Targeted Tag(s) appropriately.
|
|
*/
|
|
document.ready.then(() => {
|
|
const select = document.getElementsByClassName('js-placement-area')[0];
|
|
const articleSpecificPlacement = ['post_comments', 'post_sidebar'];
|
|
const targetedTagPlacements = [
|
|
'post_comments',
|
|
'post_sidebar',
|
|
'feed_first',
|
|
'feed_second',
|
|
'feed_third',
|
|
];
|
|
|
|
if (targetedTagPlacements.includes(select.value)) {
|
|
showTagsField();
|
|
}
|
|
|
|
select.addEventListener('change', (event) => {
|
|
if (targetedTagPlacements.includes(event.target.value)) {
|
|
showTagsField();
|
|
} else {
|
|
hideTagsField();
|
|
clearTagList();
|
|
}
|
|
});
|
|
|
|
if (articleSpecificPlacement.includes(select.value)) {
|
|
showExcludeIds();
|
|
}
|
|
|
|
select.addEventListener('change', (event) => {
|
|
if (articleSpecificPlacement.includes(event.target.value)) {
|
|
showExcludeIds();
|
|
} else {
|
|
hideExcludeIds();
|
|
clearExcludeIds();
|
|
}
|
|
});
|
|
|
|
const userRadios = document.querySelectorAll('input[name=display_to]');
|
|
userRadios.forEach((radio) => {
|
|
radio.addEventListener('change', (event) => {
|
|
if (event.target.value == 'logged_in') {
|
|
displayUserTargets();
|
|
} else {
|
|
hideUserTargets();
|
|
clearUserTargetSelection();
|
|
}
|
|
});
|
|
});
|
|
});
|