Skip to content
This repository was archived by the owner on Aug 31, 2022. It is now read-only.

Commit 8c1ac57

Browse files
author
anishaswain
committed
Adds Overview Page
1 parent 93542f1 commit 8c1ac57

File tree

22 files changed

+1910
-181
lines changed

22 files changed

+1910
-181
lines changed

config/router.config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ module.exports = [
7474
name: 'profile',
7575
component: './Profile',
7676
},
77+
{
78+
path: '/result',
79+
name: 'result',
80+
component: './Result',
81+
},
82+
{
83+
path: '/expiring-results',
84+
name: 'expiring-results',
85+
component: './ExpiringResults',
86+
},
7787
{
7888
path: '/exception/403',
7989
name: 'exception-403',

mock/api.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,23 @@ export const mockControllers = new Array(DEFAULT_SIZE).fill().map((value, index)
1515
}));
1616

1717
export const mockResults = hostname =>
18-
new Array(DEFAULT_SIZE).fill().map((value, index) => ({
18+
new Array(DEFAULT_SIZE).fill().map(() => ({
1919
'@metadata.controller_dir': hostname,
2020
config: casual.word,
2121
controller: hostname,
2222
end: moment.utc(),
23-
// Since dataset id is a long hex string, removed "-" characters here to make it look like real data
24-
id: casual.uuid.replace(/-/g, ''),
25-
result: `${index}${hostname.slice(0, -6)}${index}`,
26-
start: moment.utc(),
23+
id: createUniqueKey(),
24+
result: `${casual.word}.${casual.word}.${casual.word}`,
25+
start: moment.utc().subtract(Math.random() * 10 + 10, 'days'),
26+
serverMetadata: {
27+
dashboard: {
28+
saved: false,
29+
seen: false,
30+
},
31+
'dataset.access': 'public',
32+
'dataset.owner': '[email protected]',
33+
'server.deletion': moment.utc().add('days', Math.random() * 10 + 10),
34+
},
2735
}));
2836

2937
export const mockSamples = {
@@ -330,7 +338,8 @@ export default {
330338
'POST /api/v1/controllers/list': mockControllers,
331339
'POST /api/v1/datasets/list': (req, res) => {
332340
const data = {};
333-
data[req.body.controller] = mockResults(req.body.controller);
341+
const controller = req.body.controller || 'mock-controller';
342+
data[controller] = mockResults(controller);
334343
res.send(data);
335344
},
336345
'POST /api/v1/datasets/detail': (req, res) => {

src/common/menu.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ export const menuData = [
2727
},
2828
],
2929
},
30+
{
31+
name: 'Overview',
32+
icon: 'overview',
33+
path: '/overview',
34+
routes: [
35+
{
36+
name: 'Expiring Results',
37+
path: '/expiring-results',
38+
},
39+
{
40+
name: 'result',
41+
path: '/result',
42+
},
43+
],
44+
},
3045
{
3146
name: 'Search',
3247
path: '/search',

src/components/AuthLayout/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ class AuthLayout extends Component {
240240
<Button
241241
variant="link"
242242
className={styles.continueBtn}
243-
onClick={() => this.navigate('controllers')}
243+
onClick={() => this.navigate('')}
244244
>
245245
here
246246
</Button>

src/components/LoginForm/index.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import React, { useState, useEffect } from 'react';
2+
import {
3+
Form,
4+
FormGroup,
5+
TextInput,
6+
Checkbox,
7+
ActionGroup,
8+
Button,
9+
Title,
10+
} from '@patternfly/react-core';
11+
import { connect } from 'dva';
12+
import styles from './index.less';
13+
import { validateEmail } from '@/utils/validator';
14+
15+
const mapStateToProps = state => {
16+
const { auth } = state;
17+
return { auth };
18+
};
19+
20+
const LoginForm = props => {
21+
const [username, setUsername] = useState('');
22+
const [password, setPassword] = useState('');
23+
const [errors, setErrors] = useState({
24+
email: '',
25+
});
26+
const [btnDisabled, setBtnDisabled] = useState(true);
27+
28+
const handleUsernameChange = val => {
29+
setUsername(val);
30+
const validEmail = validateEmail(val);
31+
setErrors({
32+
...errors,
33+
...validEmail,
34+
});
35+
};
36+
37+
const handleLoginSubmit = () => {
38+
const { dispatch } = props;
39+
dispatch({
40+
type: 'auth/loginUser',
41+
payload: {
42+
username,
43+
password,
44+
},
45+
});
46+
};
47+
48+
/* eslint-disable no-restricted-syntax */
49+
const validateForm = () => {
50+
if (username.trim() === '' || password.trim() === '') {
51+
return false;
52+
}
53+
for (const dep of Object.entries(errors)) {
54+
if (dep[1].length > 0) {
55+
return false;
56+
}
57+
}
58+
// if we reach here, it means
59+
// we have covered all of the edge cases.
60+
return true;
61+
};
62+
63+
useEffect(
64+
() => {
65+
if (validateForm()) {
66+
setBtnDisabled(false);
67+
} else setBtnDisabled(true);
68+
},
69+
[username, password]
70+
);
71+
72+
const form = (
73+
<div className={styles.section}>
74+
<Form className={styles.section}>
75+
<FormGroup label="Email address" isRequired fieldId="horizontal-form-name">
76+
<TextInput
77+
isRequired
78+
type="text"
79+
id="horizontal-form-name"
80+
aria-describedby="horizontal-form-name-helper"
81+
name="horizontal-form-name"
82+
onChange={handleUsernameChange}
83+
/>
84+
<p className={styles.error}>{errors.email}</p>
85+
</FormGroup>
86+
<FormGroup label="Password" isRequired fieldId="horizontal-form-password">
87+
<TextInput
88+
isRequired
89+
type="password"
90+
id="horizontal-form-password"
91+
name="horizontal-form-password"
92+
onChange={val => setPassword(val)}
93+
/>
94+
</FormGroup>
95+
<FormGroup fieldId="remember-me">
96+
<Checkbox
97+
label="Keep me logged in"
98+
id="alt-form-checkbox-1"
99+
name="alt-form-checkbox-1"
100+
className={styles.check}
101+
/>
102+
</FormGroup>
103+
<ActionGroup>
104+
<Button
105+
isBlock
106+
onClick={handleLoginSubmit}
107+
className={styles.btn}
108+
id="submitBtn"
109+
isDisabled={btnDisabled}
110+
>
111+
<Title
112+
headingLevel="h4"
113+
size="xl"
114+
style={btnDisabled ? { color: 'black' } : { color: 'white' }}
115+
>
116+
Submit
117+
</Title>
118+
</Button>
119+
</ActionGroup>
120+
</Form>
121+
</div>
122+
);
123+
return <React.Fragment>{form}</React.Fragment>;
124+
};
125+
126+
export default connect(mapStateToProps)(LoginForm);

src/pages/LoginHandler/index.less renamed to src/components/LoginForm/index.less

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
.section {
2-
padding: 5% 10% 5% 10% !important;
2+
padding: 5% 10% 5% 10%;
33
}
44

55
.btn {
66
padding: 10px;
77
color: white;
88
}
99

10-
.inlineLink {
11-
font-size: var(--pf-global--FontSize--xl);
12-
}
13-
1410
.pf-c-form__group .pf-c-form__label {
1511
font-size: 50px !important;
1612
}

src/components/LoginHint/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import styles from './index.less';
99
store,
1010
auth: auth.auth,
1111
}))
12-
class Overview extends Component {
12+
class LoginHint extends Component {
1313
navigateToAuth = () => {
1414
const { dispatch } = this.props;
1515
dispatch(routerRedux.push(`/auth`));
@@ -49,4 +49,4 @@ class Overview extends Component {
4949
}
5050
}
5151

52-
export default Overview;
52+
export default LoginHint;

src/components/LoginModal/index.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import React from 'react';
2+
import {
3+
Modal,
4+
ModalVariant,
5+
Button,
6+
TextContent,
7+
Text,
8+
TextVariants,
9+
} from '@patternfly/react-core';
10+
import { routerRedux } from 'dva/router';
11+
import { connect } from 'dva';
12+
import LoginForm from '@/components/LoginForm';
13+
14+
@connect(auth => ({
15+
auth: auth.auth,
16+
}))
17+
class LoginModal extends React.Component {
18+
constructor(props) {
19+
super(props);
20+
this.state = {
21+
isModalOpen: false,
22+
modalView: false,
23+
};
24+
}
25+
26+
componentDidMount() {
27+
this.handleModalToggle();
28+
}
29+
30+
handleModalToggle = () => {
31+
this.setState(({ isModalOpen }) => ({
32+
isModalOpen: !isModalOpen,
33+
}));
34+
};
35+
36+
handleModalCancel = () => {
37+
const { dispatch } = this.props;
38+
this.setState(({ isModalOpen }) => ({
39+
isModalOpen: !isModalOpen,
40+
}));
41+
dispatch(routerRedux.push(`/`));
42+
};
43+
44+
handleLoginModal = () => {
45+
this.setState({
46+
modalView: true,
47+
});
48+
};
49+
50+
handleSignupModal = () => {
51+
const { dispatch } = this.props;
52+
this.setState(({ isModalOpen }) => ({
53+
isModalOpen: !isModalOpen,
54+
}));
55+
dispatch(routerRedux.push(`/signup`));
56+
};
57+
58+
render() {
59+
const { isModalOpen, modalView } = this.state;
60+
const loginAction = (
61+
<div>
62+
<TextContent>
63+
<Text component={TextVariants.h4}>
64+
This action requires login. Please login to Pbench Dashboard to continue.
65+
</Text>
66+
</TextContent>
67+
<Button key="confirm" variant="primary" onClick={this.handleLoginModal}>
68+
Login
69+
</Button>
70+
<Button key="confirm" variant="link" onClick={this.handleSignupModal}>
71+
Signup
72+
</Button>
73+
<Button key="cancel" variant="link" onClick={this.handleModalCancel}>
74+
Cancel
75+
</Button>
76+
</div>
77+
);
78+
const modalContent = !modalView ? loginAction : <LoginForm />;
79+
return (
80+
<React.Fragment>
81+
<Modal
82+
variant={ModalVariant.small}
83+
isOpen={isModalOpen}
84+
onClose={this.handleModalCancel}
85+
showClose="false"
86+
>
87+
{modalContent}
88+
</Modal>
89+
</React.Fragment>
90+
);
91+
}
92+
}
93+
94+
export default LoginModal;

0 commit comments

Comments
 (0)