docs: diagram #5
7 changed files with 195 additions and 47 deletions
124
.github/workflows/main.yml
vendored
Normal file
124
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
main
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_VERSION: 16
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
setup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Setup
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v2
|
||||||
|
id: node-setup
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
id: cache-restore
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
.yarn
|
||||||
|
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ env.NODE_VERSION }}
|
||||||
|
- name: Install dependencies
|
||||||
|
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||||
|
run: yarn
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Build
|
||||||
|
needs: setup
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v2
|
||||||
|
id: node-setup
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
- name: Yarn cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
id: yarn-cache-restore
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
.yarn
|
||||||
|
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ env.NODE_VERSION }}
|
||||||
|
- name: Parcel cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
id: parcel-cache-restore
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
.parcel-cache
|
||||||
|
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ env.NODE_VERSION }}-parcel
|
||||||
|
- run: |
|
||||||
|
yarn
|
||||||
|
yarn build
|
||||||
|
- name: Build Artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: build-artifacts
|
||||||
|
path: dist
|
||||||
|
preview:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Deploy preview
|
||||||
|
if: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
needs: build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v2
|
||||||
|
id: node-setup
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
- name: Build Artifacts
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: build-artifacts
|
||||||
|
path: dist
|
||||||
|
- name: Netlify CLI setup
|
||||||
|
run: npm install -g netlify-cli
|
||||||
|
- name: Deploy
|
||||||
|
id: preview-deploy
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||||
|
run: |
|
||||||
|
netlify deploy --dir=dist > output.log
|
||||||
|
echo "::set-output name=draft-url::$(grep 'Website Draft URL' output.log)"
|
||||||
|
- name: Report
|
||||||
|
uses: actions/github-script@v2
|
||||||
|
env:
|
||||||
|
DRAFT_URL: ${{ steps.preview-deploy.outputs.draft-url }}
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
script: |
|
||||||
|
github.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: `:eyes: Branch deployed at ${process.env.DRAFT_URL}`
|
||||||
|
})
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Deploy
|
||||||
|
needs: build
|
||||||
|
if: ${{ github.ref == 'refs/heads/main' }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v2
|
||||||
|
id: node-setup
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
- name: Build Artifacts
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: build-artifacts
|
||||||
|
path: dist
|
||||||
|
- name: Netlify CLI setup
|
||||||
|
run: npm install -g netlify-cli
|
||||||
|
- name: Deploy
|
||||||
|
id: preview-deploy
|
||||||
|
env:
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||||
|
run: |
|
||||||
|
netlify deploy --dir=dist --prod
|
|
@ -8,6 +8,7 @@
|
||||||
"lint": "eslint src",
|
"lint": "eslint src",
|
||||||
"lint:fix": "eslint src netlify --fix",
|
"lint:fix": "eslint src netlify --fix",
|
||||||
"types": "tsc --noEmit",
|
"types": "tsc --noEmit",
|
||||||
|
"clean": "rm -rf dist/*",
|
||||||
"build": "parcel build src/index.html",
|
"build": "parcel build src/index.html",
|
||||||
"build:bundlesize": "parcel build src/index.html --reporter @parcel/reporter-bundle-analyzer"
|
"build:bundlesize": "parcel build src/index.html --reporter @parcel/reporter-bundle-analyzer"
|
||||||
},
|
},
|
||||||
|
@ -37,8 +38,8 @@
|
||||||
"@material-ui/core": "^4.12.1",
|
"@material-ui/core": "^4.12.1",
|
||||||
"@material-ui/icons": "^4.11.2",
|
"@material-ui/icons": "^4.11.2",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"crypto-js": "^4.0.0",
|
|
||||||
"htmlparser2": "^6.1.0",
|
"htmlparser2": "^6.1.0",
|
||||||
|
"md5": "^2.3.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2"
|
"react-dom": "^17.0.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,48 @@
|
||||||
import React, { ReactNode } from 'react'
|
import React, { ReactNode } from 'react'
|
||||||
import Box from '@material-ui/core/Box'
|
import Box from '@material-ui/core/Box'
|
||||||
|
import Card from '@material-ui/core/Card'
|
||||||
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
|
|
||||||
import ItemCard from './ItemCard'
|
|
||||||
import type { Item } from './types'
|
import type { Item } from './types'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
items: Item[]
|
items: Item[]
|
||||||
}
|
}
|
||||||
|
interface CardProps {
|
||||||
|
title: string
|
||||||
|
url: string
|
||||||
|
published: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
root: {
|
||||||
|
margin: '5px',
|
||||||
|
padding: '10px',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
function ItemCard(props: CardProps): ReactNode {
|
||||||
|
const { title, url, published } = props
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
const formattedDate = published.toLocaleString('en-GB', { timeZone: 'UTC' })
|
||||||
|
return (
|
||||||
|
<Card className={classes.root}>
|
||||||
|
<a href={url}>{title}</a>
|
||||||
|
<span>{formattedDate}</span>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
export default function FeedsPanel(props: Props): ReactNode {
|
export default function FeedsPanel(props: Props): ReactNode {
|
||||||
const { items } = props
|
const { items } = props
|
||||||
return (
|
return (
|
||||||
<Box display="flex" flexDirection="column">
|
<Box display="flex" flexDirection="column">
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<ItemCard
|
<ItemCard
|
||||||
key={`feed_item_${item.title.replace(' ', '_')}`}
|
|
||||||
{...item}
|
{...item}
|
||||||
|
key={`feed_item_${item.title.replace(' ', '_')}`}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
import React, { ReactNode } from 'react'
|
|
||||||
import Card from '@material-ui/core/Card'
|
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
|
||||||
|
|
||||||
interface CardProps {
|
|
||||||
title: string
|
|
||||||
url: string
|
|
||||||
published: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
|
||||||
root: {
|
|
||||||
margin: '5px',
|
|
||||||
padding: '10px',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
function formatDate(date: Date): string {
|
|
||||||
return date.toLocaleString('en-GB', { timeZone: 'UTC' })
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ItemCard(props: CardProps): ReactNode {
|
|
||||||
const { title, url, published } = props
|
|
||||||
const classes = useStyles()
|
|
||||||
return (
|
|
||||||
<Card className={classes.root}>
|
|
||||||
<a href={url}>{title}</a>
|
|
||||||
<span>{formatDate(published)}</span>
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
import md5 from 'crypto-js/md5'
|
import md5 from 'md5'
|
||||||
|
|
||||||
import type { RSSData, Settings } from '../types'
|
import type { RSSData, Settings } from '../types'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { useReducer, useRef } from 'react'
|
import { useReducer, useRef } from 'react'
|
||||||
|
|
||||||
|
import type { State } from '../types'
|
||||||
import { panelIdentifiers } from '../constants'
|
import { panelIdentifiers } from '../constants'
|
||||||
|
|
||||||
export const SET_PANEL_IDENTIFIER = 'setPanelIdentifier'
|
export const SET_PANEL_IDENTIFIER = 'setPanelIdentifier'
|
||||||
|
@ -46,7 +47,17 @@ function setRssItems(rssItems) {
|
||||||
payload: { rssItems },
|
payload: { rssItems },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default function useAppState() {
|
|
||||||
|
type Action =
|
||||||
|
| ReturnType<setRssItems>
|
||||||
|
| ReturnType<setFeedUrls>
|
||||||
|
| ReturnType<setACtivePanel>
|
||||||
|
|
||||||
|
interface ActionSet {
|
||||||
|
[key: string]: Action
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useAppState(): [State, ActionSet] {
|
||||||
const [state, dispatch] = useReducer(reducer, defaultState)
|
const [state, dispatch] = useReducer(reducer, defaultState)
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
|
36
yarn.lock
36
yarn.lock
|
@ -2937,6 +2937,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"charenc@npm:0.0.2":
|
||||||
|
version: 0.0.2
|
||||||
|
resolution: "charenc@npm:0.0.2"
|
||||||
|
checksum: 81dcadbe57e861d527faf6dd3855dc857395a1c4d6781f4847288ab23cffb7b3ee80d57c15bba7252ffe3e5e8019db767757ee7975663ad2ca0939bb8fcaf2e5
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"chownr@npm:^2.0.0":
|
"chownr@npm:^2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "chownr@npm:2.0.0"
|
resolution: "chownr@npm:2.0.0"
|
||||||
|
@ -3321,6 +3328,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"crypt@npm:0.0.2":
|
||||||
|
version: 0.0.2
|
||||||
|
resolution: "crypt@npm:0.0.2"
|
||||||
|
checksum: baf4c7bbe05df656ec230018af8cf7dbe8c14b36b98726939cef008d473f6fe7a4fad906cfea4062c93af516f1550a3f43ceb4d6615329612c6511378ed9fe34
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"crypto-browserify@npm:^3.12.0":
|
"crypto-browserify@npm:^3.12.0":
|
||||||
version: 3.12.0
|
version: 3.12.0
|
||||||
resolution: "crypto-browserify@npm:3.12.0"
|
resolution: "crypto-browserify@npm:3.12.0"
|
||||||
|
@ -3340,13 +3354,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"crypto-js@npm:^4.0.0":
|
|
||||||
version: 4.0.0
|
|
||||||
resolution: "crypto-js@npm:4.0.0"
|
|
||||||
checksum: f769e9331f037d79873061656a26d21cae7a04dde0a64f37b9a6af45989ef0cd1461e64e0e72e6b842b3c865473489f55dfd05653609b90306baf3ea79d7c250
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"css-color-names@npm:^0.0.4":
|
"css-color-names@npm:^0.0.4":
|
||||||
version: 0.0.4
|
version: 0.0.4
|
||||||
resolution: "css-color-names@npm:0.0.4"
|
resolution: "css-color-names@npm:0.0.4"
|
||||||
|
@ -5593,7 +5600,7 @@ fsevents@^2.3.2:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"is-buffer@npm:^1.1.5":
|
"is-buffer@npm:^1.1.5, is-buffer@npm:~1.1.6":
|
||||||
version: 1.1.6
|
version: 1.1.6
|
||||||
resolution: "is-buffer@npm:1.1.6"
|
resolution: "is-buffer@npm:1.1.6"
|
||||||
checksum: 4a186d995d8bbf9153b4bd9ff9fd04ae75068fe695d29025d25e592d9488911eeece84eefbd8fa41b8ddcc0711058a71d4c466dcf6f1f6e1d83830052d8ca707
|
checksum: 4a186d995d8bbf9153b4bd9ff9fd04ae75068fe695d29025d25e592d9488911eeece84eefbd8fa41b8ddcc0711058a71d4c466dcf6f1f6e1d83830052d8ca707
|
||||||
|
@ -7145,6 +7152,17 @@ fsevents@^2.3.2:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"md5@npm:^2.3.0":
|
||||||
|
version: 2.3.0
|
||||||
|
resolution: "md5@npm:2.3.0"
|
||||||
|
dependencies:
|
||||||
|
charenc: 0.0.2
|
||||||
|
crypt: 0.0.2
|
||||||
|
is-buffer: ~1.1.6
|
||||||
|
checksum: a63cacf4018dc9dee08c36e6f924a64ced735b37826116c905717c41cebeb41a522f7a526ba6ad578f9c80f02cb365033ccd67fe186ffbcc1a1faeb75daa9b6e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"mdn-data@npm:2.0.14":
|
"mdn-data@npm:2.0.14":
|
||||||
version: 2.0.14
|
version: 2.0.14
|
||||||
resolution: "mdn-data@npm:2.0.14"
|
resolution: "mdn-data@npm:2.0.14"
|
||||||
|
@ -9309,7 +9327,6 @@ resolve@^2.0.0-next.3:
|
||||||
"@typescript-eslint/eslint-plugin": ^4.28.3
|
"@typescript-eslint/eslint-plugin": ^4.28.3
|
||||||
"@typescript-eslint/parser": ^4.28.3
|
"@typescript-eslint/parser": ^4.28.3
|
||||||
axios: ^0.21.1
|
axios: ^0.21.1
|
||||||
crypto-js: ^4.0.0
|
|
||||||
eslint: ^7.30.0
|
eslint: ^7.30.0
|
||||||
eslint-config-prettier: ^8.3.0
|
eslint-config-prettier: ^8.3.0
|
||||||
eslint-import-resolver-node: ^0.3.4
|
eslint-import-resolver-node: ^0.3.4
|
||||||
|
@ -9322,6 +9339,7 @@ resolve@^2.0.0-next.3:
|
||||||
eslint-plugin-react-hooks: ^4.2.0
|
eslint-plugin-react-hooks: ^4.2.0
|
||||||
htmlparser2: ^6.1.0
|
htmlparser2: ^6.1.0
|
||||||
jest: ^27.0.6
|
jest: ^27.0.6
|
||||||
|
md5: ^2.3.0
|
||||||
parcel: ^2.0.0-beta.2
|
parcel: ^2.0.0-beta.2
|
||||||
prettier: ^2.3.2
|
prettier: ^2.3.2
|
||||||
react: ^17.0.2
|
react: ^17.0.2
|
||||||
|
|
Loading…
Reference in a new issue