ブログ用にNotionDBを使って記事を管理するeasy-notion-blog。
「記事以外もNotionDBで管理したい」と思ったことはありませんか??
実を言うとだいぶ前からその願望があり…..
複数のNotionAPIを使いこなす方法が分からず
苦し紛れに別サーバーで用意したものを埋め込む….といったことをしていました。
見るだけなら不自由ないのですが、
クリックするとエラーになってしまう….
という問題を抱えていました。
思い切って再チャレンジしてみるか…..
学んだことを出し切れば….
なんとかなるのでは….????
と数カ月ぶりにやる気になり、
改造してみたら上手くいきました⭐
解説します\(^o^)/
Next.jsのサンプルページからNotionAPIを使って
1ページで実装する【流れ】がよく分かる動画です。
そこから表示させたいNotionDBのプロパティを追加して….
表示させたい行は….この2行!!!
Filter処理して…..
実装してみます。
コードにするとこんな感じです。
import type { NextPage } from 'next'
import Link from 'next/link'
import {Client}from"@notionhq/client"
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import Pstyles from '../styles/posting.module.css'
type Help={
title:string;
description:string;
date:string;
tags:string;
last_edit:string;
URL:string;
site:string;
siteCollor:string;
}
export async function getStaticProps(){
const herotoken="***** NOTION_API_SECRET ******";
const herodatabaseId="******* DATABASE_ID *******";
const heronotion = new Client({ auth: herotoken });
const data = await heronotion.databases.query({
database_id: herodatabaseId,
filter: {
property: 'tags',
select: {
equals: "posting",
}
},
sorts:[{
property: 'date',
direction: 'descending',
},],
});
const helpList: Help[]=data.results.map((_:any)=>_.properties).map(_=>{
return{
date: _.date.date.start,
title: _.title.title[0].plain_text,
description: _.description.rich_text[0].plain_text,
tags: _.tags.select.name,
last_edit: _.last_edit.last_edited_time,
URL: _.URL.url,
site: _.site.select.name,
siteCollor: _.site.select.color
};
});
return {props:{helpList},revalidate:30};
}
type Props={
helpList:Help[];
};
const Home = ({helpList}:Props) => {
return (
<div className={styles.container}>
<Head>
<title>Posting App</title>
<meta name="description" content="Generated by Posting app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<p>▼ こちらはherohoroブログ以外で投稿した時に更新します。</p>
<h1 className={styles.title}>
External Posting
</h1>
<p className={styles.description}>
From NotionDB{' '}
<code className={styles.code}>pages/posting.tsx</code>
</p>
<h3>気になるcardをクリックすると記事へ飛べるよー</h3>
{/* gridのクラス名が効かない....siteCollorも効かない */}
<div className={Pstyles.grid}>
{helpList.map((_)=>(
<div className={Pstyles.card} key={_.title}>
<div className={styles.siteCollor} >
<div className={`${_.siteCollor}`}>
<p>{_.site}</p>
</div>
</div>
<h3>{_.date}</h3>
<Link href={_.URL} passHref><p>📝 {_.title}</p></Link>
<p>😙 {(_.description)?(_.description):null}</p>
<hr/>
{/* <p>last edit : {_.last_edit}</p> */}
</div>
))}
</div>
</main>
</div>
)
}
export default Home
これをeasy-notion-blogに導入するには…..
libやgetStaticPropsなどの組み方に調整する必要があります。(ここでずっと詰まってました)
以前投稿した
「Notion APIの公式リファレンスを徹底的に根拠付けしながらブログにtitle,text,dateを一覧にして表示させる方法_Blog learn03」
の流れに沿って実装したら上手くいったので、
今回はその流れに沿って解説していきます。\(^o^)/
ブログ用のDBを設定した時と同じく2つの文字列を設定します。
※ 今回は2つ目の文字列…ということで文頭に「SEC_ 」と付けてます
この2つの文字列を….
開発環境:
SEC_NOTION_API_SECRET=
SEC_DATABASE_ID=
本番環境:
追加します\(^o^)/
追加した環境変数を取り出しやすくするためにsever-containts.js
をいじります。
const path = require('path')
const NOTION_API_SECRET = process.env.NOTION_API_SECRET
const DATABASE_ID = process.env.DATABASE_ID
const NEXT_PUBLIC_URL = process.env.NEXT_PUBLIC_URL
const NEXT_PUBLIC_GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_TRACKING_ID
const BLOG_INDEX_CACHE = path.resolve('.blog_index_data')
const NUMBER_OF_POSTS_PER_PAGE = 10
const SEC_NOTION_API_SECRET = process.env.SEC_NOTION_API_SECRET 👉 追加
const SEC_DATABASE_ID = process.env.SEC_DATABASE_ID 👉 追加
module.exports = {
NOTION_API_SECRET,
DATABASE_ID,
NEXT_PUBLIC_URL,
NEXT_PUBLIC_GA_TRACKING_ID,
BLOG_INDEX_CACHE,
NUMBER_OF_POSTS_PER_PAGE,
SEC_NOTION_API_SECRET, 👉 追加
SEC_DATABASE_ID 👉 追加
}
これで他のファイルから呼び出せるようになりました🎶
トレーニングの段階で記述した….
type Help={
title:string;
description:string;
date:string;
tags:string;
last_edit:string;
URL:string;
site:string;
siteCollor:string;
}
この部分を定位置に収納します。
export interface Post {
title: string;
description: string;
date: string;
tags: string;
last_edit: string;
URL: string;
site: string;
siteCollor: string;
}
ブログ用と区別するために
libディレクトリ内に【sec-notion】というディレクトリを
用意することにしました(´・ω・`)
トレーニングの段階で記述した…..
export async function getStaticProps(){
const herotoken="***** NOTION_API_SECRET ******";
const herodatabaseId="******* DATABASE_ID *******";
const heronotion = new Client({ auth: herotoken });
const data = await heronotion.databases.query({
database_id: herodatabaseId,
filter: {
property: 'tags',
select: {
equals: "posting",
}
},
sorts:[{
property: 'date',
direction: 'descending',
},],
});
const helpList: Help[]=data.results.map((_:any)=>_.properties).map(_=>{
return{
date: _.date.date.start,
title: _.title.title[0].plain_text,
description: _.description.rich_text[0].plain_text,
tags: _.tags.select.name,
last_edit: _.last_edit.last_edited_time,
URL: _.URL.url,
site: _.site.select.name,
siteCollor: _.site.select.color
};
});
console.dir(helpList,{depth:null});
return {props:{helpList},revalidate:30};
}
この部分を定位置に収納します。
client.tsというファイルです。
これもinterfaces.tsと同様、
ブログ用と区別するために
【sec-notion】ディレクトリに
入れることにしました。(´・ω・`)
import { SEC_NOTION_API_SECRET, SEC_DATABASE_ID } from '../notion/server-constants'
import { Post } from './interfaces'
const { Client } = require('@notionhq/client')
const client = new Client({
auth: SEC_NOTION_API_SECRET,
})
export async function getAllSecPosts() {
let results = []
const params = {
database_id: SEC_DATABASE_ID,
filter: {
property: 'tags',
select: {
equals: "posting",
}
},
sorts: [
{
property: 'date',
direction: 'descending',
},
]
}
const data = await client.databases.query(params)
results = results.concat(data.results)
params['start_cursor'] = data.next_cursor
return results.map(item => _buildPost(item))
}
function _buildPost(data) {
const prop = data.properties
const post: Post = {
title: prop.title.title[0].plain_text,
date: prop.date.date.start,
tags: prop.tags.select.name,
description:
prop.description.rich_text.length > 0
? prop.description.rich_text[0].plain_text
: '',
last_edit: prop.last_edit.last_edited_time,
URL:prop.URL.url,
site: prop.site.select.name,
siteCollor: prop.site.select.color
}
return post
}
これで他のファイルからgetAllSecPosts
をimportすれば使えるようになりました。
トレーニングの記述で残るは後半!!
const Home = ({helpList}:Props) => {
return (
<div className={styles.container}>
<Head>
<title>Posting App</title>
<meta name="description" content="Generated by Posting app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<p>▼ こちらはherohoroブログ以外で投稿した時に更新します。</p>
<h1 className={styles.title}>
External Posting
</h1>
<p className={styles.description}>
From NotionDB{' '}
<code className={styles.code}>pages/posting.tsx</code>
</p>
<h3>気になるcardをクリックすると記事へ飛べるよー</h3>
{/* gridのクラス名が効かない....siteCollorも効かない */}
<div className={Pstyles.grid}>
{helpList.map((_)=>(
<div className={Pstyles.card} key={_.title}>
<div className={styles.siteCollor} >
<div className={`${_.siteCollor}`}>
<p>{_.site}</p>
</div>
</div>
<h3>{_.date}</h3>
<Link href={_.URL} passHref><p>📝 {_.title}</p></Link>
<p>😙 {(_.description)?(_.description):null}</p>
<hr/>
{/* <p>last edit : {_.last_edit}</p> */}
</div>
))}
</div>
</main>
</div>
)
}
export default Home
これをeasy-notion-blogに表示させたいページへ調合します。
今回はブログのトップページに入れたいのでsrc/pages/index.tsx
に追記していきましょう。
import { getEditTimeStr } from '../lib/blog-helpers'
import { getAllSecPosts } from '../lib/sec-notion/client'
// 他のimportはそのまま使ってね
export async function getStaticProps() {
const posts = await getPosts()
const rankedPosts = await getRankedPosts()
const tags = await getAllTags()
const secPosts = await getAllSecPosts() 👉 追加
return {
props: {
posts,
rankedPosts,
tags,
secPosts 👉 追加
},
revalidate: 60,
}
}
const RenderPage = ({ rankedPosts = [], tags = [],secPosts=[] }) => (
//引数にsecPosts=[]を追加
<div className={styles.container}>
<DocumentHead />
<div className={styles.mainContent}>
{/* 以下、追加したい場所にコピペ */}
<div className={SecStyles.grid}>
<h3>
\ 他のサイトへの記事投稿 /
</h3>
<p>
たまに気が向くと投稿することがあるので良かったらのぞいてみてください\(^o^)/
</p>
{secPosts.map(secPost => {
return(
<div className={SecStyles.card} key={secPost.title}>
<div >
<div className={`${secPost.siteCollor}`}>
<p>{secPost.site}</p>
</div>
</div>
<h3>{secPost.date}</h3>
<Link href={secPost.URL} passHref><p>📝 {secPost.title}</p></Link>
<p>😙 {(secPost.description)?(secPost.description):null}</p>
<hr/>
<p>last edit : {getEditTimeStr(secPost.last_edit)}</p>
</div>
)
})}
</div>
引数に入れたsecPosts
を1つずつ取り出したのがsecPost
。
secPostが抱えているプロパティはclient.tsで追記したメンバーで…
これらを使って表示させると…….
こんな感じになりました\(^o^)/
cssは省略していますが、
簡単な記述なのでみなさんならちょちょいのちょいでできるかと思います⭐
Blog learn恐るべし!
他の改造でも手順の雛形として活用できそうな予感がするので
改造作業を進める中で
「あ!ここも使えるじゃん💡」
といった発見があり次第記事にして投稿してみようと思います\(^o^)/
ブログとしても使いたいし、
日々の振り返りをCardにして並べるのも面白そうだし、
bookmarkのように使うのも良さそうですね〜〜。
このブログのSpaceページにもiframeで埋め込んでいるNotionDBがあり…..
https://herohoro.com/herospace
実は今回取り込んだDBと同じDBだったりします。
Filterを上手く使いこなせば1つのDBからいろんな表現ができそうです…..(*´∀`*)(*´∀`*)
今回、iframeで埋め込むとリンクを埋め込んでも使えない…といった問題を解決するべく結構な気合で改造したものの、普通にiframeが使えたら改造しなかったかもしれません。。。。(;O;)
不自由って改造意欲を沸き立たす要因だなと思い
余韻に浸っているへろほろでした 🧘♀️🧘♀️🧘♀️🧘♀️🧘♀️
(*´ω`*)🍺
▼ この記事に興味があったら同じタグから関連記事をのぞいてみてね
RSSリーダーにatomのリンクを登録すると通知が行くよ🐌
https://herohoro.com/atom
やってみてね(*´ω`*)(*´ω`*)
フォロー大歓迎\(^o^)/
フォロー大歓迎\(^o^)/