-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
157 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
type MainOption = { | ||
header: { | ||
label: string, | ||
}[] | ||
}; | ||
export function TableElement(mainOption: MainOption, bodyList: { element: JSX.Element }[][]) { | ||
if (mainOption.header.length <= 0) { | ||
throw new Error(`カラムの数は1以上にして下さい`); | ||
} | ||
const headerElementList: JSX.Element[] = []; | ||
for (const h of mainOption.header) { | ||
const index = mainOption.header.indexOf(h); | ||
headerElementList.push( | ||
<th scope="col" className="px-6 py-4 text-left" key={`th-${index}`}>{h.label}</th> | ||
); | ||
} | ||
const bodyElementList: JSX.Element[] = []; | ||
let trIndex = 0; | ||
for (const body of bodyList) { | ||
const tdElementList: JSX.Element[] = []; | ||
for (let i = 0; i < mainOption.header.length; i++) { | ||
const tdBody: { element: JSX.Element } = body[i]; | ||
tdElementList.push(<td className="px-1 py-1" key={`td-${i}`}>{tdBody.element}</td>); | ||
} | ||
bodyElementList.push( | ||
<tr className="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100 text-sm text-gray-900 font-light" key={`tr-${trIndex}`}> | ||
{tdElementList} | ||
</tr> | ||
); | ||
trIndex += 1; | ||
} | ||
return ( | ||
<table className="w-full"> | ||
<thead className="bg-white border-b sticky top-0 text-md font-medium text-gray-900"> | ||
<tr> | ||
{headerElementList} | ||
</tr> | ||
</thead> | ||
<tbody className=""> | ||
{bodyElementList} | ||
</tbody> | ||
</table> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,133 +1,124 @@ | ||
import Link from "next/link"; | ||
import dateformat from "dateformat"; | ||
import { ArticleLoader } from "../../../util/articleLoader"; | ||
import { TableElement } from "../../_components/tableElements"; | ||
dateformat.i18n.dayNames = [ | ||
'日', '月', '火', '水', '木', '金', '土', | ||
'日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日' | ||
]; | ||
type DisplayData = Awaited<ReturnType<ArticleLoader["loadData"]>>["articles"][number]; | ||
type CategoryTagData = Awaited<ReturnType<ArticleLoader["loadData"]>>["categoryTag"] | ||
export function ArticleListElement(displayData: DisplayData[], categoryTag: CategoryTagData) { | ||
return ( | ||
<table className="w-full"> | ||
<thead className="bg-white border-b sticky top-0 text-md font-medium text-gray-900"> | ||
<tr> | ||
<th scope="col" className="px-6 py-4 text-left"> | ||
No | ||
</th> | ||
<th scope="col" className="px-6 py-4 text-left"> | ||
カテゴリ | ||
</th> | ||
<th scope="col" className="px-6 py-4 text-left"> | ||
タイトル | ||
</th> | ||
<th scope="col" className="px-6 py-4 text-left"> | ||
日時 | ||
</th> | ||
</tr> | ||
</thead> | ||
<tbody className=""> | ||
{displayData.map(d => { | ||
const officialLinkTitle = `公式のakiba-souken.com へのリンク。閉鎖後は繋がらなくなるはず`; | ||
const iaSearchResultLinkTitle = `InternetArchive の検索結果へのリンク`; | ||
const iframeLinkTitle = `Iframeを使ってInternetArchiveに記録されたアーカイブを表示します`; | ||
const topCategory = d.breadLinks[0]; | ||
const timestampStr = dateformat(new Date(d.timestampMs), "yyyy/mm/dd(ddd)HH:MM"); | ||
const originalUrl = `https://akiba-souken.com/article/${d.articleId}/`; | ||
const page2After = (() => { | ||
if (d.maxPageNumber == 1) { | ||
return [(<></>)]; | ||
} | ||
const result: JSX.Element[] = [ | ||
(<hr key={`hr`} />) | ||
]; | ||
for (let page = 2; page <= d.maxPageNumber; page++) { | ||
result.push( | ||
<div className="flex gap-4 text-xs text-gray-300" key={`page-${page}`}> | ||
<a href={`https://akiba-souken.com/article/${d.articleId}/?page=${page}`} target="_blank" className="transition duration-300 ease-in-out hover:text-gray-900" title={officialLinkTitle}>公式</a> | ||
<a href={`https://web.archive.org/web/*/https://akiba-souken.com/article/${d.articleId}/?page=${page}`} target="_blank" className="transition duration-300 ease-in-out hover:text-gray-900" title={iaSearchResultLinkTitle}>IA検索結果</a> | ||
<Link href={`/iframe?src=article-${d.articleId}-${page}`} className="transition duration-300 ease-in-out hover:text-gray-900" title={iframeLinkTitle}>IAをiframe</Link> Page:{page} | ||
</div> | ||
); | ||
} | ||
return result; | ||
})(); | ||
// パンくずリスト部分を作成 | ||
let breadElement = (<span key={`notice`}></span>); | ||
if (0 < d.breadLinks.length) { | ||
const breadChildElement: JSX.Element[] = []; | ||
breadChildElement.push(<span className="mr-[-0.5rem]" key={`label`}>パンくずリスト:</span>); | ||
for (const bread of d.breadLinks) { | ||
if (d.breadLinks.indexOf(bread) != 0) { | ||
breadChildElement.push(<span>></span>); | ||
} | ||
const tagCount = categoryTag.getTagCount(bread); | ||
breadChildElement.push( | ||
<Link | ||
href={`/article/tag/${bread}`} | ||
className="transition duration-300 ease-in-out hover:text-gray-900" | ||
key={`bread-${bread}`} | ||
>{bread}({tagCount})</Link> | ||
); | ||
} | ||
breadElement = ( | ||
<span className="flex gap-0.5"> | ||
{breadChildElement} | ||
</span> | ||
); | ||
} | ||
// タグ部分を作成 | ||
let tagElement = (<span key={`notice`}>タグ無し</span>); | ||
if (d.tags.length != 0) { | ||
const tagChildElements: JSX.Element[] = []; | ||
tagChildElements.push(<span className="mr-[-0.5rem]" key={`label`}>タグ:</span>); | ||
for (const tag of d.tags) { | ||
if (d.tags.indexOf(tag) != 0) { | ||
tagChildElements.push(<span>/</span>); | ||
}; | ||
const tagCount = categoryTag.getTagCount(tag); | ||
tagChildElements.push( | ||
<Link | ||
href={`/article/tag/${tag}`} | ||
className="transition duration-300 ease-in-out hover:text-gray-900" | ||
key={`tag-${tag}`} | ||
>{tag}({tagCount})</Link> | ||
); | ||
} | ||
tagElement = ( | ||
<span className="flex gap-0.5"> | ||
{tagChildElements} | ||
</span> | ||
); | ||
} | ||
const hatebuElement = ( | ||
<a href={`https://b.hatena.ne.jp/entry/${originalUrl}`}> | ||
<img src={`https://b.hatena.ne.jp/entry/image/${originalUrl}`} /> | ||
</a> | ||
); | ||
return ( | ||
<tr className="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100 text-sm text-gray-900 font-light"> | ||
<td className="px-1 py-1">{d.articleId}</td> | ||
<td className="px-1 py-1"> | ||
<Link href={`/article/tag/${topCategory}`} className="transition duration-300 ease-in-out hover:text-gray-900 original-href" >{topCategory}</Link> | ||
</td> | ||
<td className="px-1 py-1"> | ||
<div>{d.title}</div> | ||
<div className="flex gap-4 text-xs text-gray-300"> | ||
<a href={originalUrl} target="_blank" className="transition duration-300 ease-in-out hover:text-gray-900" title={officialLinkTitle}>公式</a> | ||
<a href={`https://web.archive.org/web/*/${originalUrl}`} target="_blank" className="transition duration-300 ease-in-out hover:text-gray-900" title={iaSearchResultLinkTitle}>IA検索結果</a> | ||
<Link href={`/iframe?src=article-${d.articleId}`} className="transition duration-300 ease-in-out hover:text-gray-900" title={iframeLinkTitle}>IAをiframe</Link> | ||
{breadElement} | ||
{tagElement} | ||
{hatebuElement} | ||
</div> | ||
{page2After} | ||
</td> | ||
<td className="px-1 py-1">{timestampStr}</td> | ||
</tr> | ||
); | ||
})} | ||
</tbody> | ||
</table> | ||
const result = TableElement({ | ||
header: [ | ||
{ label: "No" }, | ||
{ label: "カテゴリ" }, | ||
{ label: "タイトル" }, | ||
{ label: "日付" }, | ||
] | ||
}, displayData.map(d => { | ||
return getDisplayData(d, categoryTag); | ||
})); | ||
return result; | ||
} | ||
function getDisplayData(d: DisplayData, categoryTag: CategoryTagData) { | ||
const officialLinkTitle = `公式のakiba-souken.com へのリンク。閉鎖後は繋がらなくなるはず`; | ||
const iaSearchResultLinkTitle = `InternetArchive の検索結果へのリンク`; | ||
const iframeLinkTitle = `Iframeを使ってInternetArchiveに記録されたアーカイブを表示します`; | ||
const topCategory = d.breadLinks[0]; | ||
const timestampStr = dateformat(new Date(d.timestampMs), "yyyy/mm/dd(ddd)HH:MM"); | ||
const originalUrl = `https://akiba-souken.com/article/${d.articleId}/`; | ||
const page2After = (() => { | ||
if (d.maxPageNumber == 1) { | ||
return [(<></>)]; | ||
} | ||
const result: JSX.Element[] = [ | ||
(<hr key={`hr`} />) | ||
]; | ||
for (let page = 2; page <= d.maxPageNumber; page++) { | ||
result.push( | ||
<div className="flex gap-4 text-xs text-gray-300" key={`page-${page}`}> | ||
<a href={`https://akiba-souken.com/article/${d.articleId}/?page=${page}`} target="_blank" className="transition duration-300 ease-in-out hover:text-gray-900" title={officialLinkTitle}>公式</a> | ||
<a href={`https://web.archive.org/web/*/https://akiba-souken.com/article/${d.articleId}/?page=${page}`} target="_blank" className="transition duration-300 ease-in-out hover:text-gray-900" title={iaSearchResultLinkTitle}>IA検索結果</a> | ||
<Link href={`/iframe?src=article-${d.articleId}-${page}`} className="transition duration-300 ease-in-out hover:text-gray-900" title={iframeLinkTitle}>IAをiframe</Link> Page:{page} | ||
</div> | ||
); | ||
} | ||
return result; | ||
})(); | ||
// パンくずリスト部分を作成 | ||
let breadElement = (<span key={`notice`}></span>); | ||
if (0 < d.breadLinks.length) { | ||
const breadChildElement: JSX.Element[] = []; | ||
breadChildElement.push(<span className="mr-[-0.5rem]" key={`label`}>パンくずリスト:</span>); | ||
for (const bread of d.breadLinks) { | ||
if (d.breadLinks.indexOf(bread) != 0) { | ||
breadChildElement.push(<span>></span>); | ||
} | ||
const tagCount = categoryTag.getTagCount(bread); | ||
breadChildElement.push( | ||
<Link | ||
href={`/article/tag/${bread}`} | ||
className="transition duration-300 ease-in-out hover:text-gray-900" | ||
key={`bread-${bread}`} | ||
>{bread}({tagCount})</Link> | ||
); | ||
} | ||
breadElement = ( | ||
<span className="flex gap-0.5"> | ||
{breadChildElement} | ||
</span> | ||
); | ||
} | ||
// タグ部分を作成 | ||
let tagElement = (<span key={`notice`}>タグ無し</span>); | ||
if (d.tags.length != 0) { | ||
const tagChildElements: JSX.Element[] = []; | ||
tagChildElements.push(<span className="mr-[-0.5rem]" key={`label`}>タグ:</span>); | ||
for (const tag of d.tags) { | ||
if (d.tags.indexOf(tag) != 0) { | ||
tagChildElements.push(<span>/</span>); | ||
}; | ||
const tagCount = categoryTag.getTagCount(tag); | ||
tagChildElements.push( | ||
<Link | ||
href={`/article/tag/${tag}`} | ||
className="transition duration-300 ease-in-out hover:text-gray-900" | ||
key={`tag-${tag}`} | ||
>{tag}({tagCount})</Link> | ||
); | ||
} | ||
tagElement = ( | ||
<span className="flex gap-0.5"> | ||
{tagChildElements} | ||
</span> | ||
); | ||
} | ||
const hatebuElement = ( | ||
<a href={`https://b.hatena.ne.jp/entry/${originalUrl}`}> | ||
<img src={`https://b.hatena.ne.jp/entry/image/${originalUrl}`} /> | ||
</a> | ||
); | ||
const result: { element: JSX.Element }[] = [ | ||
{ element: <>{d.articleId}</> }, | ||
{ element: <Link href={`/article/tag/${topCategory}`} className="transition duration-300 ease-in-out hover:text-gray-900 original-href" >{topCategory}</Link> }, | ||
{ | ||
element: <> | ||
<div>{d.title}</div> | ||
<div className="flex gap-4 text-xs text-gray-300"> | ||
<a href={originalUrl} target="_blank" className="transition duration-300 ease-in-out hover:text-gray-900" title={officialLinkTitle}>公式</a> | ||
<a href={`https://web.archive.org/web/*/${originalUrl}`} target="_blank" className="transition duration-300 ease-in-out hover:text-gray-900" title={iaSearchResultLinkTitle}>IA検索結果</a> | ||
<Link href={`/iframe?src=article-${d.articleId}`} className="transition duration-300 ease-in-out hover:text-gray-900" title={iframeLinkTitle}>IAをiframe</Link> | ||
{breadElement} | ||
{tagElement} | ||
{hatebuElement} | ||
</div> | ||
{page2After} | ||
</> | ||
}, | ||
{ | ||
element: <>{timestampStr}</> | ||
} | ||
] | ||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters