| 1 |
/** |
| 2 |
* External dependencies |
| 3 |
*/ |
| 4 |
import domReady from '@wordpress/dom-ready'; |
| 5 |
|
| 6 |
/** |
| 7 |
* Internal dependencies |
| 8 |
*/ |
| 9 |
import { getUuidFromVisitorCookie } from '../lib/personalization'; |
| 10 |
|
| 11 |
interface WidgetData { |
| 12 |
data: { |
| 13 |
[key: string]: WidgetRecommendation; |
| 14 |
}; |
| 15 |
} |
| 16 |
|
| 17 |
interface WidgetRecommendation { |
| 18 |
title: string; |
| 19 |
url: string; |
| 20 |
author: string; |
| 21 |
image_url: string; |
| 22 |
thumb_url_medium: string; |
| 23 |
} |
| 24 |
|
| 25 |
interface WidgetOptions { |
| 26 |
url: string; |
| 27 |
outerDiv: Element; |
| 28 |
displayAuthor: boolean; |
| 29 |
displayDirection: string | null; |
| 30 |
imgDisplay: string | null; |
| 31 |
widgetId: string | null; |
| 32 |
} |
| 33 |
|
| 34 |
interface WidgetOptionsGroup { |
| 35 |
[key: string]: WidgetOptions[]; |
| 36 |
} |
| 37 |
|
| 38 |
function constructUrl( apiUrl: string, permalink: string, personalized: boolean ): string { |
| 39 |
if ( personalized ) { |
| 40 |
const uuid = getUuidFromVisitorCookie(); |
| 41 |
if ( uuid ) { |
| 42 |
return `${ apiUrl }&uuid=${ encodeURIComponent( uuid ) }`; |
| 43 |
} |
| 44 |
} |
| 45 |
|
| 46 |
return `${ apiUrl }&url=${ encodeURIComponent( permalink ) }`; |
| 47 |
} |
| 48 |
|
| 49 |
function constructWidget( widget: Element ): WidgetOptions { |
| 50 |
const apiUrl = widget.getAttribute( 'data-parsely-widget-api-url' ) || ''; |
| 51 |
const permalink = widget.getAttribute( 'data-parsely-widget-permalink' ) || ''; |
| 52 |
const personalized = widget.getAttribute( 'data-parsely-widget-personalized' ) === 'true'; |
| 53 |
const url = constructUrl( apiUrl, permalink, personalized ); |
| 54 |
|
| 55 |
return { |
| 56 |
outerDiv: widget, |
| 57 |
url, |
| 58 |
displayAuthor: widget.getAttribute( 'data-parsely-widget-display-author' ) === 'true', |
| 59 |
displayDirection: widget.getAttribute( 'data-parsely-widget-display-direction' ), |
| 60 |
imgDisplay: widget.getAttribute( 'data-parsely-widget-img-display' ), |
| 61 |
widgetId: widget.getAttribute( 'data-parsely-widget-id' ), |
| 62 |
}; |
| 63 |
} |
| 64 |
|
| 65 |
function renderWidget( data: WidgetData, { |
| 66 |
outerDiv, |
| 67 |
displayAuthor, |
| 68 |
displayDirection, |
| 69 |
imgDisplay, |
| 70 |
widgetId, |
| 71 |
}: WidgetOptions ) { |
| 72 |
if ( imgDisplay !== 'none' ) { |
| 73 |
outerDiv.classList.add( 'display-thumbnail' ); |
| 74 |
} |
| 75 |
|
| 76 |
if ( displayDirection ) { |
| 77 |
outerDiv.classList.add( 'list-' + displayDirection ); |
| 78 |
} |
| 79 |
|
| 80 |
const outerList = document.createElement( 'ul' ); |
| 81 |
outerList.className = 'parsely-recommended-widget'; |
| 82 |
outerDiv.appendChild( outerList ); |
| 83 |
|
| 84 |
for ( const [ key, value ] of Object.entries( data.data ) ) { |
| 85 |
const widgetEntry = document.createElement( 'li' ); |
| 86 |
widgetEntry.className = 'parsely-recommended-widget-entry'; |
| 87 |
widgetEntry.setAttribute( 'id', 'parsely-recommended-widget-item' + key ); |
| 88 |
|
| 89 |
const textDiv = document.createElement( 'div' ); |
| 90 |
textDiv.className = 'parsely-text-wrapper'; |
| 91 |
|
| 92 |
const thumbnailImg = document.createElement( 'img' ); |
| 93 |
if ( imgDisplay === 'parsely_thumb' ) { |
| 94 |
thumbnailImg.setAttribute( 'src', value.thumb_url_medium ); |
| 95 |
} else if ( imgDisplay === 'original' ) { |
| 96 |
thumbnailImg.setAttribute( 'src', value.image_url ); |
| 97 |
} |
| 98 |
widgetEntry.appendChild( thumbnailImg ); |
| 99 |
|
| 100 |
const itmId = `?itm_campaign=${ widgetId }`; |
| 101 |
const itmMedium = '&itmMedium=site_widget'; |
| 102 |
const itmSource = '&itmSource=parsely_recommended_widget'; |
| 103 |
const itmContent = '&itm_content=widget_item-' + key; |
| 104 |
const itmLink = value.url + itmId + itmMedium + itmSource + itmContent; |
| 105 |
|
| 106 |
const postTitle = document.createElement( 'div' ); |
| 107 |
postTitle.className = 'parsely-recommended-widget-title'; |
| 108 |
|
| 109 |
const postLink = document.createElement( 'a' ); |
| 110 |
postLink.setAttribute( 'href', itmLink ); |
| 111 |
postLink.textContent = value.title; |
| 112 |
|
| 113 |
postTitle.appendChild( postLink ); |
| 114 |
textDiv.appendChild( postTitle ); |
| 115 |
|
| 116 |
if ( displayAuthor ) { |
| 117 |
const authorLink = document.createElement( 'div' ); |
| 118 |
authorLink.className = 'parsely-recommended-widget-author'; |
| 119 |
authorLink.textContent = value.author; |
| 120 |
|
| 121 |
textDiv.appendChild( authorLink ); |
| 122 |
} |
| 123 |
|
| 124 |
widgetEntry.appendChild( textDiv ); |
| 125 |
outerList.appendChild( widgetEntry ); |
| 126 |
} |
| 127 |
|
| 128 |
outerDiv.appendChild( outerList ); |
| 129 |
outerDiv.closest( '.widget.Recommended_Widget' )?.classList.remove( 'parsely-recommended-widget-hidden' ); |
| 130 |
} |
| 131 |
|
| 132 |
domReady( () => { |
| 133 |
const widgetDOMElements = document.querySelectorAll( '.parsely-recommended-widget' ); |
| 134 |
const widgetObjects = Array.from( widgetDOMElements ).map( ( widget: Element ) => constructWidget( widget ) ); |
| 135 |
|
| 136 |
const widgetsGroupedByUrl: WidgetOptionsGroup = widgetObjects.reduce( ( acc: WidgetOptionsGroup, curr: WidgetOptions ): object => { |
| 137 |
if ( ! acc[ curr.url ] ) { |
| 138 |
acc[ curr.url ] = []; |
| 139 |
} |
| 140 |
acc[ curr.url ].push( curr ); |
| 141 |
return acc; |
| 142 |
}, {} ); |
| 143 |
|
| 144 |
Object.entries( widgetsGroupedByUrl ).forEach( ( [ url, widgets ] ) => { |
| 145 |
fetch( url ) |
| 146 |
.then( ( response ) => response.json() ) |
| 147 |
.then( ( data ) => { |
| 148 |
widgets.forEach( ( widget: WidgetOptions ) => { |
| 149 |
renderWidget( data, widget ); |
| 150 |
} ); |
| 151 |
} ); |
| 152 |
} ); |
| 153 |
} ); |
| 154 |
|