This commit is contained in:
Aarni Koskela
2022-02-11 16:54:44 +02:00
parent 5c237084f5
commit a4a04f1dac
14 changed files with 172 additions and 224 deletions

View File

@@ -25,8 +25,10 @@ function renderStringWithChannelRefs(value: string) {
export const ChannelReferenceRenderer = ({
children,
}: React.PropsWithChildren<{}>) => {
// TODO: this should probably walk the tree
if (typeof children[0] === "string")
return renderStringWithChannelRefs(children[0]);
// TODO: this must be made sound
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const c0 = children[0];
if (typeof c0 === "string") return renderStringWithChannelRefs(c0);
return <>{children}</>;
};

View File

@@ -4,7 +4,7 @@ type Props = {
threshold: number;
};
function clamp(min, max, value) {
function clamp(min: number, max: number, value: number) {
return Math.min(Math.max(value, min), max);
}

View File

@@ -1,17 +1,28 @@
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";
import timeagoFi from "javascript-time-ago/locale/fi.json";
import { convertTwitterItems, TwitterItem } from "./feed-transformers/twitter";
import { GithubApi } from "parse-github-event/lib/types";
import { convertGithubItems } from "./feed-transformers/github";
import { KKEvent } from "../data/events";
JavascriptTimeAgo.addLocale(timeagoFi);
interface FeedsResult {
twitter?: TwitterItem[];
github?: GithubApi.GithubEvent[];
}
interface FeedState {
messages: KKEvent[];
}
export default class Feed extends React.Component {
state = {
public state: FeedState = {
messages: [],
};
@@ -20,9 +31,13 @@ export default class Feed extends React.Component {
}
async updateFeed() {
const res = await request.get(api("feeds"));
const res = await request.get<FeedsResult>(api("feeds"));
const { github, twitter } = res.data;
const messages = sortBy(
flatMap(res.data, (messages, type) => transformers[type](messages)),
[
...convertTwitterItems(twitter ?? []),
...convertGithubItems(github ?? []),
].flat(),
"timestamp"
);
messages.reverse(); // In-place
@@ -68,7 +83,7 @@ export default class Feed extends React.Component {
<span className="message__timestamp">
<ReactTimeAgo date={message.timestamp} locale="fi" />
</span>
<span className="message__meta">{message.meta}</span>
{/*<span className="message__meta">{message.meta}</span>*/}
</div>
</div>
</div>

View File

@@ -4,15 +4,21 @@ import classSet from "classnames";
import api from "./api";
import Loader from "./Loader";
type InviteFormState = {
submitted: boolean;
sending: boolean;
error: any | null;
email: string;
};
export default class InviteForm extends React.Component {
state = {
public state: InviteFormState = {
email: "",
submitted: false,
sending: false,
error: null,
};
onSubmit = async (e) => {
onSubmit = async (e: React.FormEvent) => {
e.preventDefault();
this.setState({
@@ -35,11 +41,11 @@ export default class InviteForm extends React.Component {
this.setState({ submitted: true, sending: false });
};
handleError = (err) => {
this.setState({ error: err, sending: false });
handleError = (error: any) => {
this.setState({ error, sending: false });
};
onChange = (e) => {
onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.value === this.state.email) {
return;
}

View File

@@ -3,8 +3,16 @@ import request from "axios";
import shuffle from "lodash/shuffle";
import api from "./api";
interface Member {
avatar_url: string;
}
interface MembersState {
members: Member[];
}
export default class Members extends React.Component {
state = {
public state: MembersState = {
members: [],
};

View File

@@ -1,5 +1,5 @@
const host = process.env.SERVER || "https://koodiklinikka-api.herokuapp.com/";
export default function getApiURL(path) {
export default function getApiURL(path: string) {
return host + path;
}

View File

@@ -1,70 +0,0 @@
import lodashTemplate from "lodash/template";
import defaultTemplateSettings from "lodash/templateSettings";
import githubEvent from "parse-github-event";
import twitterText from "twitter-text";
const isVisibleGithubEvent = ({ type }) =>
type !== "PushEvent" && type !== "DeleteEvent";
const templateSettings = {
...defaultTemplateSettings,
interpolate: /{{([\s\S]+?)}}/g,
};
export default {
github(items) {
return items.filter(isVisibleGithubEvent).map((item) => {
const template = lodashTemplate(
githubEvent.parse(item).text,
templateSettings,
false
);
const repository = `https://github.com/${item.repo.name}`;
let branch;
if (item.payload.ref) {
branch = item.payload.ref.replace("refs/heads/", "");
}
const message = template({
repository: `<a target="_blank" href="${repository}">${item.repo.name}</a>`,
branch: branch,
number: item.payload.number,
ref_type: item.payload.ref_type,
ref: item.payload.ref,
});
const url = `https://github.com/${item.actor.login}`;
return {
user: item.actor.login,
userLink: url,
image: item.actor.avatar_url,
imageLink: url,
body: message,
timestamp: new Date(item.created_at),
url: message.url,
type: "github",
};
});
},
twitter(items) {
return items.map((item) => {
if (item.retweeted) {
item = item.retweeted_status;
}
const url = `https://twitter.com/${item.user.screen_name}`;
return {
user: `@${item.user.screen_name}`,
userLink: url,
image: item.user.profile_image_url_https,
imageLink: url,
body: twitterText.autoLink(item.text),
timestamp: new Date(item.created_at),
type: "twitter",
};
});
},
};

View File

@@ -0,0 +1,47 @@
import { GithubApi } from "parse-github-event/lib/types";
import { KKEvent } from "../../data/events";
import githubEvent from "parse-github-event";
import lodashTemplate from "lodash/template";
import defaultTemplateSettings from "lodash/templateSettings";
const isVisibleGithubEvent = ({ type }: GithubApi.GithubEvent) =>
type !== "PushEvent" && type !== "DeleteEvent";
const templateSettings = {
...defaultTemplateSettings,
interpolate: /{{([\s\S]+?)}}/g,
};
function convertGithubEvent(item: GithubApi.GithubEvent): KKEvent {
const parsedEvent = githubEvent.parse(item);
const template = lodashTemplate(parsedEvent?.text, templateSettings, false);
const repository = `https://github.com/${item.repo.name}`;
let branch;
if (item.payload.ref) {
branch = item.payload.ref.replace("refs/heads/", "");
}
const message = template({
repository: `<a target="_blank" href="${repository}">${item.repo.name}</a>`,
branch: branch,
number: item.payload.number,
ref_type: item.payload.ref_type,
ref: item.payload.ref,
});
const url = `https://github.com/${item.actor.login}`;
return {
user: item.actor.login,
userLink: url,
image: item.actor.avatar_url,
imageLink: url,
body: message,
timestamp: new Date(item.created_at),
type: "github",
};
}
export function convertGithubItems(items: readonly GithubApi.GithubEvent[]) {
return items.filter(isVisibleGithubEvent).map(convertGithubEvent);
}

View File

@@ -0,0 +1,35 @@
import { KKEvent } from "../../data/events";
import twitterText from "twitter-text";
export interface TwitterItem {
retweeted?: boolean;
retweeted_status?: TwitterItem;
user: {
screen_name: string;
profile_image_url_https: string;
};
text: string;
created_at: number | string; // TODO: type?
}
function convertTwitterItem(item: TwitterItem): KKEvent {
if (item.retweeted && item.retweeted_status) {
item = item.retweeted_status;
}
const url = `https://twitter.com/${item.user.screen_name}`;
return {
user: `@${item.user.screen_name}`,
userLink: url,
image: item.user.profile_image_url_https,
imageLink: url,
body: twitterText.autoLink(item.text),
timestamp: new Date(item.created_at),
type: "twitter",
};
}
export function convertTwitterItems(items: readonly TwitterItem[]) {
return items.map(convertTwitterItem);
}