Skip to content

Commit

Permalink
Merge 3915336 into 6c69f41
Browse files Browse the repository at this point in the history
  • Loading branch information
emasys committed Jul 18, 2018
2 parents 6c69f41 + 3915336 commit 5ffc433
Show file tree
Hide file tree
Showing 14 changed files with 732 additions and 9 deletions.
3 changes: 2 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import NotFound from './components/NotFound';
import DictionaryOverview from './components/dashboard/components/dictionary/DictionaryContainer';
import OwnerDictionary from './components/dashboard/container/OwnerDictionary';
import GeneralSearchContainer from './components/GeneralSearch/GeneralSearchContainer';
import UserDashboard from './components/userDasboard/container/UserDashboard';

const App = () => (
<Provider store={store}>
Expand All @@ -25,7 +26,7 @@ const App = () => (
<Navbar />
<Switch>
<Route exact path="/" component={Authenticate(Login)} />
<Route exact path="/dashboard" component={Authenticate(OwnerDictionary)} />
<Route exact path="/dashboard" component={Authenticate(UserDashboard)} />
<Route exact path="/dashboard/sources" component={Authenticate(SourceSearch)} />
<Route exact path="/dashboard/concepts" component={Authenticate(ConceptSearch)} />
<Route exact path="/dashboard/dictionaries" component={Authenticate(DictionaryDisplay)} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,10 @@ const DictionaryCard = (dictionary) => {
</div>
<div className="source-card-footer">
<Link
className="viewdetailslink"
className="view-details-link"
to={`/dictionaryOverview${url}`}
>
<button
type="button"
className="btn btn-outline-secondary"
id="viewDetails"
>
View Details
</button>
<span id="viewDetails">View Details</span>
</Link>
</div>
</div>
Expand Down
36 changes: 36 additions & 0 deletions src/components/userDasboard/components/CardWrapper.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import PropTypes from 'prop-types';
import DictionaryCard from '../../dashboard/components/dictionary/DictionaryCard';
import Loader from '../../Loader';

const CardWrapper = ({ dictionaries, fetching }) => {
if (dictionaries.length >= 1) {
return (
<div className="row justify-content-center">
{dictionaries.map(dictionary => (
<DictionaryCard dictionary={dictionary} key={dictionary.uuid} />
))}
</div>
);
}
if (fetching) {
return (
<div className="text-center mt-3">
<Loader />
</div>
);
}
return (
<div className="text-center mt-3 p-10">
<h6 className="p-20">No dictionary found</h6>
</div>
);
};

CardWrapper.propTypes = {
fetching: PropTypes.bool.isRequired,
dictionaries: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
})).isRequired,
};
export default CardWrapper;
74 changes: 74 additions & 0 deletions src/components/userDasboard/components/DashboardDetails.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';

const DashboardDetails = ({ numberOfOrgs, numberOfDictionary, organizations }) => {
const nameOfOrganizations = organizations.map(organization => organization.name).join(',');
const dictionary = numberOfDictionary < 2 ? 'dictionary' : 'dictionaries';
if (numberOfOrgs === 1) {
return (
<div className="user-data">
<p className="lead">
You belong to {nameOfOrganizations} organization. This can be changed via{' '}
<a href="https://qa.openconceptlab.org/" target="_blank" rel="noopener noreferrer">
the traditional OCL
</a>.
</p>
<p className="lead">
You currently have {numberOfDictionary} {dictionary}. You can{' '}
<Link to="dashboard/dictionaries">view all OpenMRS public dictionaries</Link>.
</p>
</div>
);
} else if (numberOfOrgs > 1) {
return (
<div className="user-data">
<p className="lead">
You belong to {numberOfOrgs} organizations:{' '}
{organizations.map(organization => (
<span className="d-block lead org-name text-capitalize" key={organization.id}>
<a
href={`https://qa.openconceptlab.org${organization.url}`}
target="_blank"
rel="noopener noreferrer"
>
<i className="fas fa-arrow-circle-right fa-fw" />{' '}
{organization.name}
</a>
</span>
))}{' '}
This can be changed via{' '}
<a href="https://qa.openconceptlab.org/" target="_blank" rel="noopener noreferrer">
the traditional OCL
</a>.
</p>
<p className="lead">
You currently have {numberOfDictionary} {dictionary}. You can{' '}
<Link to="dashboard/dictionaries">view all OpenMRS public dictionaries</Link>.
</p>
</div>
);
}
return (
<div className="user-data">
<p className="lead">
You do not belong to any organization. This can be changed via{' '}
<a href="https://qa.openconceptlab.org/" target="_blank" rel="noopener noreferrer">
the traditional OCL
</a>.
</p>
<p className="lead">
You currently have {numberOfDictionary} {dictionary}. You can{' '}
<Link to="dashboard/dictionaries">view all OpenMRS public dictionaries</Link>.
</p>
</div>
);
};

