From 2c86fa34fd8c6e3bf5b28fca61655bb81b3b6f93 Mon Sep 17 00:00:00 2001 From: gingervitis Date: Sat, 3 Apr 2021 21:25:21 -0700 Subject: [PATCH] add news feed (#99) * add news feed * Prettified Code! Co-authored-by: gingervitis --- web/components/news-feed.tsx | 64 ++++++++++++++++++++++++++++++++++++ web/pages/index.tsx | 15 ++++++--- web/pages/offline-notice.tsx | 28 +++++++++++----- web/styles/home.scss | 48 +++++++++++++++++++++++++-- web/utils/apis.ts | 8 +++-- 5 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 web/components/news-feed.tsx diff --git a/web/components/news-feed.tsx b/web/components/news-feed.tsx new file mode 100644 index 000000000..8224f1cd9 --- /dev/null +++ b/web/components/news-feed.tsx @@ -0,0 +1,64 @@ +/* eslint-disable camelcase */ +/* eslint-disable react/no-danger */ +import React, { useState, useEffect } from 'react'; +import { Typography } from 'antd'; +import format from 'date-fns/format'; + +import { fetchExternalData } from '../utils/apis'; + +const { Title, Link } = Typography; + +const OWNCAST_FEED_URL = 'https://owncast.online/news/index.json'; +const OWNCAST_BASE_URL = 'https://owncast.online'; + +interface Article { + title: string; + url: string; + content_html: string; + date_published: string; +} + +function ArticleItem({ title, url, content_html: content, date_published: date }: Article) { + const dateObject = new Date(date); + const dateString = format(dateObject, 'MMM dd, yyyy, HH:mm'); + return ( +
+

{dateString}

+ + <Link href={`${OWNCAST_BASE_URL}${url}`} target="_blank" rel="noopener noreferrer"> + {title} + </Link> + +
+
+ ); +} + +export default function NewsFeed() { + const [feed, setFeed] = useState([]); + const getFeed = async () => { + try { + const result = await fetchExternalData(OWNCAST_FEED_URL); + setFeed(result.items); + } catch (error) { + console.log('==== error', error); + } + }; + + useEffect(() => { + getFeed(); + }, []); + + if (!feed.length) { + return null; + } + + return ( +
+ News & Updates from Owncast + {feed.map(item => ( + + ))} +
+ ); +} diff --git a/web/pages/index.tsx b/web/pages/index.tsx index bf03c3c94..a5718d52c 100644 --- a/web/pages/index.tsx +++ b/web/pages/index.tsx @@ -8,6 +8,7 @@ import Offline from './offline-notice'; import { LOGS_WARN, fetchData, FETCH_INTERVAL } from '../utils/apis'; import { formatIPAddress, isEmptyObject } from '../utils/format'; +import NewsFeed from '../components/news-feed'; function streamDetailsFormatter(streamDetails) { return ( @@ -135,13 +136,16 @@ export default function Home() { - - + + {videoQualitySettings} - - + + +
diff --git a/web/pages/offline-notice.tsx b/web/pages/offline-notice.tsx index c0f0903a0..b3e7004ec 100644 --- a/web/pages/offline-notice.tsx +++ b/web/pages/offline-notice.tsx @@ -1,5 +1,5 @@ import Link from 'next/link'; -import { Result, Card, Row, Col } from 'antd'; +import { Typography, Card, Row, Col } from 'antd'; import { MessageTwoTone, QuestionCircleTwoTone, @@ -9,7 +9,9 @@ import { } from '@ant-design/icons'; import OwncastLogo from '../components/logo'; import LogTable from '../components/log-table'; +import NewsFeed from '../components/news-feed'; +const { Title } = Typography; const { Meta } = Card; export default function Offline({ logs = [], config }) { @@ -77,15 +79,20 @@ export default function Offline({ logs = [], config }) { return ( <> - - - } - title="No stream is active." - subTitle="You should start one." - /> + + +
+ + + +
+ No stream is active +

You should start one.

+
+
- +
+ {data.map(item => ( @@ -93,6 +100,9 @@ export default function Offline({ logs = [], config }) { ))} + + + diff --git a/web/styles/home.scss b/web/styles/home.scss index 7a5a211a4..2266bbecb 100644 --- a/web/styles/home.scss +++ b/web/styles/home.scss @@ -34,12 +34,14 @@ } } - .outbound-details, - .inbound-details { + .stream-details { > .ant-card-bordered { border-color: rgba(255, 255, 255, 0.1); } } + .outbound-details { + margin-bottom: 1em; + } } .offline-content { @@ -75,3 +77,45 @@ } } } + +.offline-intro { + display: flex; + flex-direction: row; + justify-content: space-evenly; + align-items: center; + margin-bottom: 2em; + .logo-svg { + height: 6em; + width: 6em; + } +} + +.news-feed { + margin-top: 0; + padding: 1.5em; + + h2 { + font-size: 1.2em; + margin-top: 0; + color: var(--pink); + } + article { + padding: 1em 0.25em; + font-size: 14px; + color: var(--white-75); + border-bottom: 1px solid var(--gray); + + h3 { + font-size: 1.2em; + a { + font-weight: 400; + font-size: 1em; + } + } + .timestamp { + margin-top: 0; + font-size: 0.75em; + color: var(--white-50); + } + } +} diff --git a/web/utils/apis.ts b/web/utils/apis.ts index 24c9a558d..c737a0826 100644 --- a/web/utils/apis.ts +++ b/web/utils/apis.ts @@ -116,9 +116,9 @@ export async function fetchData(url: string, options?: FetchOptions) { return {}; } -export async function getGithubRelease() { +export async function fetchExternalData(url: string) { try { - const response = await fetch(GITHUB_RELEASE_URL); + const response = await fetch(url); if (!response.ok) { const message = `An error has occured: ${response.status}`; throw new Error(message); @@ -131,6 +131,10 @@ export async function getGithubRelease() { return {}; } +export async function getGithubRelease() { + return fetchExternalData(GITHUB_RELEASE_URL); +} + // Stolen from https://gist.github.com/prenagha/98bbb03e27163bc2f5e4 const VPAT = /^\d+(\.\d+){0,2}$/; function upToDate(local, remote) {