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

View File

@ -11,6 +11,7 @@ export namespace UnbodyGraphQl {
result: string result: string
startPosition: number startPosition: number
} }
interface AdditionalnumbererpretationSource { interface AdditionalnumbererpretationSource {
concept: string concept: string
occurrence: number occurrence: number
@ -22,7 +23,7 @@ export namespace UnbodyGraphQl {
} }
interface AdditionalFeatureProjection { interface AdditionalFeatureProjection {
vector: [number] vector: number[]
} }
interface AdditionalNearestNeighborsNeighbor { interface AdditionalNearestNeighborsNeighbor {
@ -43,11 +44,11 @@ export namespace UnbodyGraphQl {
} }
interface AdditionalClassification { interface AdditionalClassification {
basedOn: [string] basedOn: string[]
classifiedFields: [string] classifiedFields: string[]
completed: string completed: string
id: string id: string
scope: [string] scope: string[]
} }
export interface AdditionalProps { export interface AdditionalProps {
@ -58,7 +59,7 @@ export namespace UnbodyGraphQl {
id: string id: string
lastUpdateTimeUnix: string lastUpdateTimeUnix: string
score: string score: string
vector: [number] vector: number[]
interpretation: Additionalnumbererpretation interpretation: Additionalnumbererpretation
nearestNeighbors: AdditionalNearestNeighbors nearestNeighbors: AdditionalNearestNeighbors
@ -83,6 +84,7 @@ export namespace UnbodyGraphQl {
export namespace Fragments { export namespace Fragments {
export interface TocItem {} export interface TocItem {}
export interface FootnoteItem {} export interface FootnoteItem {}
} }
@ -163,7 +165,7 @@ export namespace UnbodyGraphQl {
organizerEmail: string organizerEmail: string
organizerId: string organizerId: string
organizerSelf: boolean organizerSelf: boolean
recurrence: [string] recurrence: string[]
remoteId: string remoteId: string
sequence: number sequence: number
sourceId: string sourceId: string
@ -176,8 +178,8 @@ export namespace UnbodyGraphQl {
attachments: Array<ImageBlock> attachments: Array<ImageBlock>
} }
export namespace Explore { export namespace Filters {
interface ExploreNearObjectInpObj { interface NearObjectInpObj {
beacon?: string beacon?: string
certainty?: number certainty?: number
distance?: number distance?: number
@ -206,7 +208,7 @@ export namespace UnbodyGraphQl {
force?: number force?: number
} }
interface Txt2VecC11yExploreNearTextInpObj { interface Txt2VecC11yNearTextInpObj {
moveTo?: Txt2VecC11yExploreMoveTo moveTo?: Txt2VecC11yExploreMoveTo
certainty?: number certainty?: number
distance?: number distance?: number
@ -214,24 +216,133 @@ export namespace UnbodyGraphQl {
concepts?: string[] concepts?: string[]
} }
interface ExploreNearVectorInpObj { interface NearVectorInpObj {
distance?: number distance?: number
vector?: number[] vector?: number[]
certainty?: number certainty?: number
} }
interface QnATransformersExploreAskInpObj { interface QnATransformersAskInpObj {
question: string question: string
properties?: string[] properties?: string[]
} }
export interface ExploreArgs { export interface ExploreArgs {
nearObject?: ExploreNearObjectInpObj nearObject?: NearObjectInpObj
nearText?: Txt2VecC11yExploreNearTextInpObj nearText?: Txt2VecC11yNearTextInpObj
ask?: QnATransformersExploreAskInpObj ask?: QnATransformersAskInpObj
offset?: number offset?: number
limit?: 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 UnbodyTextBlock = UnbodyGraphQl.TextBlock
export type UnbodyImageBlock = UnbodyGraphQl.ImageBlock export type UnbodyImageBlock = UnbodyGraphQl.ImageBlock
export type UnbodyAudio = UnbodyGraphQl.AudioFile 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> = { export type UnbodyGraphQlResponse<T> = {
data: { 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 => { const parse = (obj: any): string | number => {
if (typeof obj === 'number') { if (typeof obj === 'number') {
return obj 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)) { if (Array.isArray(obj)) {
const props = obj.map((value) => `${parse(value)}`).join(',') const props = obj.map((value) => `${parse(value)}`).join(',')
return `[${props}]` 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 { GetGoogleDocQuery } from '.'
import { UnbodyExploreArgs } from '@/lib/unbody/unbody.types' import { UnbodyGetFilters } from '@/lib/unbody/unbody.types'
const defaultArgs: UnbodyExploreArgs = { const defaultArgs: UnbodyGetFilters = {
limit: 1, limit: 1,
nearText: { concepts: ['home'] },
} }
export const getArticlePostQuery = (args: UnbodyExploreArgs = defaultArgs) => export const getArticlePostQuery = (args: UnbodyGetFilters = defaultArgs) =>
GetGoogleDocQuery(args)(` GetGoogleDocQuery(args)(`
sourceId sourceId
remoteId remoteId

View File

@ -1,15 +1,14 @@
import { gql } from 'graphql-request' import { gql } from 'graphql-request'
import { GetGoogleDocQuery, GetQuery } from '.' import { GetGoogleDocQuery, GetQuery } from '.'
import { pareseExploreArgs } from '@/lib/unbody/unbody.utils' import { UnbodyGetFilters } from '@/lib/unbody/unbody.types'
import { UnbodyExploreArgs } from '@/lib/unbody/unbody.types'
const defaultArgs: UnbodyExploreArgs = { const defaultArgs: UnbodyGetFilters = {
limit: 10, limit: 10,
nearText: { concepts: ['home'] }, nearText: { concepts: ['home'] },
} }
export const getHomePagePostsQuery = (args: UnbodyExploreArgs = defaultArgs) => export const getHomePagePostsQuery = (args: UnbodyGetFilters = defaultArgs) =>
GetGoogleDocQuery(args)(` GetGoogleDocQuery(args)(`
title title
summary 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 { UnbodyGetFilters } from '@/lib/unbody/unbody.types'
import { pareseExploreArgs } from '@/lib/unbody/unbody.utils' import { parseFilterArgs } from '@/lib/unbody/unbody.utils'
export const GetQuery = (q: string) => `query { Get{ ${q} } }` export const GetQuery = (q: string) => `query { Get{ ${q} } }`
export const GetGoogleDocQuery = (args: UnbodyExploreArgs) => (q: string) => export const GetGoogleDocQuery = (args: UnbodyGetFilters) => (q: string) => {
GetQuery(`GoogleDoc(${pareseExploreArgs(args)}){ ${q} }`) 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 { import {
UnbodyGoogleDoc, UnbodyGoogleDoc,
UnbodyGraphQlResponseGoogleDoc, UnbodyGraphQlResponseGoogleDoc,
UnbodyGetFilters,
} from '@/lib/unbody/unbody.types' } from '@/lib/unbody/unbody.types'
import { UnbodyGraphQl } from '@/lib/unbody/unbody-content.types'
import { getArticlePostQuery } from '@/queries/getPost' import { getArticlePostQuery } from '@/queries/getPost'
import { getHomePagePostsQuery } from '@/queries/getPosts' import { getHomePagePostsQuery } from '@/queries/getPosts'
import { getAllPostsSlugQuery } from '@/queries/getPostsSlugs'
const { UNBODY_API_KEY, UNBODY_LPE_PROJECT_ID } = process.env const { UNBODY_API_KEY, UNBODY_LPE_PROJECT_ID } = process.env
@ -24,10 +29,33 @@ export const getHomepagePosts = (): Promise<HomepagePost[]> => {
.then(({ data }) => data.Get.GoogleDoc) .then(({ data }) => data.Get.GoogleDoc)
} }
export const getArticlePost = (): Promise<HomepagePost[]> => { export const getAllArticlePostSlugs = (): Promise<{ remoteId: string }[]> => {
console.log(getAllPostsSlugQuery())
return unbody return unbody
.request<UnbodyGraphQlResponseGoogleDoc>(getArticlePostQuery()) .request<UnbodyGraphQlResponseGoogleDoc>(getAllPostsSlugQuery())
.then(({ data }) => data.Get.GoogleDoc) .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 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>
}