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

Addition of Overview page in the dashboard #105

Merged
merged 3 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions config/router.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ module.exports = [
name: 'profile',
component: './Profile',
},
{
path: '/result',
name: 'result',
component: './Result',
},
{
path: '/expiring-results',
name: 'expiring-results',
component: './ExpiringResults',
},
{
path: '/exception/403',
name: 'exception-403',
Expand Down
21 changes: 15 additions & 6 deletions mock/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@ export const mockControllers = new Array(DEFAULT_SIZE).fill().map((value, index)
}));

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

export const mockSamples = {
Expand Down Expand Up @@ -330,7 +338,8 @@ export default {
'POST /api/v1/controllers/list': mockControllers,
'POST /api/v1/datasets/list': (req, res) => {
const data = {};
data[req.body.controller] = mockResults(req.body.controller);
const controller = req.body.controller || 'mock-controller';
data[controller] = mockResults(controller);
res.send(data);
},
'POST /api/v1/datasets/detail': (req, res) => {
Expand Down
15 changes: 15 additions & 0 deletions src/common/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,21 @@ export const menuData = [
},
],
},
{
name: 'Overview',
icon: 'overview',
path: '/overview',
routes: [
{
name: 'Expiring Results',
path: '/expiring-results',
},
{
name: 'result',
path: '/result',
},
],
},
{
name: 'Search',
path: '/search',
Expand Down
2 changes: 1 addition & 1 deletion src/components/AuthLayout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ class AuthLayout extends Component {
<Button
variant="link"
className={styles.continueBtn}
onClick={() => this.navigate('controllers')}
onClick={() => this.navigate('')}
>
here
</Button>
Expand Down
123 changes: 123 additions & 0 deletions src/components/LoginForm/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React, { useState, useEffect } from 'react';
import {
Form,
FormGroup,
TextInput,
Checkbox,
ActionGroup,
Button,
Title,
} from '@patternfly/react-core';
import { connect } from 'dva';
import styles from './index.less';

const mapStateToProps = state => {
const { auth } = state;
return { auth };
};

const LoginForm = props => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [errors, setErrors] = useState({
email: '',
});
const [btnDisabled, setBtnDisabled] = useState(true);

const handleUsernameChange = val => {
setUsername(val);
setErrors({
...errors,
});
};

const handleLoginSubmit = () => {
const { dispatch } = props;
dispatch({
type: 'auth/loginUser',
payload: {
username,
password,
},
});
};

/* eslint-disable no-restricted-syntax */
anishaswain marked this conversation as resolved.
Show resolved Hide resolved
const validateForm = () => {
if (username.trim() === '' || password.trim() === '') {
return false;
}
for (const dep of Object.entries(errors)) {
if (dep[1].length > 0) {
return false;
}
}
// if we reach here, it means
// we have covered all of the edge cases.
return true;
};

useEffect(
() => {
if (validateForm()) {
setBtnDisabled(false);
} else setBtnDisabled(true);
},
[username, password]
);

const form = (
<div className={styles.section}>
<Form className={styles.section}>
<FormGroup label="Username" isRequired fieldId="horizontal-form-name">
<TextInput
isRequired
type="text"
id="horizontal-form-name"
aria-describedby="horizontal-form-name-helper"
name="horizontal-form-name"
onChange={handleUsernameChange}
/>
<p className={styles.error}>{errors.email}</p>
</FormGroup>
<FormGroup label="Password" isRequired fieldId="horizontal-form-password">
<TextInput
isRequired
type="password"
id="horizontal-form-password"
name="horizontal-form-password"
onChange={val => setPassword(val)}
/>
</FormGroup>
<FormGroup fieldId="remember-me">
<Checkbox
label="Keep me logged in"
id="alt-form-checkbox-1"
name="alt-form-checkbox-1"
className={styles.check}
/>
</FormGroup>
<ActionGroup>
<Button
isBlock
onClick={handleLoginSubmit}
className={styles.btn}
id="submitBtn"
isDisabled={btnDisabled}
>
<Title
headingLevel="h4"
size="xl"
style={btnDisabled ? { color: 'black' } : { color: 'white' }}
>
Submit
</Title>
</Button>
</ActionGroup>
</Form>
</div>
);
return <React.Fragment>{form}</React.Fragment>;
};

export default connect(mapStateToProps)(LoginForm);
aquibbaig marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
.section {
padding: 5% 10% 5% 10% !important;
padding: 5% 10% 5% 10%;
}

.btn {
padding: 10px;
color: white;
}

.inlineLink {
font-size: var(--pf-global--FontSize--xl);
}

.pf-c-form__group .pf-c-form__label {
font-size: 50px !important;
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/LoginHint/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import styles from './index.less';
store,
auth: auth.auth,
}))
class Overview extends Component {
class LoginHint extends Component {
navigateToAuth = () => {
const { dispatch } = this.props;
dispatch(routerRedux.push(`/auth`));
Expand Down Expand Up @@ -49,4 +49,4 @@ class Overview extends Component {
}
}

export default Overview;
export default LoginHint;
94 changes: 94 additions & 0 deletions src/components/LoginModal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import {
Modal,
ModalVariant,
Button,
TextContent,
Text,
TextVariants,
} from '@patternfly/react-core';
import { routerRedux } from 'dva/router';
import { connect } from 'dva';
import LoginForm from '@/components/LoginForm';

@connect(auth => ({
auth: auth.auth,
}))
class LoginModal extends React.Component {
constructor(props) {
super(props);
this.state = {
isModalOpen: false,
modalView: false,
};
}

componentDidMount() {
this.handleModalToggle();
}

handleModalToggle = () => {
this.setState(({ isModalOpen }) => ({
isModalOpen: !isModalOpen,
}));
};

handleModalCancel = () => {
const { dispatch } = this.props;
this.setState(({ isModalOpen }) => ({
isModalOpen: !isModalOpen,
}));
dispatch(routerRedux.push(`/`));
};

handleLoginModal = () => {
this.setState({
modalView: true,
});
};

handleSignupModal = () => {
const { dispatch } = this.props;
this.setState(({ isModalOpen }) => ({
isModalOpen: !isModalOpen,
}));
dispatch(routerRedux.push(`/signup`));
};

render() {
const { isModalOpen, modalView } = this.state;
const loginAction = (
<div>
<TextContent>
<Text component={TextVariants.h4}>
This action requires login. Please login to Pbench Dashboard to continue.
</Text>
</TextContent>
<Button key="confirm" variant="primary" onClick={this.handleLoginModal}>
Login
</Button>
<Button key="confirm" variant="link" onClick={this.handleSignupModal}>
Signup
</Button>
<Button key="cancel" variant="link" onClick={this.handleModalCancel}>
Cancel
</Button>
</div>
);
const modalContent = !modalView ? loginAction : <LoginForm />;
return (
<React.Fragment>
<Modal
variant={ModalVariant.small}
isOpen={isModalOpen}
onClose={this.handleModalCancel}
showClose="false"
>
{modalContent}
anishaswain marked this conversation as resolved.
Show resolved Hide resolved
</Modal>
</React.Fragment>
);
}
}

export default LoginModal;
Loading