Skip to content

Commit

Permalink
Merge pull request #1476 from CuBoulder/issue/1391
Browse files Browse the repository at this point in the history
Newsletters: New `Newsletter List Block` and `Newsletter Archive`.  Summary field added to Newsletter: Email
  • Loading branch information
jcsparks authored and web-flow committed Nov 19, 2024
2 parents 4f4d91a + d88ca84 commit c12259f
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 0 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- ### Newsletters: New `Newsletter List Block` and `Newsletter Archive`. Summary field added to Newsletter: Email
Adds the `Newsletter List Block`, which allows aggregation of 1-10 of the most recent Newsletters of the selected type. Will link to the Newsletter Archive.

The Newsletter Archive isn't a content type, it is a route that will exist for any newsletters of the specified type listing them in a paginated view with the title and the summary. The summary will use either the summary field or the first piece of content's title. You can find the Newsletter Archive at `/newsletter/<Newsletter-Type>`

Also adds a Summary field to the Newsletter page, which will be used as a pre-header on the emails and used as a Summary on the Newsletter List Block and Newsletter Archive page.

This should show up after the Subject on an Email in specific clients such as Gmail, iOS, and others ( this will require prod - testing )

Includes:
- `theme` => https://github.com/CuBoulder/tiamat-theme/pull/1476
- `profile` => https://github.com/CuBoulder/tiamat10-profile/pull/231
- `custom-entities` => https://github.com/CuBoulder/tiamat-custom-entities/pull/192

Resolves https://github.com/CuBoulder/tiamat-theme/issues/1391
Resolves https://github.com/CuBoulder/tiamat-theme/issues/1475
---

- ### Expandable url has updates
Series of updates to add functionality to expendables and ckeditor accordions for address bar hash updates.

Expand Down
8 changes: 8 additions & 0 deletions boulder_base.libraries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -519,3 +519,11 @@ colorbox-image:
css/block/image-gallery.css: {}
css/colorbox-image.css: {}
js/glightbox/glightbox.min.css: {}

ucb-newsletter-list-block:
version: 1.x
js:
js/ucb-newsletter-list-block.js: {}
css:
theme:
css/block/ucb-newsletter-list-block.css: {}
14 changes: 14 additions & 0 deletions css/block/ucb-newsletter-list-block.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.ucb-newsletter-list-text{
font-weight: bold;
margin-bottom: 0px;
}

.ucb-newsletter-row{
margin-bottom: 20px;
border-bottom: 1px solid rgba(128, 128, 128, 0.333);
padding-bottom: 20px;
}

.ucb-newsletter-list-summary{
margin-bottom: 0px;
}
20 changes: 20 additions & 0 deletions css/ucb-taxonomy-page.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,23 @@
.feed-icon {
display: none;
}


.ucb-newsletter-list-text{
font-weight: bold;
margin-bottom: 0px;
}

.ucb-newsletter-row{
margin-bottom: 20px;
border-bottom: 1px solid rgba(128, 128, 128, 0.333);
padding-bottom: 20px;
}

.ucb-newsletter-list-summary{
margin-bottom: 0px;
}

