Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

383 blog authors not showing #396

Merged
merged 5 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions blocks/blog-footer/blog-footer.css
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ ul.authorprofile-socialnetworks {
}

.blogpost .blogfooter-authorprofile {
display: flex;
justify-content: space-around;
margin: 24px 0;
}

Expand Down
97 changes: 40 additions & 57 deletions blocks/blog-footer/blog-footer.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,5 @@
import { loadCSS, toClassName } from '../../scripts/lib-franklin.js';

export async function getProfile() {
const authors = document.head.querySelector('meta[name="authors"]').content;
const profile = {};
let profileQuery = '/profiles/';
profileQuery += toClassName(authors);
profileQuery += '.plain.html';
const response = await fetch(profileQuery);
const profileResponse = await response.text();
if (response.ok) {
const parser = new DOMParser();
const pdoc = parser.parseFromString(profileResponse, 'text/html');
const name = pdoc.querySelector('h1');
const title = pdoc.querySelector('h3');
const image = pdoc.querySelector('body > div > p > picture > img');
profile.name = name.innerHTML;
profile.title = title.innerHTML;
profile.image = image.getAttribute('src');
}
return profile;
}
import getAuthors from '../../scripts/authors.js';

export async function buildBlogFooter(main) {
loadCSS('/blocks/blog-footer/blog-footer.css');
Expand Down Expand Up @@ -97,42 +77,45 @@ export async function buildBlogFooter(main) {
bFooter.append(hrFooter);
const blogfooterAuthor = document.createElement('div');
blogfooterAuthor.setAttribute('class', 'blogfooter-authorprofile');
const author = await getProfile();
blogfooterAuthor.innerHTML = `<div>
<div class="authorprofile-base">
<div class="authorprofile-image">
<div class="nc-image-base">
<div class="nc-image-container" itemtype="http://schema.org/ImageObject">
<img class="nc-image" src="${author.image ?? '/icons/nc.svg'}" itemprop="contentUrl" alt="" sizes="10vw" width="70" height="70">
</div>
</div>
</div>
<div class="authorprofile-info">
<p class="authorprofile-name">${author.name ?? 'Cognizant Netcentric'}</p>
<p class="authorprofile-position">${author.title ?? ''}</p>
<ul class="authorprofile-socialnetworks">
<li class="authorprofile-socialnetwork">
<a href="https://twitter.com/netcentricHQ" target="_blank" rel="noopener noreferrer">
<i class="icons icon-wrapper ">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31.05 31.05"><g data-name="Capa 2"><path d="M15.53 0a15.53 15.53 0 1015.52 15.52A15.52 15.52 0 0015.53 0zM22 12.24v.39a9.44 9.44 0 01-14.55 8 7.3 7.3 0 00.81 0 6.47 6.47 0 004.11-1.41 3.29 3.29 0 01-3.1-2.31 2.55 2.55 0 00.61.08 4.42 4.42 0 00.89-.11 3.36 3.36 0 01-2.69-3.27 3.28 3.28 0 001.53.39 3.16 3.16 0 01-1.49-2.76 3.37 3.37 0 01.45-1.69A9.24 9.24 0 0015.42 13a2.82 2.82 0 01-.09-.71 3.35 3.35 0 013.31-3.37 3.29 3.29 0 012.43 1 6.9 6.9 0 002.11-.79A3.59 3.59 0 0121.72 11a6.86 6.86 0 001.9-.52A8.12 8.12 0 0122 12.24z" data-name="Capa 1"></path></g></svg>
</i>
</a>
</li>
<li class="authorprofile-socialnetwork">
<a href="https://www.linkedin.com/company/cognizantnetcentric" target="_blank" rel="noopener noreferrer">
<i class="icons icon-wrapper ">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><g data-name="Capa 2"><path d="M16 0a16 16 0 1016 16A16 16 0 0016 0zm-3.33 23.23H9.82v-9.87h2.85zm-1.43-10.91a1.75 1.75 0 01-1.73-1.75 1.77 1.77 0 011.73-1.79A1.79 1.79 0 0113 10.56a1.77 1.77 0 01-1.76 1.76zm11.25 10.91h-2.81v-6a1 1 0 00-.48-.81c-1.12-.64-2.29.5-2.29.5v6.33h-2.86v-9.89h2.85v.48a4.22 4.22 0 013.67.1 3.94 3.94 0 011.92 3.29z" data-name="Capa 1"></path></g></svg>
</i>
</a>
</li>
</ul>
</div>
</div>
</div>`;
if (author.name) {
// strip out the social networks for non-nc profiles
blogfooterAuthor.querySelector('.authorprofile-socialnetworks').remove();
}
const authors = await getAuthors();

authors.forEach((author) => {
const authorRootDiv = document.createElement('div');
authorRootDiv.innerHTML = `<div class="authorprofile-base">
<div class="authorprofile-image">
<div class="nc-image-base">
<div class="nc-image-container" itemtype="http://schema.org/ImageObject">
<img class="nc-image" src="${author.image}" itemprop="contentUrl" alt="" sizes="10vw" width="70" height="70">
</div>
</div>
</div>
<div class="authorprofile-info">
<p class="authorprofile-name">${author.name}</p>
<p class="authorprofile-position">${author.role}</p>
<ul class="authorprofile-socialnetworks">
<li class="authorprofile-socialnetwork">
<a href="https://twitter.com/netcentricHQ" target="_blank" rel="noopener noreferrer">
<i class="icons icon-wrapper ">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31.05 31.05"><g data-name="Capa 2"><path d="M15.53 0a15.53 15.53 0 1015.52 15.52A15.52 15.52 0 0015.53 0zM22 12.24v.39a9.44 9.44 0 01-14.55 8 7.3 7.3 0 00.81 0 6.47 6.47 0 004.11-1.41 3.29 3.29 0 01-3.1-2.31 2.55 2.55 0 00.61.08 4.42 4.42 0 00.89-.11 3.36 3.36 0 01-2.69-3.27 3.28 3.28 0 001.53.39 3.16 3.16 0 01-1.49-2.76 3.37 3.37 0 01.45-1.69A9.24 9.24 0 0015.42 13a2.82 2.82 0 01-.09-.71 3.35 3.35 0 013.31-3.37 3.29 3.29 0 012.43 1 6.9 6.9 0 002.11-.79A3.59 3.59 0 0121.72 11a6.86 6.86 0 001.9-.52A8.12 8.12 0 0122 12.24z" data-name="Capa 1"></path></g></svg>
</i>
</a>
</li>
<li class="authorprofile-socialnetwork">
<a href="https://www.linkedin.com/company/cognizantnetcentric" target="_blank" rel="noopener noreferrer">
<i class="icons icon-wrapper ">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><g data-name="Capa 2"><path d="M16 0a16 16 0 1016 16A16 16 0 0016 0zm-3.33 23.23H9.82v-9.87h2.85zm-1.43-10.91a1.75 1.75 0 01-1.73-1.75 1.77 1.77 0 011.73-1.79A1.79 1.79 0 0113 10.56a1.77 1.77 0 01-1.76 1.76zm11.25 10.91h-2.81v-6a1 1 0 00-.48-.81c-1.12-.64-2.29.5-2.29.5v6.33h-2.86v-9.89h2.85v.48a4.22 4.22 0 013.67.1 3.94 3.94 0 011.92 3.29z" data-name="Capa 1"></path></g></svg>
</i>
</a>
</li>
</ul>
</div>
</div>`;
if (author.name) {
// strip out the social networks for non-nc profiles
authorRootDiv.querySelector('.authorprofile-socialnetworks').remove();
}
blogfooterAuthor.appendChild(authorRootDiv);
});
bFooter.append(blogfooterAuthor);
blogpost.appendChild(bFooter);
}
Expand Down
16 changes: 12 additions & 4 deletions blocks/blog-posts/blog-posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ const defaultAuthorName = 'Cognizant Netcentric';
const defaultAuthorRole = '';
const defaultAuthorImage = '/icons/nc.svg';

let profilesCache = null;

async function fetchProfiles() {
if (!profilesCache) {
const response = await fetch('/profiles/query-index.json');
profilesCache = await response.json();
}
return profilesCache;
}

function closePopup(el) {
el.classList.remove('languagepopup--open');
}
Expand Down Expand Up @@ -151,11 +161,9 @@ export function createCardsList(parent, cards = []) {
}

export async function joinArticlesWithProfiles(articles) {
const response = await fetch('/profiles/query-index.json');
const json = await response.json();

const profilesData = await fetchProfiles();
Object.values(articles).forEach((value) => {
value.profiles = json.data.find((profile) => profile.name === value.authors) ?? {};
value.profiles = profilesData.data.find((profile) => profile.name === value.authors) || {};
});

return articles;
Expand Down
102 changes: 49 additions & 53 deletions blocks/blog-sidebar/blog-sidebar.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import { createOptimizedPicture } from '../../scripts/lib-franklin.js';

const defaultAuthorName = 'Cognizant Netcentric';
const defaultAuthorRole = '';
const defaultAuthorImage = '/icons/nc.svg';
import getAuthors from '../../scripts/authors.js';

function getLang() {
return document
.querySelector('html')
.getAttribute('lang');
return document.querySelector('html').getAttribute('lang');
}

function getMetaContent(metadataName) {
return document
.querySelector(`meta[name="${metadataName}"]`)
.getAttribute('content');
return document.querySelector(`meta[name="${metadataName}"]`).getAttribute('content');
}

export default async function decorate(block) {
const authors = getMetaContent('authors');
const date = new Date(getMetaContent('publishdate'));

// TODO when we have blog articles in German we'll need to get the language
const locale = getLang();
const printableDate = date.toLocaleDateString(
locale,
Expand All @@ -31,31 +21,42 @@ export default async function decorate(block) {
},
).toUpperCase();

// TODO cache and share with related-blogs?
const response = await fetch('/profiles/query-index.json');
const json = await response.json();
if (!response.ok) {
// eslint-disable-next-line no-console
console.log('error loading profile blog', response);
return;
}
let authorHTML = '';
const authors = await getAuthors();
const defaultAuthor = { name: 'Cognizant Netcentric', role: '', image: '/icons/nc.svg' };

authors.forEach((authorInfo) => {
if (!authorInfo.role || !authorInfo.image) {
// eslint-disable-next-line no-param-reassign
authorInfo = { ...defaultAuthor };
}

const authorImageAlt = `Picture of ${authorInfo.name}`;
let authorImageHTML = '';

const authorInfo = json.data.find((element) => element.name === authors);
if (authorInfo.image) {
authorImageHTML = createOptimizedPicture(
authorInfo.image,
authorImageAlt,
false,
[{ width: 70 }],
).outerHTML;
}

const authorImageAlt = `Picture of ${authorInfo?.name ?? defaultAuthorName}`;
let authorImageHTML = `<img src="${authorInfo?.image ?? defaultAuthorImage}" alt="${authorImageAlt}" />`;
if (authorInfo?.image) {
authorImageHTML = createOptimizedPicture(
authorInfo.image,
authorImageAlt,
false,
[{ width: 70 }],
).outerHTML;
}
authorHTML += `
<div class="authorprofile">
<div class="image">
${authorImageHTML || `<img src="${defaultAuthor.image}" alt="Author Image">`}
</div>
<div class="info">
<p class="name">${authorInfo.name}</p>
<p class="role">${authorInfo.role}</p>
</div>
</div>
`;
});

const pageURL = window.location.href;
// TODO is twitter title good enough?
// should we check whether it exists and hide the icon otherwise?
const shareText = getMetaContent('twitter:title');
const shareSource = 'netcentric.biz';

Expand All @@ -64,31 +65,26 @@ export default async function decorate(block) {
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
block.querySelector(`.share a.${clazz}`).href = urlPostProcess(url.toString());
};

block.innerHTML = `
<div class="authorprofile">
<div class="image">
${authorImageHTML}
</div>
<div class="info">
<p class="name" >${authorInfo?.name ?? defaultAuthorName}</p>
<p class="role">${authorInfo?.role ?? defaultAuthorRole}</p>
</div>
</div>
<div class="date">${printableDate}</div>
<div class="share">
<p>${window.placeholders?.default?.share || 'SHARE'}</p>
<div>
<a class="facebook"><span class="icon icon-facebook"></span></a>
<a class="twitter"><span class="icon icon-twitter"></span></a>
<a class="linkedin"><span class="icon icon-linkedin"></span></a>
<a class="mail"><span class="icon icon-email"></span></a>
</div>
</div>
${authorHTML}
<div class="date">${printableDate}</div>
<div class="share">
<p>${window.placeholders?.default?.share || 'SHARE'}</p>
<div>
<a class="facebook"><span class="icon icon-facebook"></span></a>
<a class="twitter"><span class="icon icon-twitter"></span></a>
<a class="linkedin"><span class="icon icon-linkedin"></span></a>
<a class="mail"><span class="icon icon-email"></span></a>
</div>
</div>
`;

setShareUrl('facebook', 'http://www.facebook.com/share.php', { u: pageURL });
setShareUrl('twitter', 'http://www.twitter.com/share', { url: pageURL, text: shareText });
setShareUrl('linkedin', 'http://www.linkedin.com/shareArticle?mini=true', { url: pageURL, title: shareText, source: shareSource });
setShareUrl('mail', 'mailto:', { subject: shareText, body: pageURL }, (url) => url.replaceAll('+', '%20'));

const imageElement = block.querySelector('.authorprofile .image img');
imageElement.setAttribute('width', 70);
imageElement.setAttribute('height', 70);
Expand Down
29 changes: 29 additions & 0 deletions scripts/authors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { getMetadata } from './lib-franklin.js';

const defaultAuthor = { name: 'Cognizant Netcentric', role: '', image: '/icons/nc.svg' };
let authors = false;

// TODO use in related-blogs?
export default async function getAuthors() {
if (authors) {
return authors;
}

authors = (async () => {
const response = await fetch('/profiles/query-index.json');
if (!response.ok) {
// eslint-disable-next-line no-console
console.error('error loading profile blog', response);
return { data: [] };
}
return response.json();
})().then((json) => {
const metadata = getMetadata('authors').split(',');
const result = metadata.map((author) => ({
...defaultAuthor,
...json.data.find((element) => element.name.trim() === author.trim()),
}));
return result.length > 0 ? result : [];
});
return authors;
}
1 change: 0 additions & 1 deletion scripts/lib-franklin.js
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,6 @@ export function createElement(tagName, classes, props = {}) {

return element;
}

/**
* init block utils
*/
Expand Down