Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit fa03aa8

Browse files
author
Noah Lee
authored
Separate the state from the views (#401)
1 parent c702383 commit fa03aa8

File tree

16 files changed

+357
-143
lines changed

16 files changed

+357
-143
lines changed

ui/src/components/Pagination.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Button } from 'antd'
22

3-
interface PaginationProps {
3+
export interface PaginationProps {
44
disabledPrev: boolean
55
disabledNext: boolean
66
onClickPrev(): void

ui/src/views/home/RepoList.tsx

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,18 @@
1-
import { shallowEqual } from 'react-redux'
21
import { List, Typography } from 'antd'
32
import moment from "moment"
43

5-
import { useAppSelector } from '../../redux/hooks'
6-
import { Deployment } from '../../models'
4+
import { Repo, Deployment } from '../../models'
75
import UserAvatar from '../../components/UserAvatar'
86
import DeploymentStatusBadge from "../../components/DeploymentStatusBadge"
97
import DeploymentRefCode from "../../components/DeploymentRefCode"
10-
import Spin from '../../components/Spin'
118

129
const { Text, Paragraph } = Typography
1310

14-
export default function RepoList(): JSX.Element {
15-
const { loading, repos } = useAppSelector(state => state.home, shallowEqual)
16-
17-
if (loading) {
18-
return (
19-
<div style={{textAlign: "center"}}>
20-
<Spin />
21-
</div>
22-
)
23-
}
11+
export interface RepoListProps {
12+
repos: Repo[]
13+
}
2414

15+
export default function RepoList({repos}: RepoListProps): JSX.Element {
2516
return (
2617
<List
2718
dataSource={repos}

ui/src/views/home/index.tsx

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@ import { RequestStatus } from '../../models'
1010
import { subscribeEvents } from "../../apis"
1111

1212
import Main from '../main'
13-
import RepoList from './RepoList'
13+
import RepoList, { RepoListProps } from './RepoList'
1414
import Pagination from '../../components/Pagination'
15+
import Spin from '../../components/Spin'
1516

1617
const { Search } = Input
1718
const { actions } = homeSlice
1819

19-
export default function Home(): JSX.Element {
20-
const { repos, page, syncing } = useAppSelector(state => state.home, shallowEqual)
20+
// Binding the state to the deployment page.
21+
export default ():JSX.Element => {
22+
const { loading, repos, page, syncing } = useAppSelector(state => state.home, shallowEqual)
2123
const dispatch = useAppDispatch()
2224

2325
useEffect(() => {
@@ -59,6 +61,43 @@ export default function Home(): JSX.Element {
5961

6062
return (
6163
<Main>
64+
<Home
65+
loading={loading}
66+
syncing={syncing}
67+
page={page}
68+
repos={repos}
69+
search={search}
70+
onClickSync={onClickSync}
71+
onClickPrev={onClickPrev}
72+
onClickNext={onClickNext}
73+
/>
74+
</Main>
75+
)
76+
}
77+
78+
interface HomeProps extends RepoListProps {
79+
loading: boolean
80+
syncing: RequestStatus
81+
page: number
82+
search(q: string): void
83+
onClickSync(): void
84+
onClickPrev(): void
85+
onClickNext(): void
86+
}
87+
88+
function Home({
89+
loading,
90+
page,
91+
syncing,
92+
repos,
93+
search,
94+
onClickSync,
95+
onClickPrev,
96+
onClickNext,
97+
}: HomeProps): JSX.Element {
98+
99+
return (
100+
<>
62101
<Helmet>
63102
<title>Home</title>
64103
</Helmet>
@@ -82,7 +121,12 @@ export default function Home(): JSX.Element {
82121
<Search placeholder="Search repository ..." onSearch={search} size="large" enterButton />
83122
</div>
84123
<div style={{"marginTop": "20px"}}>
85-
<RepoList />
124+
{(loading)?
125+
<div style={{textAlign: "center"}}>
126+
<Spin />
127+
</div>
128+
:
129+
<RepoList repos={repos} />}
86130
</div>
87131
<div style={{marginTop: "20px", textAlign: "center"}}>
88132
<Pagination
@@ -92,6 +136,6 @@ export default function Home(): JSX.Element {
92136
onClickNext={onClickNext}
93137
/>
94138
</div>
95-
</Main>
139+
</>
96140
)
97141
}

ui/src/views/main/Content.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
import { shallowEqual } from "react-redux"
21
import { Row, Col, Result, Button} from "antd"
32

4-
import { useAppSelector, useAppDispatch } from "../../redux/hooks"
5-
import { mainSlice as slice } from "../../redux/main"
63
import React from "react"
74

8-
export default function Content(props: React.PropsWithChildren<any>): JSX.Element {
9-
const {
10-
available,
11-
authorized,
12-
expired,
13-
} = useAppSelector(state => state.main, shallowEqual)
14-
const dispatch = useAppDispatch()
5+
export interface ContentProps {
6+
available: boolean
7+
authorized: boolean
8+
expired: boolean
9+
onClickRetry(): void
10+
}
11+
12+
export default function Content({
13+
available,
14+
authorized,
15+
expired,
16+
children,
17+
onClickRetry,
18+
}: React.PropsWithChildren<ContentProps>): JSX.Element {
1519

16-
const onClickRetry = () => {
17-
dispatch(slice.actions.setAvailable(true))
18-
dispatch(slice.actions.setExpired(false))
19-
}
2020

2121
let content: React.ReactNode
2222
if (!available) {
@@ -44,7 +44,7 @@ export default function Content(props: React.PropsWithChildren<any>): JSX.Elemen
4444
extra={[<Button key="console" type="primary" onClick={onClickRetry}>Retry</Button>]}
4545
/>
4646
} else {
47-
content = props.children
47+
content = children
4848
}
4949

5050
return (

ui/src/views/main/Header.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
import { useState } from "react"
2-
import { shallowEqual } from "react-redux"
32
import { Menu, Row, Col, Button, Drawer, Avatar, Dropdown, Badge, Space} from "antd"
43
import { SettingFilled } from "@ant-design/icons"
54

6-
import { useAppSelector } from "../../redux/hooks"
7-
5+
import { Deployment, User, Review } from "../../models"
86
import RecentActivities from "../../components/RecentActivities"
97

108
import Logo from "../../logo.svg"
119

12-
export default function Header(): JSX.Element {
13-
const {
14-
authorized,
15-
user,
16-
deployments,
17-
reviews,
18-
} = useAppSelector(state => state.main, shallowEqual)
10+
export interface HeaderProps {
11+
user: User | undefined
12+
deployments: Deployment[]
13+
reviews: Review[]
14+
}
1915

16+
export default function Header({
17+
user,
18+
deployments,
19+
reviews,
20+
}: HeaderProps): JSX.Element {
2021
const activitiesCount = deployments.length + reviews.length
2122

2223
const [ isRecentActivitiesVisible, setRecentActivitiesVisible ] = useState(false)
@@ -63,7 +64,7 @@ export default function Header(): JSX.Element {
6364
reviews={reviews}
6465
/>
6566
</Drawer>
66-
{(authorized) ?
67+
{(user) ?
6768
<Dropdown
6869
overlay={(
6970
<Menu>

ui/src/views/main/LicenseWarningFooter.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import moment from "moment"
2-
import { shallowEqual } from "react-redux"
32

4-
import { useAppSelector } from "../../redux/hooks"
3+
import { License } from "../../models"
54

6-
export default function LicenseWarningFooter(): JSX.Element {
7-
const { license } = useAppSelector(state => state.main, shallowEqual)
5+
export interface LicenseWarningFooterProps {
6+
license?: License
7+
}
88

9+
export default function LicenseWarningFooter({
10+
license
11+
}: LicenseWarningFooterProps): JSX.Element {
912
if (!license) {
1013
return <></>
1114
}

ui/src/views/main/index.tsx

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,22 @@ import {
1616
mainSlice as slice
1717
} from "../../redux/main"
1818

19-
import MainHeader from "./Header"
20-
import MainContent from "./Content"
21-
import LicenseWarning from "./LicenseWarningFooter"
19+
import MainHeader, { HeaderProps } from "./Header"
20+
import MainContent, { ContentProps } from "./Content"
21+
import LicenseWarning, { LicenseWarningFooterProps } from "./LicenseWarningFooter"
2222

2323
const { Header, Content, Footer } = Layout
2424

25-
// eslint-disable-next-line
26-
export default function Main(props: React.PropsWithChildren<{}>) {
25+
export default (props: React.PropsWithChildren<any>): JSX.Element => {
2726
const {
27+
authorized,
28+
available,
29+
expired,
30+
user,
2831
deployments,
2932
reviews,
3033
} = useAppSelector(state => state.main, shallowEqual)
34+
3135
const dispatch = useAppDispatch()
3236

3337
useEffect(() => {
@@ -48,6 +52,38 @@ export default function Main(props: React.PropsWithChildren<{}>) {
4852
}
4953
}, [dispatch])
5054

55+
const onClickRetry = () => {
56+
dispatch(slice.actions.setAvailable(true))
57+
dispatch(slice.actions.setExpired(false))
58+
}
59+
60+
return (
61+
<Main
62+
authorized={authorized}
63+
available={available}
64+
expired={expired}
65+
user={user}
66+
deployments={deployments}
67+
reviews={reviews}
68+
onClickRetry={onClickRetry}
69+
children={props.children}
70+
/>
71+
)
72+
}
73+
74+
interface MainProps extends HeaderProps, ContentProps, LicenseWarningFooterProps {}
75+
76+
function Main({
77+
authorized,
78+
available,
79+
expired,
80+
user,
81+
deployments,
82+
reviews,
83+
license,
84+
children,
85+
onClickRetry
86+
}: React.PropsWithChildren<MainProps>) {
5187
return (
5288
<Layout className="layout">
5389
<Helmet>
@@ -58,16 +94,27 @@ export default function Main(props: React.PropsWithChildren<{}>) {
5894
<link rel="icon" href="/favicon.ico" />}
5995
</Helmet>
6096
<Header>
61-
<MainHeader />
97+
<MainHeader
98+
user={user}
99+
deployments={deployments}
100+
reviews={reviews}
101+
/>
62102
</Header>
63103
<Content style={{ padding: "50px 50px" }}>
64-
<MainContent>
65-
{props.children}
104+
<MainContent
105+
authorized={authorized}
106+
available={available}
107+
expired={expired}
108+
onClickRetry={onClickRetry}
109+
>
110+
{children}
66111
</MainContent>
67112
</Content>
68113
<Footer style={{ textAlign: "center" }}>
69114
<div>
70-
<LicenseWarning />
115+
<LicenseWarning
116+
license={license}
117+
/>
71118
</div>
72119
<div>
73120
Gitploy ©{moment().format("YYYY")} Created by Gitploy.IO

ui/src/views/members/MemberList.tsx

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,31 @@
1-
import { shallowEqual } from "react-redux"
21
import { List, Switch, Button, Avatar } from "antd"
32

4-
import { useAppSelector, useAppDispatch } from "../../redux/hooks"
5-
import { updateUser, deleteUser } from "../../redux/members"
6-
73
import { User } from "../../models"
84

9-
export default function MemberList(): JSX.Element {
10-
const { users } = useAppSelector(state => state.members, shallowEqual)
11-
const dispatch = useAppDispatch()
12-
13-
const onChangeSwitch = (user: User, checked: boolean) => {
14-
dispatch(updateUser({user, admin: checked}))
15-
}
16-
17-
const onClickDelete = (user: User) => {
18-
dispatch(deleteUser(user))
19-
}
5+
export interface MemberListProps {
6+
users: User[]
7+
onChangeSwitch(user: User, checked: boolean): void
8+
onClickDelete(user: User): void
9+
}
2010

11+
export default function MemberList(props: MemberListProps): JSX.Element {
2112
return (
2213
<List
2314
itemLayout="horizontal"
24-
dataSource={users}
15+
dataSource={props.users}
2516
renderItem={(user) => (
2617
<List.Item
2718
actions={[
2819
<Switch
2920
checkedChildren="Adm"
3021
unCheckedChildren="Mem"
3122
checked={user.admin}
32-
onChange={(checked) => {onChangeSwitch(user, checked)}}
23+
onChange={(checked) => {props.onChangeSwitch(user, checked)}}
3324
/>,
3425
<Button
3526
type="primary"
3627
danger
37-
onClick={() => {onClickDelete(user)}}
28+
onClick={() => {props.onClickDelete(user)}}
3829
>
3930
Delete
4031
</Button>

0 commit comments

Comments
 (0)