mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-07 20:40:26 +08:00
adds user account dropdown
This commit is contained in:
parent
226458a3f0
commit
bd352869a3
13 changed files with 216 additions and 13 deletions
14
app/controllers/client_api/users_controller.rb
Normal file
14
app/controllers/client_api/users_controller.rb
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
module ClientApi
|
||||||
|
class UsersController < ApplicationController
|
||||||
|
|
||||||
|
def current_user_info
|
||||||
|
respond_to do |format|
|
||||||
|
format.json do
|
||||||
|
render template: '/client_api/users/show',
|
||||||
|
status: :ok,
|
||||||
|
locals: { user: current_user }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,9 +4,11 @@ import {
|
||||||
getListOfTeams
|
getListOfTeams
|
||||||
} from "../shared/reducers/TeamReducers";
|
} from "../shared/reducers/TeamReducers";
|
||||||
import { globalActivities } from "../shared/reducers/ActivitiesReducers";
|
import { globalActivities } from "../shared/reducers/ActivitiesReducers";
|
||||||
|
import { currentUser } from "../shared/reducers/UsersReducer";
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
current_team: setCurrentTeam,
|
current_team: setCurrentTeam,
|
||||||
all_teams: getListOfTeams,
|
all_teams: getListOfTeams,
|
||||||
global_activities: globalActivities
|
global_activities: globalActivities,
|
||||||
|
current_user: currentUser
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,3 +10,14 @@ export const SEARCH_PATH = "/search";
|
||||||
|
|
||||||
// notifications
|
// notifications
|
||||||
export const RECENT_NOTIFICATIONS_PATH = "/client_api/recent_notifications";
|
export const RECENT_NOTIFICATIONS_PATH = "/client_api/recent_notifications";
|
||||||
|
|
||||||
|
// users
|
||||||
|
export const CURRENT_USER_PATH = "/client_api/current_user_info";
|
||||||
|
|
||||||
|
// info dropdown_title
|
||||||
|
export const CUSTOMER_SUPPORT_LINK = "http://scinote.net/support";
|
||||||
|
export const TUTORIALS_LINK = "http://scinote.net/product/tutorials/";
|
||||||
|
export const RELEASE_NOTES_LINK = "http://scinote.net/docs/release-notes/";
|
||||||
|
export const PREMIUM_LINK = "http://scinote.net/premium/";
|
||||||
|
export const CONTACT_US_LINK =
|
||||||
|
"http://scinote.net/story-of-scinote/#contact-scinote";
|
||||||
|
|
|
@ -18,6 +18,18 @@ export default {
|
||||||
dropdown_title: "Notifications",
|
dropdown_title: "Notifications",
|
||||||
dropdown_settings_link: "Settings",
|
dropdown_settings_link: "Settings",
|
||||||
dropdown_show_all: "Show all notifications"
|
dropdown_show_all: "Show all notifications"
|
||||||
|
},
|
||||||
|
info_dropdown: {
|
||||||
|
customer_support: "Customer support",
|
||||||
|
tutorials: "Tutorials",
|
||||||
|
release_notes: "Release notes",
|
||||||
|
premium: "Premium",
|
||||||
|
contact_us: "Contact us"
|
||||||
|
},
|
||||||
|
user_account_dropdown: {
|
||||||
|
greeting: "Hi, {name}",
|
||||||
|
settings: "Settings",
|
||||||
|
log_out: "Log out"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
23
app/javascript/packs/shared/actions/UsersActions.js
Normal file
23
app/javascript/packs/shared/actions/UsersActions.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import axios from "axios";
|
||||||
|
import { CURRENT_USER_PATH } from "../../app/routes";
|
||||||
|
import { SET_CURRENT_USER } from "./types";
|
||||||
|
|
||||||
|
function addCurrentUser(data) {
|
||||||
|
return {
|
||||||
|
type: SET_CURRENT_USER,
|
||||||
|
payload: data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentUser() {
|
||||||
|
return dispatch => {
|
||||||
|
axios
|
||||||
|
.get(CURRENT_USER_PATH, { withCredentials: true })
|
||||||
|
.then(({ data }) => {
|
||||||
|
dispatch(addCurrentUser(data.user));
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log("get Current User Error: ", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
|
@ -4,3 +4,6 @@ export const GET_LIST_OF_TEAMS = "GET_LIST_OF_TEAMS";
|
||||||
|
|
||||||
// activities
|
// activities
|
||||||
export const GLOBAL_ACTIVITIES_DATA = "GLOBAL_ACTIVITIES_DATA";
|
export const GLOBAL_ACTIVITIES_DATA = "GLOBAL_ACTIVITIES_DATA";
|
||||||
|
|
||||||
|
// users
|
||||||
|
export const SET_CURRENT_USER = "SET_CURRENT_USER";
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
export const MAIN_COLOR_BLUE = '#37a0d9';
|
export const MAIN_COLOR_BLUE = '#37a0d9';
|
||||||
|
export const WHITE_COLOR = '#fff';
|
||||||
|
export const BORDER_GRAY_COLOR = '#d2d2d2';
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
import { NavDropdown, MenuItem } from "react-bootstrap";
|
||||||
|
import {
|
||||||
|
CUSTOMER_SUPPORT_LINK,
|
||||||
|
TUTORIALS_LINK,
|
||||||
|
RELEASE_NOTES_LINK,
|
||||||
|
PREMIUM_LINK,
|
||||||
|
CONTACT_US_LINK
|
||||||
|
} from "../../../app/routes";
|
||||||
|
|
||||||
|
const InfoDropdown = () =>
|
||||||
|
<NavDropdown
|
||||||
|
noCaret
|
||||||
|
title={<span className="glyphicon glyphicon-info-sign" />}
|
||||||
|
id="nav-info-dropdown"
|
||||||
|
>
|
||||||
|
<MenuItem href={CUSTOMER_SUPPORT_LINK} target="_blank">
|
||||||
|
<FormattedMessage id="info_dropdown.customer_support" />
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem href={TUTORIALS_LINK} target="_blank">
|
||||||
|
<FormattedMessage id="info_dropdown.tutorials" />
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem href={RELEASE_NOTES_LINK} target="_blank">
|
||||||
|
<FormattedMessage id="info_dropdown.release_notes" />
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem href={PREMIUM_LINK} target="_blank">
|
||||||
|
<FormattedMessage id="info_dropdown.premium" />
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem href={CONTACT_US_LINK} target="_blank">
|
||||||
|
<FormattedMessage id="info_dropdown.contact_us" />
|
||||||
|
</MenuItem>
|
||||||
|
</NavDropdown>;
|
||||||
|
|
||||||
|
export default InfoDropdown;
|
|
@ -0,0 +1,75 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { NavDropdown, MenuItem } from "react-bootstrap";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
|
import { getCurrentUser } from "../../actions/UsersActions";
|
||||||
|
|
||||||
|
const StyledNavDropdown = styled(NavDropdown)`
|
||||||
|
& #user-account-dropdown {
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
class UserAccountDropdown extends Component {
|
||||||
|
componentDidMount() {
|
||||||
|
this.props.getCurrentUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<StyledNavDropdown
|
||||||
|
id="user-account-dropdown"
|
||||||
|
className="dropdown"
|
||||||
|
noCaret
|
||||||
|
title={
|
||||||
|
<span>
|
||||||
|
<FormattedMessage
|
||||||
|
id="user_account_dropdown.greeting"
|
||||||
|
values={{ name: this.props.current_user.fullName }}
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src={this.props.current_user.avatarPath}
|
||||||
|
alt={this.props.current_user.fullName}
|
||||||
|
className="img-circle"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MenuItem href="/settings">
|
||||||
|
<FormattedMessage id="user_account_dropdown.settings" />
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem divider />
|
||||||
|
<MenuItem href="/users/sign_out">
|
||||||
|
<FormattedMessage id="user_account_dropdown.log_out" />
|
||||||
|
</MenuItem>
|
||||||
|
</StyledNavDropdown>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UserAccountDropdown.propTypes = {
|
||||||
|
getCurrentUser: PropTypes.func.isRequired,
|
||||||
|
current_user: PropTypes.shape({
|
||||||
|
id: PropTypes.number.isRequired,
|
||||||
|
fullName: PropTypes.string.isRequired,
|
||||||
|
avatarPath: PropTypes.string.isRequired
|
||||||
|
}).isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
// Map the states from store to component
|
||||||
|
const mapStateToProps = ({ current_user }) => ({ current_user });
|
||||||
|
|
||||||
|
// Map the fetch activity action to component
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
getCurrentUser() {
|
||||||
|
dispatch(getCurrentUser());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(
|
||||||
|
UserAccountDropdown
|
||||||
|
);
|
|
@ -3,13 +3,24 @@ import PropTypes from "prop-types";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { Navbar, Nav, NavItem } from "react-bootstrap";
|
import { Navbar, Nav, NavItem } from "react-bootstrap";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { MAIN_COLOR_BLUE } from "../constants/colors";
|
import {
|
||||||
|
MAIN_COLOR_BLUE,
|
||||||
|
WHITE_COLOR,
|
||||||
|
BORDER_GRAY_COLOR
|
||||||
|
} from "../constants/colors";
|
||||||
import { getActivities } from "../actions/ActivitiesActions";
|
import { getActivities } from "../actions/ActivitiesActions";
|
||||||
import { getTeamsList } from "../actions/TeamsActions";
|
import { getTeamsList } from "../actions/TeamsActions";
|
||||||
import TeamSwitch from "./components/TeamSwitch";
|
import TeamSwitch from "./components/TeamSwitch";
|
||||||
import GlobalActivitiesModal from "./components/GlobalActivitiesModal";
|
import GlobalActivitiesModal from "./components/GlobalActivitiesModal";
|
||||||
import SearchDropdown from "./components/SearchDropdown";
|
import SearchDropdown from "./components/SearchDropdown";
|
||||||
import NotificationsDropdown from "./components/NotificationsDropdown"
|
import NotificationsDropdown from "./components/NotificationsDropdown";
|
||||||
|
import InfoDropdown from "./components/InfoDropdown";
|
||||||
|
import UserAccountDropdown from "./components/UserAccountDropdown";
|
||||||
|
|
||||||
|
const StyledNavbar = styled(Navbar)`
|
||||||
|
background-color: ${WHITE_COLOR};
|
||||||
|
border-color: ${BORDER_GRAY_COLOR};
|
||||||
|
`;
|
||||||
|
|
||||||
const StyledBrand = styled.a`
|
const StyledBrand = styled.a`
|
||||||
background-color: ${MAIN_COLOR_BLUE};
|
background-color: ${MAIN_COLOR_BLUE};
|
||||||
|
@ -21,7 +32,9 @@ const StyledBrand = styled.a`
|
||||||
}
|
}
|
||||||
|
|
||||||
& > img {
|
& > img {
|
||||||
height: 20px;
|
margin-top: -4px;
|
||||||
|
max-width: 132px;
|
||||||
|
max-height: 26px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -38,7 +51,6 @@ class Navigation extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
console.log("runned");
|
|
||||||
this.props.getTeamsList();
|
this.props.getTeamsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +70,7 @@ class Navigation extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Navbar onSelect={this.selectItemCallback}>
|
<StyledNavbar onSelect={this.selectItemCallback}>
|
||||||
<Navbar.Header>
|
<Navbar.Header>
|
||||||
<Navbar.Brand>
|
<Navbar.Brand>
|
||||||
<StyledBrand href="/" title="sciNote">
|
<StyledBrand href="/" title="sciNote">
|
||||||
|
@ -97,11 +109,10 @@ class Navigation extends Component {
|
||||||
<TeamSwitch eventKey={5} />
|
<TeamSwitch eventKey={5} />
|
||||||
<SearchDropdown />
|
<SearchDropdown />
|
||||||
<NotificationsDropdown />
|
<NotificationsDropdown />
|
||||||
<NavItem eventKey={7} href="#">
|
<InfoDropdown />
|
||||||
Link Right
|
<UserAccountDropdown />
|
||||||
</NavItem>
|
|
||||||
</Nav>
|
</Nav>
|
||||||
</Navbar>
|
</StyledNavbar>
|
||||||
<GlobalActivitiesModal
|
<GlobalActivitiesModal
|
||||||
showModal={this.state.showActivitesModal}
|
showModal={this.state.showActivitesModal}
|
||||||
onCloseModal={this.closeModalCallback}
|
onCloseModal={this.closeModalCallback}
|
||||||
|
|
11
app/javascript/packs/shared/reducers/UsersReducer.js
Normal file
11
app/javascript/packs/shared/reducers/UsersReducer.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { SET_CURRENT_USER } from "../actions/types";
|
||||||
|
|
||||||
|
export function currentUser(
|
||||||
|
state = { id: 0, fullName: "", avatarPath: "" },
|
||||||
|
action
|
||||||
|
) {
|
||||||
|
if (action.type === SET_CURRENT_USER) {
|
||||||
|
return Object.assign({}, state, action.payload);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
5
app/views/client_api/users/show.json.jbuilder
Normal file
5
app/views/client_api/users/show.json.jbuilder
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
json.user do
|
||||||
|
json.id user.id
|
||||||
|
json.fullName user.full_name
|
||||||
|
json.avatarPath avatar_path(user, :icon_small)
|
||||||
|
end
|
|
@ -15,14 +15,13 @@ Rails.application.routes.draw do
|
||||||
namespace :client_api, defaults: { format: 'json' } do
|
namespace :client_api, defaults: { format: 'json' } do
|
||||||
# activities
|
# activities
|
||||||
get '/activities', to: 'activities#index'
|
get '/activities', to: 'activities#index'
|
||||||
|
|
||||||
# teams
|
# teams
|
||||||
get '/teams', to: 'teams#index'
|
get '/teams', to: 'teams#index'
|
||||||
post '/change_team', to: 'teams#change_team'
|
post '/change_team', to: 'teams#change_team'
|
||||||
|
|
||||||
# notifications
|
# notifications
|
||||||
get '/recent_notifications', to: 'notifications#recent_notifications'
|
get '/recent_notifications', to: 'notifications#recent_notifications'
|
||||||
|
# users
|
||||||
|
get '/current_user_info', to: 'users#current_user_info'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Save sample table state
|
# Save sample table state
|
||||||
|
|
Loading…
Add table
Reference in a new issue