starshard/peafowl
Template
1
Fork 0
mirror of https://github.com/starshardstudio/peafowl.git synced 2024-11-27 23:44:19 +00:00

Add "all reviews" page

This commit is contained in:
Steffo 2024-11-21 05:28:20 +01:00
parent 0bbb596c4c
commit 21ff234466
Signed by: steffo
GPG key ID: 5ADA3868646C3FC0
5 changed files with 313 additions and 39 deletions

85
_components/ReviewRow.tsx Normal file
View file

@ -0,0 +1,85 @@
import {formatDateIso} from "../_utils/date.ts"
import {ratingToClassName} from "../_utils/rating.ts"
import { ReviewData } from "../_utils/review.ts";
export type ReviewRowColumnKind = "rating" | "name" | "namesort" | "hascontent" | "date"
export type ReviewRowColumnPriority = undefined | "rating" | "progress" | "mixed"
export const reviewRowColumnKindDefault: ReviewRowColumnKind[] = ["rating", "name", "namesort", "hascontent", "date"]
export type ReviewRowProps = {
review: ReviewData,
columns?: ReviewRowColumnKind[]
priority?: ReviewRowColumnPriority
}
export function ReviewRow({review, columns = reviewRowColumnKindDefault, priority}: ReviewRowProps) {
const activeClass: string = review.active ? "review-active" : ""
const activeClassFa: string = review.active ? "fa-beat-fade" : ""
const ratingText: string = review.rating ? `${review.rating}` : ""
const ratingClass: string = ratingToClassName(review.rating)
const priorityClass: string = priority ? `priority-${priority}` : ""
const columnsElements = columns.map((kind, index) => {
switch(kind) {
case "rating": {
return (
<td key={index} className={`review-rating ${ratingClass}`}>
<data value={ratingText}>
{ratingText}
</data>
</td>
)
}
case "name": {
return (
<td key={index} className={`review-name`}>
<a href={review.url}>
<data value={review.name ?? ""}>
{review.name}
</data>
</a>
</td>
)
}
case "namesort": {
return (
<td key={index} className={`review-namesort`} hidden={true}>
<data value={review.name_sort ?? review.name ?? ""}/>
</td>
)
}
case "hascontent": {
return (
<td key={index} className={`review-hascontent`}>
<data value={review.content ? "true" : "false"}>
{review.content && <i className={"fa-sharp fa-regular fa-bars-sort"}/>}
</data>
</td>
)
}
case "date": {
const date = formatDateIso(review.date)
return (
<td key={index} className={`review-date`}>
<time dateTime={date ?? ""}>
{date}
</time>
</td>
)
}
}
})
return (
<tr className={`game ${activeClass} ${ratingClass} ${priorityClass}`}>
{columnsElements}
</tr>
)
}

View file

@ -0,0 +1,92 @@
import {GameData} from "../_utils/game.ts"
import {ReviewData} from "../_utils/review.ts";
import { ReviewRow, ReviewRowColumnKind, reviewRowColumnKindDefault, ReviewRowColumnPriority } from "./ReviewRow.tsx";
export type ReviewTableProps = {
id?: string,
reviews: ReviewData[],
columns?: ReviewRowColumnKind[]
priority?: ReviewRowColumnPriority
}
export function ReviewTable({id, reviews, columns = reviewRowColumnKindDefault, priority}: ReviewTableProps) {
const colElements = columns.map((column, index) => {
switch(column) {
case "rating": return (
<col key={index} className={`review-rating`}/>
)
case "name": return (
<col key={index} className={`review-name`}/>
)
case "hascontent": return (
<col key={index} className={`review-hascontent`}/>
)
case "date": return (
<col key={index} className={`review-date`}/>
)
}
})
const thElements = columns.map((column, index) => {
switch(column) {
case "rating": return (
<th key={index} scope={"col"} className={`review-rating`}>
<abbr title={"The given rating, from 1 to 100."}>
<i className={`fa-sharp fa-solid fa-thumbs-up`}/>
</abbr>
</th>
)
case "name": return (
<th key={index} scope={"col"} className={`review-name`}>
<abbr title={"The title of the reviewed item."}>
Title
</abbr>
</th>
)
case "namesort": return (
<th key={index} scope={"col"} className={`review-namesort`} hidden={true}>
<abbr title={"The title to sort the reviewed item as."}>
Sort by
</abbr>
</th>
)
case "hascontent":
return (
<th key={index} scope={"col"} className={`review-hascontent`}>
<abbr title={"Whether the review has textual content, or just metadata."}>
<i className={`fa-sharp fa-regular fa-bars-sort`}/>
</abbr>
</th>
)
case "date": return (
<th key={index} scope={"col"} className={`review-date`}>
<abbr title={"The date of the last update of the review."}>
Date
</abbr>
</th>
)
}
})
const trTdElements = reviews.map((review: ReviewData) => (
<ReviewRow key={review.url} review={review} columns={columns} priority={priority}/>
))
return (
<table id={id}>
<colgroup>
{colElements}
</colgroup>
<thead>
<tr>
{thElements}
</tr>
</thead>
<tbody>
{trTdElements}
</tbody>
</table>
)
}

View file

