mirror of
https://github.com/koodiklinikka/koodiklinikka.fi.git
synced 2026-02-17 19:53:57 +00:00
WIP
This commit is contained in:
@@ -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}</>;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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: [],
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
47
components/feed-transformers/github.ts
Normal file
47
components/feed-transformers/github.ts
Normal 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);
|
||||
}
|
||||
35
components/feed-transformers/twitter.ts
Normal file
35
components/feed-transformers/twitter.ts
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user