.ucb-newsletter-row .row p{
margin-bottom: 0;
}
170 changes: 170 additions & 0 deletions js/ucb-newsletter-list-block.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
(function (customElements) {
class NewsletterListElement extends HTMLElement {
constructor() {
super();
this._baseURI = this.getAttribute('baseURI');
this.count = parseInt(this.getAttribute('count'));
this.newsletterType = this.getAttribute('newsletter-type');
this.taxonomyMap;
this.taxonomyName;
// Fetch taxonomy terms to build the map first
fetch(`${this._baseURI}/jsonapi/taxonomy_term/newsletter`)
.then(response => {
if (!response.ok) throw new Error("Network response was not ok");
return response.json();
})
.then(data => {
// Create the ID-to-name map
this.taxonomyMap = data.data.reduce((map, term) => {
map[term.id] = term.attributes.name;
return map;
}, {});

// Now that the taxonomyMap is ready, fetch newsletters
this.fetchNewsletters();
})
.catch(error => {
console.log("Failed to fetch taxonomy terms:", error);
});
}

fetchNewsletters() {
const publishedParams = '&filter[published][group][conjunction]=AND'
+ '&filter[publish-check][condition][path]=status'
+ '&filter[publish-check][condition][value]=1'
+ '&filter[publish-check][condition][memberOf]=published';

fetch(`${this._baseURI}/jsonapi/node/newsletter?include=field_newsletter_section_block.field_newsletter_section_select.field_newsletter_article_select${publishedParams}&filter[field_newsletter_type.meta.drupal_internal__target_id][value]=${this.newsletterType}&sort=-created`)
.then(this.handleError)
.then((data) => this.build(data, this.count))
.catch(error => {
console.log(error);
});
}

handleError = response => {
if (!response.ok) {
throw new Error("Network response was not ok");
} else {
return response.json();
}
};

// Traverses through nested paragraphs to grab the first one Newsletter -> First Section -> First Newsletter Article or First Newsletter Content. If first article -> get the article
build(data, count) {
const newsletters = data["data"];
const references = data["included"];
const newsletterElements = []; // Array to hold newsletter elements

// Loop through newsletters up to the specified count
for (let i = 0; i < Math.min(newsletters.length, count); i++) {
const newsletter = newsletters[i];
const newsletterTitle = newsletter.attributes.title;

// Get the path using taxonomy and title
const taxonomyId = newsletter.relationships.field_newsletter_type?.data.id;
this.taxonomyName = this.taxonomyMap[taxonomyId];
const path = newsletter.attributes.path.alias
? newsletter.attributes.path.alias
: `/node/${newsletter.attributes.drupal_internal__nid}`;

// Check for a summary field in the newsletter
let summary = newsletter.attributes.field_newsletter_summary;
// If no summary is present, fall back to content processing
if (!summary) {
const sectionBlockRef = newsletter.relationships.field_newsletter_section_block?.data[0];
if (sectionBlockRef) {
const sectionBlock = references.find(
ref => ref.id === sectionBlockRef.id && ref.type === 'paragraph--newsletter_section'
);

if (sectionBlock) {
// Access the array of section items in the section block
const sectionSelectRefs = sectionBlock.relationships?.field_newsletter_section_select?.data;

if (sectionSelectRefs && sectionSelectRefs.length > 0) {
// Loop through section items and find the first valid content
for (const sectionSelectRef of sectionSelectRefs) {
const sectionContent = references.find(ref => ref.id === sectionSelectRef.id);

if (sectionContent) {
// Check if the section content is a paragraph or article and get the title
if (sectionContent.type === 'paragraph--newsletter_section_content') {
summary = sectionContent.attributes.field_newsletter_content_title;
} else if (sectionContent.type === 'paragraph--newsletter_section_article') {
const articleRef = sectionContent.relationships?.field_newsletter_article_select?.data;

if (articleRef) {
const article = references.find(
ref => ref.id === articleRef.id && ref.type === 'node--ucb_article'
);
if (article) {
summary = article.attributes.title;
}
}
}

// Exit the loop once a valid summary is found
if (summary) {
break;
}
}
}
}
}
}
}

// Store the newsletter information
newsletterElements.push({ title: newsletterTitle, summary, path });
}

// Build DOM elements for each newsletter
this.renderNewsletters(newsletterElements);
this.renderButton(this.taxonomyName);
}


// This will create the Newsletter Rows
renderNewsletters(newsletterElements) {
newsletterElements.forEach(newsletter => {
const newsletterElement = document.createElement('div');
newsletterElement.classList.add('ucb-newsletter-row');

const linkElement = document.createElement('a');
linkElement.href = newsletter.path;
linkElement.classList.add('ucb-newsletter-list-link');


const titleElement = document.createElement('p');
titleElement.textContent = newsletter.title;
titleElement.classList.add('ucb-newsletter-list-text');

linkElement.appendChild(titleElement);

const summaryElement = document.createElement('p');
summaryElement.textContent = newsletter.summary;
summaryElement.classList.add('ucb-newsletter-list-summary');

newsletterElement.appendChild(linkElement);
newsletterElement.appendChild(summaryElement);
this.appendChild(newsletterElement);
});
}

// This will create the Archive Link
renderButton(taxonomyName){
const buttonElement = document.createElement('a');
const urlName = taxonomyName
.toLowerCase() // lower
.replace(/[^\w\s-]/g, '') // remove special chars
.replace(/\s+/g, '-'); // spaces => -
buttonElement.href = `${this._baseURI}/newsletter/${urlName}`;
buttonElement.innerText = `${taxonomyName} Archive`;
this.appendChild(buttonElement);
}
}

customElements.define('ucb-newsletter-list', NewsletterListElement);

})(window.customElements);
23 changes: 23 additions & 0 deletions templates/block/block--ucb-newsletter-list-block.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{% set classes = [
'block',
'container',
'block-' ~ configuration.provider|clean_class,
'block-' ~ plugin_id|clean_class,
bundle ? 'block--type-' ~ bundle|clean_class,
view_mode ? 'block--view-mode-' ~ view_mode|clean_class,
] %}

{% extends '@boulder_base/block/styled-block.html.twig' %}

{% set baseurlJSON = url('<front>')|render|trim('/') %}

{% block content %}
{{ attach_library('boulder_base/ucb-newsletter-list-block') }}
{{ content.body }}
<ucb-newsletter-list
baseURI="{{baseurlJSON}}"
count="{{content.field_ucb_newsletter_list_count|render|striptags|trim}}"
newsletter-type="{{content.field_select_newsletter_lis_type|render|striptags|trim}}"
>
</ucb-newsletter-list>
{% endblock %}
17 changes: 17 additions & 0 deletions templates/content/node--newsletter--email-html.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -341,11 +341,28 @@ h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6 {
display: block;
}
}
/* Preheader Style -- this appears after the subject line */
.preheader{
display: none !important;
visibility: hidden;
opacity: 0;
height: 0;
width: 0;
}
</style>
</head>
{# END VARIABLE TESTS #}
{# BIG Wrapper #}
<div id="email" style="align-items:center;{{emailBackground}}">
<!--PRE-HEADER TEXT-->
{% if node.field_newsletter_summary.value %}
<span
style="display: none !important;visibility: hidden;opacity: 0;height: 0;width: 0;"
class="preheader">
{{ node.field_newsletter_summary.value }}
</span>
{% endif %}
<div id="ucb-email-body" style="margin: auto;{{divStyles}}" data-url="{{base_url}}">
{# HEADER -- to do: might need to be different tables for styling purposes #}
<!-- Header -->
Expand Down

0 comments on commit c12259f

Please sign in to comment.