@ -5,10 +5,25 @@ import fileData from "./_plugins/fileData.ts"
import Site from "lume/core/site.ts";
let location: URL | undefined = undefined
try {
location = new URL("") // TODO: Enter the base URL of your website here, or links won't work!
}
catch (e) {
if(e instanceof TypeError) {
// pass safely
}
else {
throw e
}
}
const site: Site = lume({
prettyUrls: false,
location: new URL(""), // TODO: Enter the base URL of your website here, or links won't work!
location,
})
export default site
site.use(jsx({}))
@ -18,17 +33,11 @@ site.data("styles", ["/_static/styles/base.css"])
site.data("lang", "en")
site.data("date", "Git Created")
/*===== list of lists =====*/
site.data("layout", "index.tsx", "/index.md")
site.data("tags", ["index"], "/index.md")
site.data("url", "/games/index.html", "/list-games.md")
site.data("layout", "list-games.tsx", "/list-games.md")
site.data("tags", ["list", "list-games"], "/list-games.md")
site.data("layout", "game.tsx", "/games")
site.data("tags", ["review", "game"], "/games")
site.use(fileData({
query: "index",
urlizer(data) {
@ -43,6 +52,43 @@ site.use(fileData({
}
}))
/*===== list of all reviews =====*/
site.data("url", "/all/index.html", "/list-all.md")
site.data("layout", "list-all.tsx", "/list-all.md")
site.data("tags", ["list", "list-all"], "/list-all.md")
site.use(fileData({
query: "list-all",
urlizer(_data) {
return "/all/index.json"
},
contentizer(data) {
return JSON.stringify({
content: data.content,
items: site.search.pages("review").map((data) => data.url.replace(".html", ".json"))
})
}
}))
site.use(feed({
output: ["/all/feed.rss", "/all/feed.json"],
query: "review",
limit: 10,
info: {
title: "Reviews", // TODO: Change this to your site's videogame section's name!
},
items: {
title: "=name"
}
}))
/*===== list of games =====*/
site.data("url", "/games/index.html", "/list-games.md")
site.data("layout", "list-games.tsx", "/list-games.md")
site.data("tags", ["list", "list-games"], "/list-games.md")
site.use(fileData({
query: "list-games",
urlizer(_data) {
@ -56,6 +102,23 @@ site.use(fileData({
}
}))
site.use(feed({
output: ["/games/feed.rss", "/games/feed.json"],
query: "game",
limit: 10,
info: {
title: "Videogames", // TODO: Change this to your site's videogame section's name!
},
items: {
title: "=name"
}
}))
/*===== game =====*/
site.data("layout", "game.tsx", "/games")
site.data("tags", ["review", "game"], "/games")
site.use(fileData({
query: "game",
urlizer(data) {
@ -80,26 +143,12 @@ site.use(fileData({
}
}))
site.use(feed({
output: ["/games/feed.rss", "/games/feed.json"],
query: "game",
limit: 10,
info: {
title: "Videogames", // TODO: Change this to your site's videogame section's name!
},
items: {
title: "=name"
}
}))
/*===== list of anime =====*/
site.data("url", "/anime/index.html", "/list-anime.md")
site.data("layout", "list-anime.tsx", "/list-anime.md")
site.data("tags", ["list", "list-anime"], "/list-anime.md")
site.data("layout", "anime.tsx", "/anime")
site.data("tags", ["review", "anime"], "/anime")
site.use(fileData({
query: "list-anime",
urlizer(_data) {
@ -113,6 +162,23 @@ site.use(fileData({
}
}))
site.use(feed({
output: ["/anime/feed.rss", "/anime/feed.json"],
query: "anime",
limit: 10,
info: {
title: "Anime", // TODO: Change this to your site's anime section's name!
},
items: {
title: "=name"
}
}))
/*===== anime =====*/
site.data("layout", "anime.tsx", "/anime")
site.data("tags", ["review", "anime"], "/anime")
site.use(fileData({
query: "anime",
urlizer(data) {
@ -134,18 +200,3 @@ site.use(fileData({
})
}
}))
site.use(feed({
output: ["/anime/feed.rss", "/anime/feed.json"],
query: "anime",
limit: 10,
info: {
title: "Anime", // TODO: Change this to your site's anime section's name!
},
items: {
title: "=name"
}
}))
export default site;

46
_includes/list-all.tsx Normal file
View file

@ -0,0 +1,46 @@
import { ReviewTable } from "../_components/ReviewTable.tsx";
import { ReviewData } from "../_utils/review.ts";
export const layout = "base.tsx"
export const url = "/all.html"
export default function(data: Lume.Data, helpers: Lume.Helpers) {
const intro_section = data.content ? (
<section id={"list-all-section-intro"}>
{data.children}
</section>
) : null
const reviews: ReviewData[] = data.search.pages("review")
const reviews_section = (
<section id={"list-all-section-all"}>
<h2>
Review list
<small>
<a href={helpers.url("/all/feed.rss")}>
<i className={"fa-sharp fa-solid fa-rss"}/> Feed
</a>
</small>
<small>
<a href={helpers.url("/all/index.json")}>
<i className={"fa-sharp fa-solid fa-brackets-curly"}/> Raw
</a>
</small>
</h2>
<div>
<ReviewTable id={"list-all-table"} reviews={reviews} priority={"mixed"}/>
</div>
</section>
)
return (
<main id={"list-all-main"}>
{intro_section}
{reviews_section}
<script src={"/_static/scripting/sort.js"}/>
<script src={"/_static/scripting/installSortOnLoad.js"}/>
</main>
)
}

0
list-all.md Normal file
View file