Skip to content

Commit f90e46f

Browse files
committed
refactor: support auth login in share page & improve auth client button styles
1 parent 5fca2ee commit f90e46f

File tree

10 files changed

+177
-45
lines changed

10 files changed

+177
-45
lines changed

frontend/src/app/pages/LoginPage/LoginForm.tsx

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,63 +19,52 @@
1919
import { Button, Form, Input } from 'antd';
2020
import { AuthForm } from 'app/components';
2121
import usePrefixI18N from 'app/hooks/useI18NPrefix';
22-
import {
23-
selectLoggedInUser,
24-
selectLoginLoading,
25-
selectOauth2Clients,
26-
} from 'app/slice/selectors';
27-
import { getOauth2Clients } from 'app/slice/thunks';
28-
import React, { useCallback, useEffect, useState } from 'react';
29-
import { useDispatch, useSelector } from 'react-redux';
22+
import { User } from 'app/slice/types';
23+
import React, { useCallback, useState } from 'react';
3024
import { Link, useHistory } from 'react-router-dom';
3125
import styled from 'styled-components/macro';
3226
import {
3327
BORDER_RADIUS,
3428
LINE_HEIGHT_ICON_LG,
29+
LINE_HEIGHT_ICON_XXL,
3530
SPACE_MD,
31+
SPACE_XS,
3632
} from 'styles/StyleConstants';
3733
import { getToken } from 'utils/auth';
34+
import { AUTH_CLIENT_ICON_MAPPING } from './constants';
35+
36+
interface LoginFormProps {
37+
loading: boolean;
38+
loggedInUser?: User | null;
39+
oauth2Clients: Array<{ name: string; value: string }>;
40+
registerEnable?: boolean;
41+
modal?: boolean;
42+
onLogin?: (value) => void;
43+
}
3844

3945
export function LoginForm({
46+
loading,
47+
loggedInUser,
48+
oauth2Clients,
4049
registerEnable = true,
4150
modal = false,
4251
onLogin,
43-
}: {
44-
registerEnable?: boolean;
45-
modal?: boolean;
46-
onLogin?: (value) => void;
47-
}) {
52+
}: LoginFormProps) {
4853
const [switchUser, setSwitchUser] = useState(false);
49-
const dispatch = useDispatch();
5054
const history = useHistory();
51-
const loading = useSelector(selectLoginLoading);
52-
const loggedInUser = useSelector(selectLoggedInUser);
5355
const [form] = Form.useForm();
5456
const logged = !!getToken();
5557
const t = usePrefixI18N('login');
5658
const tg = usePrefixI18N('global');
57-
const oauth2Clients = useSelector(selectOauth2Clients);
5859

5960
const toApp = useCallback(() => {
6061
history.replace('/');
6162
}, [history]);
6263

63-
useEffect(() => {
64-
dispatch(getOauth2Clients());
65-
}, [dispatch]);
66-
6764
const onSwitch = useCallback(() => {
6865
setSwitchUser(true);
6966
}, []);
7067

71-
let Oauth2BtnList = oauth2Clients.map(client => {
72-
return (
73-
<Oauth2Button key={client.value} href={client.value}>
74-
{client.name}
75-
</Oauth2Button>
76-
);
77-
});
78-
7968
return (
8069
<AuthForm>
8170
{logged && !switchUser && !modal ? (
@@ -142,8 +131,22 @@ export function LoginForm({
142131
)}
143132
</Links>
144133
)}
145-
146-
{Oauth2BtnList}
134+
{oauth2Clients.length > 0 && (
135+
<>
136+
<AuthTitle>{t('authTitle')}</AuthTitle>
137+
{oauth2Clients.map(({ name, value }) => (
138+
<AuthButton
139+
key={value}
140+
size="large"
141+
icon={AUTH_CLIENT_ICON_MAPPING[name.toLowerCase()]}
142+
href={value}
143+
block
144+
>
145+
{name}
146+
</AuthButton>
147+
))}
148+
</>
149+
)}
147150
</Form>
148151
)}
149152
</AuthForm>
@@ -154,16 +157,6 @@ const Links = styled.div`
154157
display: flex;
155158
`;
156159

