Skip to content

Commit

Permalink
feat: added option page login modal
Browse files Browse the repository at this point in the history
  • Loading branch information
baiwusanyu-c committed Apr 13, 2023
1 parent 0363d33 commit e1f971a
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 15 deletions.
12 changes: 11 additions & 1 deletion packages/extension/assets/styles/login.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
.login {
background-repeat: no-repeat;
background-size: cover;
}
}

.login-modal .ant-modal-content{
background-repeat: no-repeat;
background-size: cover;
background-image: url("../../assets/img/login-bg.png");
}

.login-modal .ant-modal-header{
background-color: transparent;
}
124 changes: 121 additions & 3 deletions packages/extension/chrome-option/components/Header-Bar.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { GithubOutlined, UserOutlined } from '@ant-design/icons'
import { Avatar } from 'antd'
import { useEffect, useState } from 'react'
import { GithubOutlined, PoweroffOutlined, UserOutlined } from '@ant-design/icons'
import { Avatar, Button, Form, Input, Modal, Popconfirm, Spin } from 'antd'
import { useCallback, useEffect, useState } from 'react'
import { useMount } from 'ahooks'
import { getUserInfo } from '@pr-checker/fetchGit'
import { useStorage } from '../../hooks/use-storage'
import { CarbonSun } from './Icon-Sun'
import { CarbonMoon } from './Icon-Moon'
import type { IRepoWithPRs } from './Repo-List'
import '../../assets/styles/login.css'
const logoImg = new URL('../../assets/img/logo.png', import.meta.url).href
interface HeaderBarProps {
userInfo: {
avatar_url: string
html_url: string
}
repoInfo: IRepoWithPRs
isLogin?: boolean
}
export const HeaderBar = (props: HeaderBarProps = {
userInfo: {
Expand Down Expand Up @@ -41,6 +46,50 @@ export const HeaderBar = (props: HeaderBarProps = {
const htmlEl = document.querySelector('html') as Element
htmlEl.className = dark ? 'dark' : ''
}, [dark])

// TODO refactor with popup
const [isModalOpen, setIsModalOpen] = useState(false)
const [passwordVisible, setPasswordVisible] = useState(false)
const [opType, setOpType] = useState('')
const { setItem, CACHE_KEYS, getItem, removeItem } = useStorage()

const [loading, setLoading] = useState(false)
const getUserData = useCallback(async(token: string) => {
setLoading(true)
const res = await getUserInfo(token)
await setItem(CACHE_KEYS.USER_INFO, JSON.stringify(res))
setLoading(false)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

const onFinish = useCallback(async(values) => {
const userInfo = await getItem(CACHE_KEYS.USER_INFO)
if (!userInfo)
await getUserData(values.token)

// 存储操作类型和 TOKEN
await Promise.all([
setItem(CACHE_KEYS.OP_TYPE, opType),
setItem(CACHE_KEYS.TOKEN, values.token),
])
setIsModalOpen(false)
setTimeout(() => {
location.reload()
}, 500)
}, [CACHE_KEYS.OP_TYPE, CACHE_KEYS.TOKEN, CACHE_KEYS.USER_INFO, opType, setItem, getItem, getUserData])

const logout = useCallback(async() => {
// 存储操作类型和 TOKEN
await Promise.all([
removeItem(CACHE_KEYS.OP_TYPE),
removeItem(CACHE_KEYS.TOKEN),
removeItem(CACHE_KEYS.USER_INFO),
])
setIsModalOpen(false)
setTimeout(() => {
location.reload()
}, 500)
}, [CACHE_KEYS.OP_TYPE, CACHE_KEYS.TOKEN, setItem])
return (
<div id="header_bar" className="flex justify-between items-center h-full py-2 px-8 dark:bg-gray-7">
<div className="flex items-center">
Expand All @@ -62,7 +111,76 @@ export const HeaderBar = (props: HeaderBarProps = {
dark ? <CarbonMoon role="button" style={{ fontSize: '30px', color: '#888888' }} className="mx-4 cursor-pointer" onClick={() => toggleTheme(false)} />
: <CarbonSun role="button" style={{ fontSize: '30px', color: '#888888' }} className="mx-4 cursor-pointer" onClick={() => toggleTheme(true)} />
}
{
!props.isLogin ? <Button className="mx-4" type="primary"
htmlType="submit"
onClick={() => { setIsModalOpen(true) }}
> Login
</Button>
: <Popconfirm
title="Logout"
description="Are you sure to logout?"
okText="Yes"
cancelText="No"
onConfirm={logout}
>
<PoweroffOutlined role="button" style={{ fontSize: '30px', color: '#888888' }} />
</Popconfirm>
}
</div>
{/* login modal */}
<Modal title={
<div className="flex items-center justify-between mb-2">
<div className="flex items-center">
<a
href="https://github.com/baiwusanyu-c/pr-checker"
target="_blank" rel="noreferrer"
title="https://github.com/baiwusanyu-c/pr-checker"
>
<img src={logoImg} alt="pr-checker" className="w-30px h-30px mr-2" />
</a>
<h1 className="text-gray-600 leading-1 m-0">
pr-checker
</h1>
</div>
</div>
}
wrapClassName="login-modal"
onCancel={() => setIsModalOpen(false)}
open={isModalOpen}
footer={null}
>
<Spin spinning={loading} tip="Loading...">
<Form
layout="vertical "
onFinish={onFinish}
>
<Form.Item label="Github Token" name="token" rules={[{ required: true }]}>
<Input.Password
placeholder="input github token"
visibilityToggle={{
visible: passwordVisible,
onVisibleChange: setPasswordVisible,
}}
/>
</Form.Item>
<Form.Item label=" ">
<div className="flex justify-center items-center w-full">
<Button className="mx-4" type="primary"
htmlType="submit"
onClick={() => setOpType('merge')}
>Merge PR
</Button>
<Button className="mx-4" type="primary"
htmlType="submit"
onClick={() => setOpType('rebase')}
>Rebase PR
</Button>
</div>
</Form.Item>
</Form>
</Spin>
</Modal>
</div>
)
}
8 changes: 4 additions & 4 deletions packages/extension/chrome-option/components/Repo-List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export const RepoList = (props: IRepoListProps) => {
const [loading, setLoading] = useState(false)
const { token, userName, opType, onSelect } = props
useEffect(() => {
setLoading(true)
if (opType === 'rebase') {
token && setLoading(true)
if (opType === 'rebase' && token) {
getIssuesPR(token, userName)
.then((res) => {
// 使用 map 避免重复遍历
Expand Down Expand Up @@ -56,7 +56,7 @@ export const RepoList = (props: IRepoListProps) => {
})
}
// merge 模式 我们只获取仓库信息
if (opType === 'merge') {
if (opType === 'merge' && token) {
getAllRepo(token).then((res) => {
const hasIssuesRepo = res.filter(val => val.open_issues_count > 0 && !val.fork)
const repos = new Map<string, IRepoWithPRs>()
Expand Down Expand Up @@ -122,7 +122,7 @@ export const RepoList = (props: IRepoListProps) => {
<div id="pr_checker_repo_list">
<Search placeholder="Input repo name" className="mb-4 !dark:bg-gray-7" onChange={run} allowClear />
<Button type="primary" className="mb-4 w-full" >
{ `${props.opType} all`}
{ `${props.opType || 'rebase'} all`}
</Button>
<ul className="list-none p-0 min-w-1 border-1"
style={loading ? { display: 'flex', justifyContent: 'center' } : {}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export const PrList = (props: PrListProps) => {
/>

<Button type="primary" className="mx-4 flex-1" onClick={handleOpAll}>
{ `${props.opType} all`}
{ `${props.opType || 'rebase'} all`}
</Button>

<Tooltip title="reload">
Expand Down
19 changes: 13 additions & 6 deletions packages/extension/chrome-option/view/OptionPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Layout } from 'antd'
import { useEffect, useState } from 'react'
import { isEmptyObj } from '@pr-checker/utils/common'
import { getAllStorageSyncData } from '../../hooks/use-storage'
import { RepoList } from '../components/Repo-List'
import { HeaderBar } from '../components/Header-Bar'
Expand All @@ -9,19 +10,25 @@ import type { IRepoWithPRs } from '../components/Repo-List'
const logoImg = new URL('../../assets/img/logo.png', import.meta.url).href
const { Header, Sider, Content } = Layout

// TODO: token is empty ?
export const OptionPage = () => {
const [storeData, setStoreData] = useState<Record<string, string | any>>({
USER_INFO: {
login: '',
},
})

const [isLogin, setIsLogin] = useState(false)
useEffect(() => {
const run = async() => {
// const data = await getAllStorageSyncData()
const data = { OP_TYPE: 'merge', TOKEN: '', USER_INFO: '{"login":"baiwusanyu-c", "avatar_url": "https://avatars.githubusercontent.com/u/32354856?v=4"}' }
data.USER_INFO = JSON.parse(data.USER_INFO)
setStoreData(data as Record<string, any>)
const data = await getAllStorageSyncData()
if (!isEmptyObj(data)) {
// const data = { OP_TYPE: 'merge', TOKEN: '', USER_INFO: '{"login":"baiwusanyu-c", "avatar_url": "https://avatars.githubusercontent.com/u/32354856?v=4"}' }
data.USER_INFO = JSON.parse(data.USER_INFO)
setStoreData(data as Record<string, any>)
setIsLogin(true)
} else {
setIsLogin(false)
}
}
run()
}, [])
Expand Down Expand Up @@ -60,7 +67,7 @@ export const OptionPage = () => {
</Sider>
<Layout>
<Header className="shadow shadow-main p-0 bg-white">
<HeaderBar userInfo={storeData.USER_INFO} repoInfo={selectRepo} />
<HeaderBar userInfo={storeData.USER_INFO} repoInfo={selectRepo} isLogin={isLogin} />
</Header>
<Content style={{ height: 'calc(100vh - 64px)' }}>
{storeData.OP_TYPE === 'rebase'
Expand Down

0 comments on commit e1f971a

Please sign in to comment.