diff options
Diffstat (limited to 'src/services/graphql')
| -rw-r--r-- | src/services/graphql/topics.query.ts | 7 | ||||
| -rw-r--r-- | src/services/graphql/topics.ts | 135 | 
2 files changed, 136 insertions, 6 deletions
| diff --git a/src/services/graphql/topics.query.ts b/src/services/graphql/topics.query.ts index 6cc525e..19be5d7 100644 --- a/src/services/graphql/topics.query.ts +++ b/src/services/graphql/topics.query.ts @@ -16,6 +16,13 @@ export const topicBySlugQuery = `query TopicBy($slug: ID!) {                }              }            } +          author { +            node { +              gravatarUrl +              name +              url +            } +          }            commentCount            contentParts {              beforeMore diff --git a/src/services/graphql/topics.ts b/src/services/graphql/topics.ts index 0f59bad..3c92442 100644 --- a/src/services/graphql/topics.ts +++ b/src/services/graphql/topics.ts @@ -1,6 +1,20 @@ -import { RawTopicPreview, TotalItems } from '@ts/types/raw-data'; +import { PageLink, Slug, Topic } from '@ts/types/app'; +import { +  RawArticle, +  RawTopic, +  RawTopicPreview, +  TotalItems, +} from '@ts/types/raw-data'; +import { getImageFromRawData } from '@utils/helpers/images'; +import { getPageLinkFromRawData } from '@utils/helpers/pages';  import { EdgesResponse, EdgesVars, fetchAPI, getAPIUrl } from './api'; -import { topicsListQuery, totalTopicsQuery } from './topics.query'; +import { getArticleFromRawData } from './articles'; +import { +  topicBySlugQuery, +  topicsListQuery, +  topicsSlugQuery, +  totalTopicsQuery, +} from './topics.query';  /**   * Retrieve the total number of topics. @@ -34,9 +48,118 @@ export const getTopicsPreview = async (    return response.topics;  }; -export const getAllTopicsLinks = async () => { -  const allTopics = []; -  const initialTopics = await getTopicsPreview({ first: 1 }); +/** + * Convert raw data to a Topic object. + * + * @param {RawTopic} data - The page raw data. + * @returns {Topic} The page data. + */ +export const getTopicFromRawData = (data: RawTopic): Topic => { +  const { +    acfTopics, +    contentParts, +    databaseId, +    date, +    featuredImage, +    info, +    modified, +    slug, +    title, +    seo, +  } = data; + +  /** +   * Retrieve an array of related topics. +   * +   * @param posts - The topic posts. +   * @returns {PageLink[]} An array of topics links. +   */ +  const getRelatedThematics = (posts: RawArticle[]): PageLink[] => { +    const thematics: PageLink[] = []; + +    posts.forEach((post) => { +      if (post.acfPosts.postsInThematic) { +        post.acfPosts.postsInThematic.forEach((thematic) => +          thematics.push(getPageLinkFromRawData(thematic)) +        ); +      } +    }); + +    const thematicsIds = thematics.map((thematic) => thematic.id); +    const uniqueThematics = thematics.filter( +      ({ id }, index) => !thematicsIds.includes(id, index + 1) +    ); +    const sortThematicByName = (a: PageLink, b: PageLink) => { +      var nameA = a.name.toUpperCase(); // ignore upper and lowercase +      var nameB = b.name.toUpperCase(); // ignore upper and lowercase +      if (nameA < nameB) { +        return -1; +      } +      if (nameA > nameB) { +        return 1; +      } + +      // names must be equal +      return 0; +    }; + +    return uniqueThematics.sort(sortThematicByName); +  }; + +  return { +    content: contentParts.afterMore, +    id: databaseId, +    intro: contentParts.beforeMore, +    meta: { +      articles: acfTopics.postsInTopic.map((post) => +        getArticleFromRawData(post) +      ), +      cover: featuredImage?.node +        ? getImageFromRawData(featuredImage.node) +        : undefined, +      dates: { publication: date, update: modified }, +      website: acfTopics.officialWebsite, +      readingTime: info.readingTime, +      seo: { +        description: seo?.metaDesc || '', +        title: seo?.title || '', +      }, +      thematics: getRelatedThematics(acfTopics.postsInTopic), +      wordsCount: info.wordsCount, +    }, +    slug, +    title, +  }; +}; + +/** + * Retrieve a Topic object by slug. + * + * @param {string} slug - The topic slug. + * @returns {Promise<Article>} The requested topic. + */ +export const getTopicBySlug = async (slug: string): Promise<Topic> => { +  const response = await fetchAPI<RawTopic, typeof topicBySlugQuery>({ +    api: getAPIUrl(), +    query: topicBySlugQuery, +    variables: { slug }, +  }); + +  return getTopicFromRawData(response.topic); +}; + +/** + * Retrieve all the topics slugs. + * + * @returns {Promise<string[]>} - An array of topics slugs. + */ +export const getAllTopicsSlugs = async (): Promise<string[]> => { +  const totalTopics = await getTotalTopics(); +  const response = await fetchAPI<Slug, typeof topicsSlugQuery>({ +    api: getAPIUrl(), +    query: topicsSlugQuery, +    variables: { first: totalTopics }, +  }); -  if (!initialTopics.pageInfo.hasNextPage) return initialTopics; +  return response.topics.edges.map((edge) => edge.node.slug);  }; | 