157-
const Oauth2Button = styled.a`
158-
display: block;
159-
height: 36px;
160-
font-weight: bold;
161-
line-height: 36px;
162-
color: #fff;
163-
text-align: center;
164-
background-color: blue;
165-
`;
166-
167160
const LinkButton = styled(Link)`
168161
flex: 1;
169162
line-height: ${LINE_HEIGHT_ICON_LG};
@@ -173,6 +166,20 @@ const LinkButton = styled(Link)`
173166
}
174167
`;
175168

169+
const AuthTitle = styled.p`
170+
line-height: ${LINE_HEIGHT_ICON_XXL};
171+
color: ${p => p.theme.textColorLight};
172+
text-align: center;
173+
`;
174+
175+
const AuthButton = styled(Button)`
176+
margin-bottom: ${SPACE_XS};
177+
178+
&:last-child {
179+
margin-bottom: 0;
180+
}
181+
`;
182+
176183
const UserPanel = styled.div`
177184
display: flex;
178185
padding: ${SPACE_MD};
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Datart
3+
*
4+
* Copyright 2021
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import {
20+
AlipayCircleOutlined,
21+
AliyunOutlined,
22+
CodepenCircleOutlined,
23+
DingdingOutlined,
24+
FacebookOutlined,
25+
GithubOutlined,
26+
GitlabOutlined,
27+
GoogleOutlined,
28+
InstagramOutlined,
29+
QqOutlined,
30+
SlackOutlined,
31+
WeiboCircleOutlined,
32+
ZhihuOutlined,
33+
} from '@ant-design/icons';
34+
35+
export const AUTH_CLIENT_ICON_MAPPING = {
36+
github: <GithubOutlined />,
37+
dingding: <DingdingOutlined />,
38+
qq: <QqOutlined />,
39+
gitlab: <GitlabOutlined />,
40+
weibo: <WeiboCircleOutlined />,
41+
zhihu: <ZhihuOutlined />,
42+
alipay: <AlipayCircleOutlined />,
43+
aliyun: <AliyunOutlined />,
44+
google: <GoogleOutlined />,
45+
facebook: <FacebookOutlined />,
46+
slack: <SlackOutlined />,
47+
instagram: <InstagramOutlined />,
48+
codepen: <CodepenCircleOutlined />,
49+
};

frontend/src/app/pages/LoginPage/index.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@
1818

