118 lines
2.8 KiB
TypeScript
118 lines
2.8 KiB
TypeScript
import React from "react";
|
|
import { Helmet } from "react-helmet";
|
|
import Anchor from "@components/Anchor";
|
|
import "./AdminFeedPage.scss";
|
|
import { StaticContext } from "@server/StaticContext";
|
|
import { Post, getFeed } from "@models/Feed";
|
|
import { formatRelative } from "date-fns";
|
|
import { th } from "date-fns/esm/locale";
|
|
import AddIcon from "@assets/img/add-icon.png";
|
|
|
|
export interface AdminFeedPageProps {
|
|
staticContext: StaticContext;
|
|
}
|
|
export interface AdminFeedPageState {
|
|
feed: Post[];
|
|
error?: string;
|
|
}
|
|
|
|
class AdminFeedPage extends React.Component<AdminFeedPageProps, AdminFeedPageState> {
|
|
constructor(props: AdminFeedPageProps) {
|
|
super(props);
|
|
const { staticContext } = props;
|
|
|
|
if (staticContext) {
|
|
/* The static context is an object that manages promises when
|
|
rendering on the server. If staticContext exists, that means
|
|
we have to store all promises in it. Otherwise, operate
|
|
normally. See server/index.ts. */
|
|
if (staticContext.resolutions.getFeed) {
|
|
const feed = staticContext.resolutions.getFeed as Post[];
|
|
this.state = {
|
|
feed,
|
|
};
|
|
} else {
|
|
this.state = {
|
|
feed: [],
|
|
};
|
|
const promiseFeed = this.fetchFeed();
|
|
staticContext.promises.getFeed = promiseFeed;
|
|
}
|
|
} else {
|
|
this.state = {
|
|
feed: [],
|
|
};
|
|
this.fetchFeed();
|
|
}
|
|
}
|
|
|
|
fetchFeed = async () => {
|
|
const getFeedPromise = getFeed();
|
|
try {
|
|
const feed = await getFeedPromise;
|
|
this.setState({
|
|
feed,
|
|
});
|
|
return getFeedPromise;
|
|
} catch (err) {
|
|
this.setState({
|
|
error: String(err),
|
|
});
|
|
}
|
|
}
|
|
|
|
renderAddLink = () => (
|
|
<Anchor className="add-link" to="/admin/feed/create">
|
|
<img src={AddIcon} /> Create post
|
|
</Anchor>
|
|
)
|
|
|
|
renderData = () => {
|
|
const { feed, error } = this.state;
|
|
|
|
if (error) {
|
|
return <div className="error">{error}</div>;
|
|
}
|
|
|
|
if (!feed || feed.length === 0) {
|
|
return <div>No posts.</div>;
|
|
}
|
|
|
|
return (
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Title</th>
|
|
<th>Description</th>
|
|
<th>Publish time</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{feed.map(post => (
|
|
<tr key={post.id}>
|
|
<td><Anchor to={`/admin/feed/${post.id}`}>{post.title_fi}</Anchor></td>
|
|
<td>{post.description_fi}</td>
|
|
<td>{formatRelative(new Date(post.publish_time), new Date())}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
);
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<div className="admin-feed-page">
|
|
<Helmet>
|
|
<link rel="canonical" href="https://sik.ayy.fi/admin/feed" />
|
|
</Helmet>
|
|
<h1>Feed</h1>
|
|
{this.renderAddLink()}
|
|
{this.renderData()}
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default AdminFeedPage;
|