Files
koodiklinikka.fi/components/Feed.tsx
Olavi Haapala f4474523ad Chore/convert to typescript (#60)
* Convert to using TypeScript

Next.js v.9 allows converting an existing project to TS by simply renaming the files as TS files

* Fix type errors: Type 'string' is not assignable to type 'number'.

* Add mention about missing typings for javascript-time-ago

* Add GA_INITIALIZED to window

* Fix type error in feed transformers

* Model MembershipInfoForm state and props with TS

* Silence the typescript warning in MembershipInfoForm

* Add threshold to Fader props

* Fix Warning: Each child in a list should have a unique "key" prop.

Sponsors don't have ids – name is probably unique and can be used as a key

* Allow key as prop for SponsorLink

* Add type of the props for SponsorLink
2019-11-07 07:28:02 +02:00

82 lines
2.2 KiB
TypeScript

import flatMap from "lodash/flatMap";
import sortBy from "lodash/sortBy";
import React from "react";
import request from "axios";
import api from "./api";
import transformers from "./feed-transformers";
import ReactTimeAgo from "react-time-ago";
import JavascriptTimeAgo from "javascript-time-ago";
import timeagoFi from "javascript-time-ago/locale/fi";
// TODO: Add type definitions for javascript-time-ago
(JavascriptTimeAgo as any).locale(timeagoFi);
export default class Feed extends React.Component {
state = {
messages: [],
};
componentDidMount() {
this.updateFeed();
}
async updateFeed() {
const res = await request.get(api("feeds"));
const messages = sortBy(
flatMap(res.data, (messages, type) => transformers[type](messages)),
"timestamp"
);
messages.reverse(); // In-place
this.setState({
messages: messages.slice(0, 40),
});
}
render() {
const messages = this.state.messages.map((message, i) => {
let image = <img src={message.image} alt="" />;
if (message.imageLink) {
image = (
<a
target="_blank"
href={message.imageLink}
rel="noopener noreferrer"
tabIndex={-1}
>
{image}
</a>
);
}
return (
<div className="message" key={i}>
<div className="message__image" aria-hidden="true">
{image}
</div>
<div className="message__content">
<div className="message__user">
<a href={message.userLink}>{message.user}</a>
</div>
<div
className="message__body"
dangerouslySetInnerHTML={{ __html: message.body }}
/>
<div className="message__icon">
<i className={`fa fa-${message.type}`} aria-hidden="true" />
</div>
<div className="message__details">
<span className="message__timestamp">
<ReactTimeAgo date={message.timestamp} locale="fi" />
</span>
<span className="message__meta">{message.meta}</span>
</div>
</div>
</div>
);
});
return <div className="feed">{messages}</div>;
}
}