DashboardDetails.propTypes = {
numberOfOrgs: PropTypes.number.isRequired,
numberOfDictionary: PropTypes.number.isRequired,
organizations: PropTypes.array.isRequired,
};

export default DashboardDetails;
96 changes: 96 additions & 0 deletions src/components/userDasboard/container/UserDashboard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import '../styles/user-dasboard-styles.css';
import { fetchUserData } from '../../../redux/actions/user';
import { getUsername } from '../../dictionaryConcepts/components/helperFunction';
import DashboardDetails from '../components/DashboardDetails';
import CardWrapper from '../components/CardWrapper';
import AddDictionary from '../../dashboard/components/dictionary/AddDictionary';

export class UserDashboard extends Component {
static propTypes = {
fetchUserData: PropTypes.func.isRequired,
loading: PropTypes.bool.isRequired,
userDictionary: PropTypes.array.isRequired,
userOrganization: PropTypes.array.isRequired,
user: PropTypes.shape({
name: PropTypes.string,
orgs: PropTypes.number,
public_collections: PropTypes.number,
}).isRequired,
};

state = {
show: false,
};

componentDidMount() {
const username = getUsername();
this.props.fetchUserData(username);
}

handleHide = () => this.setState({ show: false });
handleShow = () => this.setState({ show: true });

render() {
const {
user: { name, orgs, public_collections },
userOrganization,
userDictionary,
loading,
} = this.props;
const dictionary = public_collections < 2 ? 'dictionary' : 'dictionaries';
return (
<div className="container-fluid mt-5">
<AddDictionary show={this.state.show} handleHide={this.handleHide} />
<div className="row justify-content-center">
<div className="col-11 user-info">
<div className="row">
<div className="greetings">
<h5>Welcome {name}</h5>
</div>
</div>
<div className="row">
<DashboardDetails
numberOfOrgs={orgs}
numberOfDictionary={public_collections}
organizations={userOrganization}
/>
</div>
</div>
<div className="col-11 user-dictionary-wrapper">
<div className="row">
<div className="greetings col-12 d-flex justify-content-between">
<h3>Your {dictionary}</h3>
<h6 className="see-more-link">
<button className="btn btn-success btn-sm" id="add-dictionary" onClick={this.handleShow}>
<i className="fas fa-plus fa-fw" /> New Dictionary
</button>
</h6>
</div>
<div className="line-divider" />
</div>
<div className="row justify-content-center">
<div className="col-11">
<CardWrapper dictionaries={userDictionary} fetching={loading} />
</div>
</div>
</div>
</div>
</div>
);
}
}

export const mapStateToProps = state => ({
user: state.user.user,
userDictionary: state.user.userDictionary,
userOrganization: state.user.userOrganization,
loading: state.user.loading,
});

export default connect(
mapStateToProps,
{ fetchUserData },
)(UserDashboard);
72 changes: 72 additions & 0 deletions src/components/userDasboard/styles/user-dasboard-styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
.user-info {
box-shadow: 0px 2px 20px 15px #b1b1b114;
padding: 2rem;
}

.user-info .user-data {
text-align: left;
font-size: 1rem;
}

