Merge pull request #8 from acid-info/getarticlepost

add getarticlepost
This commit is contained in:
amir houieh 2023-05-08 15:49:43 +02:00 committed by GitHub
commit 76aeba9fdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 273 additions and 115 deletions

View File

@ -1,30 +1,28 @@
import { Article } from '@/components/Article'
import { TableOfContents } from '@/components/TableOfContents'
import { ArticleProps } from '@/pages/article/[slug]'
import styled from '@emotion/styled'
import { useState } from 'react'
import { uiConfigs } from '@/configs/ui.configs'
import { ArticleContainerContext } from '@/containers/ArticleContainer.Context'
import { UnbodyGoogleDoc } from '@/lib/unbody/unbody.types'
const ArticleContainer = (props: ArticleProps) => {
const { post } = props
interface Props {
data: UnbodyGoogleDoc
}
const ArticleContainer = (props: Props) => {
const { data } = props
const [tocIndex, setTocIndex] = useState(0)
return (
<Container>
{typeof post !== 'undefined' ? (
<ArticleContainerContext.Provider
value={{ tocIndex: tocIndex, setTocIndex: setTocIndex }}
>
<TableOfContents contents={post.toc ?? []} />
<Article data={post} />
<Right />
</ArticleContainerContext.Provider>
) : (
<div style={{ marginTop: '108px', textAlign: 'center' }}>
<h3>Loading</h3>
</div>
)}
<ArticleContainerContext.Provider
value={{ tocIndex: tocIndex, setTocIndex: setTocIndex }}
>
<TableOfContents contents={data.toc ?? []} />
{/*<Article data={data} />*/}
<Right />
</ArticleContainerContext.Provider>
</Container>
)
}

View File

@ -11,6 +11,7 @@ export namespace UnbodyGraphQl {
result: string
startPosition: number
}
interface AdditionalnumbererpretationSource {
concept: string
occurrence: number
@ -22,7 +23,7 @@ export namespace UnbodyGraphQl {
}
interface AdditionalFeatureProjection {
vector: [number]
vector: number[]
}
interface AdditionalNearestNeighborsNeighbor {
@ -43,11 +44,11 @@ export namespace UnbodyGraphQl {
}
interface AdditionalClassification {
basedOn: [string]
classifiedFields: [string]
basedOn: string[]
classifiedFields: string[]
completed: string
id: string
scope: [string]
scope: string[]
}
export interface AdditionalProps {
@ -58,7 +59,7 @@ export namespace UnbodyGraphQl {
id: string
lastUpdateTimeUnix: string
score: string
vector: [number]
vector: number[]
interpretation: Additionalnumbererpretation
nearestNeighbors: AdditionalNearestNeighbors
@ -83,6 +84,7 @@ export namespace UnbodyGraphQl {
export namespace Fragments {
export interface TocItem {}
export interface FootnoteItem {}
}
@ -163,7 +165,7 @@ export namespace UnbodyGraphQl {
organizerEmail: string
organizerId: string
organizerSelf: boolean
recurrence: [string]
recurrence: string[]
remoteId: string
sequence: number
sourceId: string
@ -176,8 +178,8 @@ export namespace UnbodyGraphQl {
attachments: Array<ImageBlock>
}
export namespace Explore {
interface ExploreNearObjectInpObj {
export namespace Filters {
interface NearObjectInpObj {
beacon?: string
certainty?: number
distance?: number
@ -206,7 +208,7 @@ export namespace UnbodyGraphQl {
force?: number
}
interface Txt2VecC11yExploreNearTextInpObj {
interface Txt2VecC11yNearTextInpObj {
moveTo?: Txt2VecC11yExploreMoveTo
certainty?: number
distance?: number
@ -214,24 +216,133 @@ export namespace UnbodyGraphQl {
concepts?: string[]
}
interface ExploreNearVectorInpObj {
interface NearVectorInpObj {
distance?: number
vector?: number[]
certainty?: number
}
interface QnATransformersExploreAskInpObj {
interface QnATransformersAskInpObj {
question: string
properties?: string[]
}
export interface ExploreArgs {
nearObject?: ExploreNearObjectInpObj
nearText?: Txt2VecC11yExploreNearTextInpObj
ask?: QnATransformersExploreAskInpObj
nearObject?: NearObjectInpObj
nearText?: Txt2VecC11yNearTextInpObj
ask?: QnATransformersAskInpObj
offset?: number
limit?: number
nearVector?: ExploreNearVectorInpObj
nearVector?: NearVectorInpObj
}
enum GroupInpObjTypeEnum {
closest = 'closest',
merge = 'merge',
}
export interface GroupInpObj {
force: number
type: GroupInpObjTypeEnum
}
export interface HybridInpObj {
query: string
alpha: number
vector: number[]
}
interface WhereGeoRangeGeoCoordinatesInpObj {
latitude: number
longitude: number
}
interface WhereGeoRangeDistanceInpObj {
max: number
}
export interface WhereGeoRangeInpObj {
geoCoordinates: WhereGeoRangeGeoCoordinatesInpObj
distance: WhereGeoRangeDistanceInpObj
}
export enum WhereOperatorEnum {
GreaterThanEqual = 'GreaterThanEqual',
WithinGeoRange = 'WithinGeoRange',
IsNull = 'IsNull',
And = 'And',
Like = 'Like',
Not = 'Not',
NotEqual = 'NotEqual',
GreaterThan = 'GreaterThan',
LessThan = 'LessThan',
LessThanEqual = 'LessThanEqual',
Or = 'Or',
Equal = 'Equal',
}
export interface WhereOperandsInpObj {
operator?: WhereOperatorEnum
path: [String]
operands?: [WhereOperandsInpObj]
valueGeoRange?: WhereGeoRangeInpObj
valueNumber?: number
valueBoolean?: boolean
valueString?: string
valueText?: string
valueDate?: string
valueInt?: number
}
export enum ObjTypeEnum {
asc = 'asc',
desc = 'desc',
}
export interface Bm25InpObj {
properties?: string[]
query: string
}
export interface AskInpObj {
question: string
properties?: string[]
}
export interface SortInpObj {
path: string[]
order: string
}
export interface WhereInpObj {
path: string[]
valueInt?: number
valueNumber?: number
valueGeoRange?: WhereGeoRangeInpObj
operator?: WhereOperatorEnum
operands?: WhereOperandsInpObj[]
valueBoolean?: boolean
valuestring?: string
valueDate?: string
valueText?: string
valueString?: string
}
export interface GetDocsArgs {
where?: WhereInpObj
bm25?: Bm25InpObj
ask?: AskInpObj
sort?: ObjTypeEnum[]
nearText?: Txt2VecC11yNearTextInpObj
nearVector?: NearVectorInpObj
nearObject?: NearObjectInpObj
offset?: number
limit?: number
group?: GroupInpObj
hybrid?: HybridInpObj
}
}
}

View File

@ -5,7 +5,9 @@ export type UnbodyGoogleCalendarEvent = UnbodyGraphQl.GoogleCalendarEvent
export type UnbodyTextBlock = UnbodyGraphQl.TextBlock
export type UnbodyImageBlock = UnbodyGraphQl.ImageBlock
export type UnbodyAudio = UnbodyGraphQl.AudioFile
export type UnbodyExploreArgs = UnbodyGraphQl.Explore.ExploreArgs
export type UnbodyGetFilters = UnbodyGraphQl.Filters.GetDocsArgs
export * as UnbodyGraphQl from './unbody-content.types'
export type UnbodyGraphQlResponse<T> = {
data: {

View File

@ -1,11 +1,23 @@
import { UnbodyExploreArgs } from './unbody.types'
import { UnbodyGetFilters } from './unbody.types'
import { UnbodyGraphQl } from './unbody-content.types'
export const pareseExploreArgs = (args: UnbodyExploreArgs = {}): string => {
const operators = Object.values(UnbodyGraphQl.Filters.WhereOperatorEnum)
export const parseFilterArgs = (args: UnbodyGetFilters = {}): string => {
const parse = (obj: any): string | number => {
if (typeof obj === 'number') {
return obj
}
if (
typeof obj === 'string' &&
operators.includes(obj as UnbodyGraphQl.Filters.WhereOperatorEnum)
) {
return obj
}
//TODO needs to be improved in order to support more complex queries
if (Array.isArray(obj)) {
const props = obj.map((value) => `${parse(value)}`).join(',')
return `[${props}]`

View File

@ -0,0 +1,59 @@
import { GetStaticPropsContext } from 'next'
import { ArticleLayout } from '@/layouts/ArticleLayout'
import { ReactNode } from 'react'
import ArticleContainer from '@/containers/ArticleContainer'
import { UnbodyGoogleDoc, UnbodyImageBlock } from '@/lib/unbody/unbody.types'
import {
getAllArticlePostSlugs,
getArticlePost,
} from '@/services/unbody.service'
import { ArticlePostData } from '@/types/data.types'
type ArticleProps = {
data: ArticlePostData | null
error: string | null
}
export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
const { remoteId } = params!
if (!remoteId) {
return {
notFound: true,
}
}
const article = await getArticlePost(remoteId as string)
return {
props: {
data: article,
error: !!article,
},
}
}
// @jinho lets handle the error directly in thew page component
const ArticlePage = (props: ArticleProps) => {
if (!props.data) return <div>Opps...</div>
return (
<div>{props.data.title}</div>
// <ArticleContainer post={props.data}
// error={props.error}
// />
)
}
export async function getStaticPaths() {
const posts = await getAllArticlePostSlugs()
return {
paths: posts.map((post) => ({ params: { remoteId: `${post.remoteId}` } })),
fallback: true,
}
}
ArticlePage.getLayout = function getLayout(page: ReactNode) {
return <ArticleLayout>{page}</ArticleLayout>
}
export default ArticlePage

View File

@ -1,67 +0,0 @@
import { GetStaticPropsContext } from 'next'
import { ArticleLayout } from '@/layouts/ArticleLayout'
import { ReactNode } from 'react'
import ArticleContainer from '@/containers/ArticleContainer'
import { UnbodyGoogleDoc, UnbodyImageBlock } from '@/lib/unbody/unbody.types'
import { getArticlePost } from '@/services/unbody.service'
import { PostDataProps } from '@/components/Post/Post'
export type ArticleProps = {
post: PostDataProps
error: string | null
}
export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
const slug = params?.slug
console.log('slug', slug) // TODO : fetch data based on slug
let post: Partial<UnbodyGoogleDoc> = {}
let error = null
try {
const posts = await getArticlePost()
post = posts[0]
} catch (e) {
error = JSON.stringify(e)
}
return {
props: {
post: {
date: post.modifiedAt,
title: post.title,
summary: post.summary,
//@ts-ignore
blocks: post.blocks
?.map((block) => `${block.html}\n`)
.slice(2)
.join(''), // temporary solution for HTML/CSS work
author: 'Cameron Williamson',
authorEmail: 'leo@acid.info',
tags: ['Tools', 'Cyber Punk', 'Docs'],
//@ts-ignore
toc: JSON.parse(post?.toc),
...(post.blocks && post.blocks!.length > 0
? { coverImage: post.blocks![0] as UnbodyImageBlock }
: {}),
},
error,
},
}
}
const ArticlePage = (props: ArticleProps) => {
return <ArticleContainer post={props.post} error={props.error} />
}
export async function getStaticPaths() {
return {
paths: [{ params: { slug: 'sth' } }],
fallback: true,
}
}
ArticlePage.getLayout = function getLayout(page: ReactNode) {
return <ArticleLayout>{page}</ArticleLayout>
}
export default ArticlePage

View File

@ -1,12 +1,11 @@
import { GetGoogleDocQuery } from '.'
import { UnbodyExploreArgs } from '@/lib/unbody/unbody.types'
import { UnbodyGetFilters } from '@/lib/unbody/unbody.types'
const defaultArgs: UnbodyExploreArgs = {
const defaultArgs: UnbodyGetFilters = {
limit: 1,
nearText: { concepts: ['home'] },
}
export const getArticlePostQuery = (args: UnbodyExploreArgs = defaultArgs) =>
export const getArticlePostQuery = (args: UnbodyGetFilters = defaultArgs) =>
GetGoogleDocQuery(args)(`
sourceId
remoteId

View File

@ -1,15 +1,14 @@
import { gql } from 'graphql-request'
import { GetGoogleDocQuery, GetQuery } from '.'
import { pareseExploreArgs } from '@/lib/unbody/unbody.utils'
import { UnbodyExploreArgs } from '@/lib/unbody/unbody.types'
import { UnbodyGetFilters } from '@/lib/unbody/unbody.types'
const defaultArgs: UnbodyExploreArgs = {
const defaultArgs: UnbodyGetFilters = {
limit: 10,
nearText: { concepts: ['home'] },
}
export const getHomePagePostsQuery = (args: UnbodyExploreArgs = defaultArgs) =>
export const getHomePagePostsQuery = (args: UnbodyGetFilters = defaultArgs) =>
GetGoogleDocQuery(args)(`
title
summary

View File

@ -0,0 +1,9 @@
import { GetGoogleDocQuery } from '.'
import { UnbodyGetFilters } from '@/lib/unbody/unbody.types'
const defaultArgs: UnbodyGetFilters = {}
export const getAllPostsSlugQuery = (args: UnbodyGetFilters = defaultArgs) =>
GetGoogleDocQuery(args)(`
remoteId
`)

View File

@ -1,7 +1,9 @@
import { UnbodyExploreArgs } from '@/lib/unbody/unbody.types'
import { pareseExploreArgs } from '@/lib/unbody/unbody.utils'
import { UnbodyGetFilters } from '@/lib/unbody/unbody.types'
import { parseFilterArgs } from '@/lib/unbody/unbody.utils'
export const GetQuery = (q: string) => `query { Get{ ${q} } }`
export const GetGoogleDocQuery = (args: UnbodyExploreArgs) => (q: string) =>
GetQuery(`GoogleDoc(${pareseExploreArgs(args)}){ ${q} }`)
export const GetGoogleDocQuery = (args: UnbodyGetFilters) => (q: string) => {
if (Object.keys(args).length === 0) return GetQuery(`GoogleDoc{ ${q} }`)
return GetQuery(`GoogleDoc(${parseFilterArgs(args)}){ ${q} }`)
}

View File

@ -2,9 +2,14 @@ import { UnbodyClient } from '@/lib/unbody/client.class'
import {
UnbodyGoogleDoc,
UnbodyGraphQlResponseGoogleDoc,
UnbodyGetFilters,
} from '@/lib/unbody/unbody.types'
import { UnbodyGraphQl } from '@/lib/unbody/unbody-content.types'
import { getArticlePostQuery } from '@/queries/getPost'
import { getHomePagePostsQuery } from '@/queries/getPosts'
import { getAllPostsSlugQuery } from '@/queries/getPostsSlugs'
const { UNBODY_API_KEY, UNBODY_LPE_PROJECT_ID } = process.env
@ -24,10 +29,33 @@ export const getHomepagePosts = (): Promise<HomepagePost[]> => {
.then(({ data }) => data.Get.GoogleDoc)
}
export const getArticlePost = (): Promise<HomepagePost[]> => {
export const getAllArticlePostSlugs = (): Promise<{ remoteId: string }[]> => {
console.log(getAllPostsSlugQuery())
return unbody
.request<UnbodyGraphQlResponseGoogleDoc>(getArticlePostQuery())
.request<UnbodyGraphQlResponseGoogleDoc>(getAllPostsSlugQuery())
.then(({ data }) => data.Get.GoogleDoc)
}
export const getArticlePost = (id: string): Promise<UnbodyGoogleDoc> => {
const query = getArticlePostQuery({
where: {
path: ['remoteId'],
operator: UnbodyGraphQl.Filters.WhereOperatorEnum.Equal,
valueString: id,
},
})
return unbody
.request<UnbodyGraphQlResponseGoogleDoc>(getArticlePostQuery())
.then(({ data }) => {
const article = data.Get.GoogleDoc[0]
return {
...article,
toc: JSON.parse(
article.toc as string,
) as Array<UnbodyGraphQl.Fragments.TocItem>,
}
})
}
export default unbody

6
src/types/data.types.ts Normal file
View File

@ -0,0 +1,6 @@
import { UnbodyGoogleDoc } from '@/lib/unbody/unbody.types'
import { UnbodyGraphQl } from '@/lib/unbody/unbody-content.types'
export interface ArticlePostData extends UnbodyGoogleDoc {
toc: Array<UnbodyGraphQl.Fragments.TocItem>
}