2021-01-29 03:50:49 +01:00
|
|
|
import { ContentfulClientApi, createClient } from 'contentful';
|
|
|
|
import moment from 'moment';
|
2021-02-12 06:37:44 +01:00
|
|
|
import { CMS } from '../constants';
|
2021-02-11 01:38:40 +01:00
|
|
|
import { SideMenuItem, TPages } from '../state/navigation';
|
2021-02-04 06:42:15 +01:00
|
|
|
import { IAuthor, IFigureImage, IPost, ISplitPage } from '../types/cms';
|
2021-01-29 03:50:49 +01:00
|
|
|
|
2021-02-10 09:38:27 +01:00
|
|
|
// Turns CMS IDs into slugs
|
|
|
|
export const slugify = (id: string) => id?.replace(/_/g, '-').toLowerCase();
|
|
|
|
export const unslugify = (slug: string) =>
|
|
|
|
slug.replace(/-/g, '_').toUpperCase();
|
|
|
|
|
2021-02-04 06:42:15 +01:00
|
|
|
export class CmsApi {
|
2021-01-29 03:50:49 +01:00
|
|
|
client: ContentfulClientApi;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.client = createClient({
|
|
|
|
space: process.env.CONTENTFUL_SPACE_ID,
|
|
|
|
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-01-31 11:02:19 +01:00
|
|
|
public async fetchBlogEntries(): Promise<Array<IPost>> {
|
2021-01-29 03:50:49 +01:00
|
|
|
return this.client
|
|
|
|
.getEntries({
|
2021-02-02 06:28:00 +01:00
|
|
|
content_type: 'post', // only fetch blog post entry
|
2021-02-10 02:04:00 +01:00
|
|
|
order: 'sys.createdAt',
|
2021-01-29 03:50:49 +01:00
|
|
|
})
|
|
|
|
.then(entries => {
|
|
|
|
if (entries && entries.items && entries.items.length > 0) {
|
2021-02-11 06:26:56 +01:00
|
|
|
console.log('cms ➡️ entries:', entries);
|
|
|
|
|
2021-01-29 03:50:49 +01:00
|
|
|
const blogPosts = entries.items.map(entry => this.convertPost(entry));
|
2021-02-11 06:26:56 +01:00
|
|
|
|
2021-01-29 03:50:49 +01:00
|
|
|
return blogPosts;
|
|
|
|
}
|
|
|
|
return [];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-01-31 11:02:19 +01:00
|
|
|
public async fetchBlogById(id): Promise<IPost> {
|
2021-01-29 03:50:49 +01:00
|
|
|
return this.client.getEntry(id).then(entry => {
|
|
|
|
if (entry) {
|
2021-02-04 07:19:04 +01:00
|
|
|
return this.convertPost(entry);
|
2021-01-29 03:50:49 +01:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-02-08 00:25:27 +01:00
|
|
|
public async fetchBlogBySlug(slug: string): Promise<IPost> {
|
2021-02-04 07:19:04 +01:00
|
|
|
return this.client
|
|
|
|
.getEntries({
|
2021-02-08 00:25:27 +01:00
|
|
|
content_type: 'post',
|
|
|
|
'fields.slug[in]': slug,
|
2021-02-04 07:19:04 +01:00
|
|
|
})
|
|
|
|
.then(entries => {
|
|
|
|
if (entries && entries.items && entries.items.length > 0) {
|
2021-02-08 00:25:27 +01:00
|
|
|
const post = this.convertPost(entries.items[0]);
|
|
|
|
return post;
|
2021-02-04 07:19:04 +01:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
});
|
2021-02-04 06:42:15 +01:00
|
|
|
}
|
|
|
|
|
2021-02-11 06:26:56 +01:00
|
|
|
public async fetchBlogEntriesByTag(tag: string): Promise<IPost[]> {
|
|
|
|
return this.client
|
|
|
|
.getEntries({
|
|
|
|
content_type: 'post',
|
|
|
|
'fields.tags.sys.id[in]': tag,
|
|
|
|
})
|
|
|
|
.then(entries => {
|
|
|
|
if (entries && entries.items && entries.items.length > 0) {
|
|
|
|
const posts = entries.items.map(entry => this.convertPost(entry));
|
|
|
|
return posts;
|
|
|
|
}
|
|
|
|
return [];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-02-08 00:25:27 +01:00
|
|
|
public async fetchPageEntries(): Promise<TPages> {
|
|
|
|
try {
|
|
|
|
const entries = await this.client.getEntries({
|
|
|
|
content_type: 'splitPage', // only fetch blog post entry
|
2021-02-10 02:04:00 +01:00
|
|
|
order: 'sys.createdAt',
|
2021-02-08 00:25:27 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
if (entries && entries.items && entries.items.length > 0) {
|
|
|
|
const pagesArray = entries.items.map(entry => this.convertPage(entry));
|
|
|
|
|
|
|
|
const pages: TPages = {};
|
|
|
|
pagesArray.forEach(page => {
|
2021-02-11 01:38:40 +01:00
|
|
|
const pageExists = SideMenuItem[page.id];
|
|
|
|
|
|
|
|
if (pageExists) {
|
|
|
|
pages[page.id] = page;
|
|
|
|
}
|
2021-02-08 00:25:27 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
return pages;
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-11 01:38:40 +01:00
|
|
|
public async fetchPageById(id: SideMenuItem): Promise<ISplitPage> {
|
2021-02-02 06:28:00 +01:00
|
|
|
return this.client
|
|
|
|
.getEntries({
|
2021-02-08 00:25:27 +01:00
|
|
|
content_type: 'splitPage',
|
|
|
|
'fields.id[in]': id,
|
2021-02-02 06:28:00 +01:00
|
|
|
})
|
|
|
|
.then(entries => {
|
|
|
|
if (entries && entries.items && entries.items.length > 0) {
|
2021-02-08 00:25:27 +01:00
|
|
|
return this.convertPage(entries.items[0]);
|
2021-02-02 06:28:00 +01:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-01-31 11:02:19 +01:00
|
|
|
public convertImage = (rawImage): IFigureImage =>
|
|
|
|
rawImage
|
|
|
|
? {
|
|
|
|
imageUrl: rawImage.file.url.replace('//', 'http://'), // may need to put null check as well here
|
2021-02-02 06:28:00 +01:00
|
|
|
description: rawImage.description ?? null,
|
|
|
|
title: rawImage.title ?? null,
|
2021-01-31 11:02:19 +01:00
|
|
|
}
|
|
|
|
: null;
|
2021-01-29 03:50:49 +01:00
|
|
|
|
2021-01-31 11:02:19 +01:00
|
|
|
public convertAuthor = (rawAuthor): IAuthor =>
|
|
|
|
rawAuthor
|
|
|
|
? {
|
2021-02-11 06:26:56 +01:00
|
|
|
name: rawAuthor?.name ?? null,
|
2021-02-02 06:28:00 +01:00
|
|
|
avatar: this.convertImage(rawAuthor.avatar.fields),
|
2021-02-11 06:26:56 +01:00
|
|
|
shortBio: rawAuthor?.shortBio ?? null,
|
|
|
|
position: rawAuthor?.position ?? null,
|
|
|
|
email: rawAuthor?.email ?? null,
|
2021-01-31 11:02:19 +01:00
|
|
|
twitter: rawAuthor?.twitter ?? null,
|
2021-02-01 03:57:54 +01:00
|
|
|
facebook: rawAuthor.facebook ?? null,
|
|
|
|
github: rawAuthor.github ?? null,
|
2021-01-31 11:02:19 +01:00
|
|
|
}
|
|
|
|
: null;
|
2021-01-29 03:50:49 +01:00
|
|
|
|
2021-01-31 11:02:19 +01:00
|
|
|
public convertPost = (rawData): IPost => {
|
2021-01-29 03:50:49 +01:00
|
|
|
const rawPost = rawData.fields;
|
2021-02-02 06:28:00 +01:00
|
|
|
const rawFeatureImage = rawPost?.featureImage
|
|
|
|
? rawPost?.featureImage.fields
|
2021-01-29 03:50:49 +01:00
|
|
|
: null;
|
|
|
|
const rawAuthor = rawPost.author ? rawPost.author.fields : null;
|
2021-01-31 11:02:19 +01:00
|
|
|
|
2021-01-29 03:50:49 +01:00
|
|
|
return {
|
2021-02-08 07:37:50 +01:00
|
|
|
id: rawData.sys.id ?? null,
|
|
|
|
body: rawPost.body ?? null,
|
|
|
|
subtitle: rawPost.subtitle ?? null,
|
|
|
|
description: rawPost.description ?? null,
|
2021-02-11 06:26:56 +01:00
|
|
|
publishedDate: moment(rawPost.date).format('DD MMMM YYYY'),
|
2021-01-29 03:50:49 +01:00
|
|
|
slug: rawPost.slug,
|
2021-02-08 07:37:50 +01:00
|
|
|
tags: rawPost?.tags?.map(t => t?.fields?.label) ?? [],
|
2021-01-29 03:50:49 +01:00
|
|
|
title: rawPost.title,
|
|
|
|
featureImage: this.convertImage(rawFeatureImage),
|
|
|
|
author: this.convertAuthor(rawAuthor),
|
|
|
|
};
|
|
|
|
};
|
2021-02-04 07:19:04 +01:00
|
|
|
|
|
|
|
public convertPage = (rawData): ISplitPage => {
|
|
|
|
const rawPage = rawData.fields;
|
|
|
|
const rawHero = rawPage?.hero ? rawPage?.hero?.fields : null;
|
|
|
|
|
|
|
|
return {
|
2021-02-11 01:38:40 +01:00
|
|
|
id: SideMenuItem[rawPage?.id] ?? null,
|
2021-02-10 09:38:27 +01:00
|
|
|
label: rawPage?.label ?? null,
|
|
|
|
title: rawPage?.title ?? null,
|
|
|
|
body: rawPage?.body ?? null,
|
2021-02-04 07:19:04 +01:00
|
|
|
hero: this.convertImage(rawHero),
|
|
|
|
};
|
|
|
|
};
|
2021-01-29 03:50:49 +01:00
|
|
|
}
|
2021-02-12 06:37:44 +01:00
|
|
|
|
|
|
|
interface IShortcodeGeneralButton {
|
|
|
|
href: string;
|
|
|
|
text: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export const extractShortcodeGeneralButton = (
|
|
|
|
value: string,
|
|
|
|
): IShortcodeGeneralButton => {
|
|
|
|
if (!CMS.SHORTCODES.GENERAL_BUTTON.test(value)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pull our href and text
|
|
|
|
};
|