1919
import { Brand } from 'app/components/Brand';
2020
import { Version } from 'app/components/Version';
21-
import { selectSystemInfo } from 'app/slice/selectors';
22-
import { login } from 'app/slice/thunks';
23-
import React, { useCallback } from 'react';
21+
import {
22+
selectLoggedInUser,
23+
selectLoginLoading,
24+
selectOauth2Clients,
25+
selectSystemInfo,
26+
} from 'app/slice/selectors';
27+
import { getOauth2Clients, login } from 'app/slice/thunks';
28+
import React, { useCallback, useEffect } from 'react';
2429
import { useDispatch, useSelector } from 'react-redux';
2530
import { useHistory } from 'react-router-dom';
2631
import styled from 'styled-components/macro';
@@ -30,6 +35,13 @@ export function LoginPage() {
3035
const dispatch = useDispatch();
3136
const history = useHistory();
3237
const systemInfo = useSelector(selectSystemInfo);
38+
const loading = useSelector(selectLoginLoading);
39+
const loggedInUser = useSelector(selectLoggedInUser);
40+
const oauth2Clients = useSelector(selectOauth2Clients);
41+
42+
useEffect(() => {
43+
dispatch(getOauth2Clients());
44+
}, [dispatch]);
3345

3446
const onLogin = useCallback(
3547
values => {
@@ -48,6 +60,9 @@ export function LoginPage() {
4860
<Wrapper>
4961
<Brand />
5062
<LoginForm
63+
loading={loading}
64+
loggedInUser={loggedInUser}
65+
oauth2Clients={oauth2Clients}
5166
registerEnable={systemInfo?.registerEnable}
5267
onLogin={onLogin}
5368
/>

frontend/src/app/pages/SharePage/ShareLoginModal.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,30 @@
1717
*/
1818

1919
import { LoginForm } from 'app/pages/LoginPage/LoginForm';
20+
import { useEffect } from 'react';
21+
import { useDispatch, useSelector } from 'react-redux';
2022
import styled from 'styled-components';
23+
import { selectLoginLoading, selectOauth2Clients } from './slice/selectors';
24+
import { getOauth2Clients } from './slice/thunks';
2125

2226
function ShareLoginModal({ visible, onChange }) {
27+
const dispatch = useDispatch();
28+
const loading = useSelector(selectLoginLoading);
29+
const oauth2Clients = useSelector(selectOauth2Clients);
30+
31+
useEffect(() => {
32+
dispatch(getOauth2Clients());
33+
}, [dispatch]);
34+
2335
return (
2436
visible && (
2537
<LoginWrapper>
26-
<LoginForm modal={true} onLogin={onChange} />
38+
<LoginForm
39+
loading={loading}
40+
oauth2Clients={oauth2Clients}
41+
modal={true}
42+
onLogin={onChange}
43+
/>
2744
</LoginWrapper>
2845
)
2946
);

frontend/src/app/pages/SharePage/slice/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import { useInjectReducer } from 'utils/@reduxjs/injectReducer';
3131
import {
3232
fetchAvailableSourceFunctions,
3333
fetchShareDataSetByPreviewChartAction,
34+
fetchShareVizInfo,
35+
getOauth2Clients,
3436
} from './thunks';
3537
// import { fetchShareDataSetByPreviewChartAction } from './thunk';
3638
import { ExecuteToken, SharePageState, ShareVizInfo } from './types';
@@ -46,6 +48,8 @@ export const initialState: SharePageState = {
4648
headlessBrowserRenderSign: false,
4749
pageWidthHeight: [0, 0],
4850
shareDownloadPolling: false,
51+
loginLoading: false,
52+
oauth2Clients: [],
4953
availableSourceFunctions: [],
5054
};
5155

@@ -173,6 +177,15 @@ export const slice = createSlice({
173177
},
174178
extraReducers: builder => {
175179
builder
180+
.addCase(fetchShareVizInfo.pending, state => {
181+
state.loginLoading = true;
182+
})
183+
.addCase(fetchShareVizInfo.fulfilled, state => {
184+
state.loginLoading = false;
185+
})
186+
.addCase(fetchShareVizInfo.rejected, state => {
187+
state.loginLoading = false;
188+
})
176189
.addCase(
177190
fetchShareDataSetByPreviewChartAction.fulfilled,
178191
(state, { payload }) => {
@@ -186,6 +199,12 @@ export const slice = createSlice({
186199
.addCase(fetchShareDataSetByPreviewChartAction.rejected, state => {
187200
state.headlessBrowserRenderSign = true;
188201
})
202+
.addCase(getOauth2Clients.fulfilled, (state, action) => {
203+
state.oauth2Clients = action.payload.map(x => ({
204+
name: Object.keys(x)[0],
205+
value: x[Object.keys(x)[0]],
206+
}));
207+
})
189208
.addCase(
190209
fetchAvailableSourceFunctions.fulfilled,
191210
(state, { payload }) => {

frontend/src/app/pages/SharePage/slice/selectors.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ export const selectSharePassword = createSelector(
7171
shareState => shareState.sharePassword,
7272
);
7373

74+
export const selectLoginLoading = createSelector(
75+
[selectDomain],
76+
shareState => shareState.loginLoading,
77+
);
78+
79+
export const selectOauth2Clients = createSelector(
80+
[selectDomain],
81+
appState => appState.oauth2Clients,
82+
);
83+
7484
export const selectAvailableSourceFunctions = createSelector(
7585
[selectDomain],
7686
shareState => shareState.availableSourceFunctions,

frontend/src/app/pages/SharePage/slice/thunks.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,17 @@ export const updateGroupAndFetchDatasetForShare = createAsyncThunk(
248248
},
249249
);
250250

251+
export const getOauth2Clients = createAsyncThunk<[]>(
252+
'app/getOauth2Clients',
253+
async () => {
254+
const { data } = await request2<[]>({
255+
url: '/tpa/getOauth2Clients',
256+
method: 'GET',
257+
});
258+
return data;
259+
},
260+
);
261+
251262
export const fetchAvailableSourceFunctions = createAsyncThunk<
252263
string[],
253264
{ sourceId: string }

frontend/src/app/pages/SharePage/slice/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export interface SharePageState {
3535
headlessBrowserRenderSign: boolean;
3636
pageWidthHeight: [number, number];
3737
shareDownloadPolling: boolean;
38+
loginLoading: boolean;
39+
oauth2Clients: Array<{ name: string; value: string }>;
3840
availableSourceFunctions?: string[];
3941
}
4042
export interface ShareVizInfo {

frontend/src/locales/en/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"login": "Log in",
7979
"register": "Sign up for an account",
8080
"forgotPassword": "Can't log in?",
81+
"authTitle": "OR",
8182
"alreadyLoggedIn": "Your account is already logged in",
8283
"enter": "Click to enter",
8384
"switch": "Switch accounts"

frontend/src/locales/zh/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"login": "登录",
7979
"register": "注册新账号",
8080
"forgotPassword": "忘记密码?",
81+
"authTitle": "第三方登录",
8182
"alreadyLoggedIn": "账号已登录",
8283
"enter": "点击进入",
8384
"switch": "切换账号"

0 commit comments

Comments
 (0)