.user-data .lead {
font-size: 1rem;
}

.user-dictionary-wrapper {
margin-top: 2rem;
box-shadow: 0px 2px 20px 15px #b1b1b114;
padding: .5rem;
}

.user-data a {
font-size: 1rem;
color: rgb(17, 88, 180);
font-weight: 400;
}

.see-more-link {
margin-top: .35rem;
}

.org-name {
line-height: 1rem;
padding: 0;
margin: .5rem;
}

.greetings h3 {
margin-bottom: .2rem;
}

.line-divider {
display: inline-block;
height: .3rem;
width: 5rem;
background: #343a40;
margin-left: 1.7rem;
border-radius: 100rem;
-webkit-border-radius: 100rem;
-moz-border-radius: 100rem;
-ms-border-radius: 100rem;
-o-border-radius: 100rem;
}

.view-details-link {
color: #343a40;
padding: .1rem .3rem;
border-radius: .2rem;
transition: all 400ms ease-in-out;
-webkit-transition: all 400ms ease-in-out;
-moz-transition: all 400ms ease-in-out;
-ms-transition: all 400ms ease-in-out;
-o-transition: all 400ms ease-in-out;
-webkit-border-radius: .2rem;
-moz-border-radius: .2rem;
-ms-border-radius: .2rem;
-o-border-radius: .2rem;
}

.view-details-link:hover {
color: #000000;
background: #8080801f;
}
3 changes: 3 additions & 0 deletions src/redux/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ export const TOTAL_CONCEPT_COUNT = '[concepts] total_concept_count';

export const ADD_EXISTING_CONCEPTS = '[concepts] add_existing_concepts';
export const SEARCH_RESULTS = '[searchResults] search';
export const GET_USER = '[user] get_user';
export const FETCH_USER_DICTIONARY = '[dictionary] fetch_user_dictionary';
export const FETCH_USER_ORGANIZATION = '[user] fetch_user_organization';
41 changes: 41 additions & 0 deletions src/redux/actions/user/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { notify } from 'react-notify-toast';
import { isSuccess, isFetching } from '../globalActionCreators';
import { GET_USER, FETCH_USER_DICTIONARY, FETCH_USER_ORGANIZATION } from '../types';
import instance from '../../../config/axiosConfig';

export const fetchUser = username => async (dispatch) => {
const url = `users/${username}`;
try {
const response = await instance.get(url);
dispatch(isSuccess(response.data, GET_USER));
} catch (error) {
notify.show('an error occurred, reload the page', 'error', 3000);
}
};
export const fetchUserOrganizations = username => async (dispatch) => {
const url = `users/${username}/orgs`;
try {
const response = await instance.get(url);
dispatch(isSuccess(response.data, FETCH_USER_ORGANIZATION));
} catch (error) {
notify.show('an error occurred, reload the page', 'error', 3000);
}
};

export const fetchUserDictionary = username => async (dispatch) => {
const url = `users/${username}/collections/?verbose=true&limit=0`;
try {
const response = await instance.get(url);
dispatch(isSuccess(response.data, FETCH_USER_DICTIONARY));
dispatch(isFetching(false));
} catch (error) {
notify.show('an error occurred, reload the page', 'error', 3000);
}
};

export const fetchUserData = username => (dispatch) => {
dispatch(isFetching(true));
dispatch(fetchUser(username));
dispatch(fetchUserOrganizations(username));
dispatch(fetchUserDictionary(username));
};
2 changes: 2 additions & 0 deletions src/redux/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import organizations from './dictionaryReducer';
import concepts from './ConceptReducers';
import dictionaries from './dictionaryReducers';
import generalSearch from './generalSearchReducer';
import user from './user';

// combined reducer to give a global state
const rootReducer = combineReducers({
Expand All @@ -14,6 +15,7 @@ const rootReducer = combineReducers({
concepts,
dictionaries,
generalSearch,
user,
});

export default rootReducer;

0 comments on commit 5ffc433

Please sign in to comment.