Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
react-rxjs
  • Loading branch information
josepot committed Sep 8, 2020
1 parent e32606f commit d3932f4
Show file tree
Hide file tree
Showing 14 changed files with 366 additions and 417 deletions.
4 changes: 3 additions & 1 deletion package.json
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@react-rxjs/core": "^0.3.0",
"@types/classnames": "^2.2.10",
"@types/jest": "26.0.10",
"@types/node": "14.6.2",
Expand All @@ -11,14 +12,15 @@
"@types/react-dom": "16.9.8",
"@types/react-paginate": "^6.2.1",
"@types/webpack-env": "^1.15.2",
"axios": "^0.19.0",
"classnames": "^2.2.6",
"parse-link-header": "^1.0.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-error-boundary": "^2.3.1",
"react-markdown": "^4.3.1",
"react-paginate": "^6.3.2",
"react-scripts": "^3.4.3",
"rxjs": "^6.6.3",
"typescript": "3.5.3"
},
"scripts": {
Expand Down
59 changes: 27 additions & 32 deletions src/api/githubAPI.tsx
@@ -1,5 +1,7 @@
import axios from 'axios'
import { ajax } from 'rxjs/ajax'
import parseLink, { Links } from 'parse-link-header'
import { map, pluck } from 'rxjs/operators'
import { Observable } from 'rxjs'

export interface Label {
id: number
Expand Down Expand Up @@ -64,47 +66,40 @@ const getPageCount = (pageLinks: Links) => {
}
}

export async function getIssues(
export function getIssues(
org: string,
repo: string,
page = 1
): Promise<IssuesResult> {
): Observable<IssuesResult> {
const url = `https://api.github.com/repos/${org}/${repo}/issues?per_page=25&page=${page}`

try {
const issuesResponse = await axios.get<Issue[]>(url)
let pageCount = 0
const pageLinks = parseLink(issuesResponse.headers.link)

if (pageLinks !== null) {
pageCount = getPageCount(pageLinks)
}

return {
pageLinks,
pageCount,
issues: issuesResponse.data,
}
} catch (err) {
throw err
}
return ajax.get(url).pipe(
map((r) => {
let pageCount = 0
const pageLinks = parseLink(r.xhr.getResponseHeader('link') as string)

if (pageLinks !== null) {
pageCount = getPageCount(pageLinks)
}

return {
pageLinks,
pageCount,
issues: r.response as Issue[],
}
})
)
}

export async function getRepoDetails(org: string, repo: string) {
export function getRepoOpenIssuesCount(org: string, repo: string) {
const url = `https://api.github.com/repos/${org}/${repo}`

const { data } = await axios.get<RepoDetails>(url)
return data
return ajax.getJSON<RepoDetails>(url).pipe(pluck('open_issues_count'))
}

export async function getIssue(org: string, repo: string, number: number) {
export function getIssue(org: string, repo: string, number: number) {
const url = `https://api.github.com/repos/${org}/${repo}/issues/${number}`

const { data } = await axios.get<Issue>(url)
return data
return ajax.getJSON<Issue>(url)
}

export async function getComments(url: string) {
const { data } = await axios.get<Comment[]>(url)
return data
export function getComments(url: string) {
return ajax.getJSON<Comment[]>(url)
}
93 changes: 17 additions & 76 deletions src/app/App.tsx
@@ -1,82 +1,23 @@
import React, { useState } from 'react'
import React from 'react'
import './App.css'

import { RepoSearchForm } from 'features/repoSearch/RepoSearchForm'
import { IssuesListPage } from 'features/issuesList/IssuesListPage'
import { IssueDetailsPage } from 'features/issueDetails/IssueDetailsPage'

const ORG = 'rails'
const REPO = 'rails'

type CurrentDisplay =
| {
type: 'issues'
}
| {
type: 'comments'
issueId: number
}

const App: React.FC = () => {
const [org, setOrg] = useState(ORG)
const [repo, setRepo] = useState(REPO)
const [page, setPage] = useState(1)
const [currentDisplay, setCurrentDisplay] = useState<CurrentDisplay>({
type: 'issues',
})

const setOrgAndRepo = (org: string, repo: string) => {
setOrg(org)
setRepo(repo)
}

const setJumpToPage = (page: number) => {
setPage(page)
}

const showIssuesList = () => {
setCurrentDisplay({ type: 'issues' })
}

const showIssueComments = (issueId: number) => {
setCurrentDisplay({ type: 'comments', issueId })
}

let content

if (currentDisplay.type === 'issues') {
content = (
<React.Fragment>
<RepoSearchForm
org={org}
repo={repo}
setOrgAndRepo={setOrgAndRepo}
setJumpToPage={setJumpToPage}
/>
<IssuesListPage
org={org}
repo={repo}
page={page}
setJumpToPage={setJumpToPage}
showIssueComments={showIssueComments}
/>
</React.Fragment>
)
} else {
const { issueId } = currentDisplay
const key = `${org}/${repo}/${issueId}`
content = (
<IssueDetailsPage
key={key}
org={org}
repo={repo}
issueId={issueId}
showIssuesList={showIssuesList}
/>
)
}

return <div className="App">{content}</div>
}
import { useSelectedIssueId } from 'state'

const List: React.FC = () =>
useSelectedIssueId() === null ? (
<>
<RepoSearchForm />
<IssuesListPage />
</>
) : null

const App: React.FC = () => (
<div className="App">
<List />
<IssueDetailsPage />
</div>
)

export default App
24 changes: 4 additions & 20 deletions src/features/issueDetails/IssueComments.tsx
Expand Up @@ -2,15 +2,11 @@ import React from 'react'
import ReactMarkdown from 'react-markdown'

import { insertMentionLinks } from 'utils/stringUtils'
import { Issue, Comment } from 'api/githubAPI'
import { Comment } from 'api/githubAPI'
import { UserWithAvatar } from 'components/UserWithAvatar'

import styles from './IssueComments.module.css'

interface ICLProps {
issue: Issue
comments: Comment[]
}
import { useIssueComments } from 'state'

interface ICProps {
comment: Comment
Expand All @@ -35,20 +31,8 @@ function IssueComment({ comment }: ICProps) {
)
}

export function IssueComments({ comments = [], issue }: ICLProps) {
// The issue has no comments
if (issue.comments === 0) {
return <div className="issue-detail--no-comments">No comments</div>
}

// The issue has comments, but they're not loaded yet
if (!comments || comments.length === 0) {
return (
<div className="issue-detail--comments-loading">Comments loading...</div>
)
}

// Comments are loaded
export const IssueComments: React.FC = () => {
const comments = useIssueComments()
return (
<ul className={styles.commentsList}>
{comments.map((comment) => (
Expand Down

0 comments on commit d3932f4

Please sign in to comment.