adds main stylesheet for global styles

This commit is contained in:
zmagod 2017-08-09 12:46:04 +02:00
parent bd352869a3
commit 007f50a158
11 changed files with 171 additions and 54 deletions

View file

@ -22,7 +22,7 @@ export function getTeamsList() {
axios axios
.get(TEAMS_PATH, { withCredentials: true }) .get(TEAMS_PATH, { withCredentials: true })
.then(response => { .then(response => {
let teams = response.data; let teams = _.values(response.data);
dispatch(addTeamsData(teams)); dispatch(addTeamsData(teams));
let current_team = _.find(teams, team => team.current_team); let current_team = _.find(teams, team => team.current_team);
dispatch(setCurrentUser(current_team)); dispatch(setCurrentUser(current_team));
@ -38,7 +38,7 @@ export function changeTeam(team_id) {
axios axios
.post(CHANGE_TEAM_PATH, { team_id }, { withCredentials: true }) .post(CHANGE_TEAM_PATH, { team_id }, { withCredentials: true })
.then(response => { .then(response => {
let teams = response.data; let teams = _.values(response.data);
dispatch(addTeamsData(teams)); dispatch(addTeamsData(teams));
let current_team = _.find(teams, team => team.current_team); let current_team = _.find(teams, team => team.current_team);
dispatch(setCurrentUser(current_team)); dispatch(setCurrentUser(current_team));

View file

@ -6,7 +6,7 @@ import axios from "axios";
import { RECENT_NOTIFICATIONS_PATH } from "../../../app/routes"; import { RECENT_NOTIFICATIONS_PATH } from "../../../app/routes";
import NotificationItem from "./NotificationItem"; import NotificationItem from "./NotificationItem";
import Spinner from "../../spinner"; import Spinner from "../../Spinner";
import CustomNavItem from "./CustomNavItem"; import CustomNavItem from "./CustomNavItem";
class NotificationsDropdown extends Component { class NotificationsDropdown extends Component {

View file

@ -1,8 +1,29 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { NavDropdown, MenuItem } from "react-bootstrap"; import {
NavDropdown,
MenuItem,
FormGroup,
InputGroup,
Glyphicon
} from "react-bootstrap";
import styled from "styled-components";
import { SEARCH_PATH } from "../../../app/routes"; import { SEARCH_PATH } from "../../../app/routes";
const StyledFormGroup = styled(FormGroup)`
margin-bottom: 0px;
`;
const StyledMenuItem = styled(MenuItem)`
padding-top: 10px;
padding-bottom: 10px;
`;
const StyledNavDropdown = styled(NavDropdown)`
& > .dropdown-menu {
width: 250px;
}
`;
class SearchDropdown extends Component { class SearchDropdown extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -10,6 +31,7 @@ class SearchDropdown extends Component {
this.handleSearchTermChange = this.handleSearchTermChange.bind(this); this.handleSearchTermChange = this.handleSearchTermChange.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this); this.handleKeyPress = this.handleKeyPress.bind(this);
this.setFocusToInput = this.setFocusToInput.bind(this); this.setFocusToInput = this.setFocusToInput.bind(this);
this.submitSearch = this.submitSearch.bind(this);
} }
setFocusToInput(ev) { setFocusToInput(ev) {
@ -20,8 +42,7 @@ class SearchDropdown extends Component {
handleKeyPress(ev) { handleKeyPress(ev) {
if (ev.charCode === 13) { if (ev.charCode === 13) {
window.location = `${SEARCH_PATH}?q=${this.state.searchTerm}`; this.submitSearch();
this.setState({ searchTerm: "" });
} }
} }
@ -29,15 +50,22 @@ class SearchDropdown extends Component {
this.setState({ searchTerm: ev.target.value }); this.setState({ searchTerm: ev.target.value });
} }
submitSearch() {
window.location = `${SEARCH_PATH}?q=${this.state.searchTerm}`;
this.setState({ searchTerm: "" });
}
render() { render() {
return ( return (
<NavDropdown <StyledNavDropdown
noCaret noCaret
title={<span className="glyphicon glyphicon-search" />} title={<span className="glyphicon glyphicon-search" />}
onClick={this.setFocusToInput} onClick={this.setFocusToInput}
id="search-dropdown" id="search-dropdown"
> >
<MenuItem> <StyledMenuItem>
<StyledFormGroup>
<InputGroup>
<input <input
onChange={this.handleSearchTermChange} onChange={this.handleSearchTermChange}
onClick={this.setFocusToInput} onClick={this.setFocusToInput}
@ -47,9 +75,18 @@ class SearchDropdown extends Component {
}} }}
type="text" type="text"
placeholder="Search" placeholder="Search"
className="form-control"
/> />
</MenuItem> <InputGroup.Addon
</NavDropdown> onClick={this.submitSearch}
className="visible-xs visible-sm"
>
<Glyphicon glyph="menu-right" />
</InputGroup.Addon>
</InputGroup>
</StyledFormGroup>
</StyledMenuItem>
</StyledNavDropdown>
); );
} }
} }

View file

@ -2,9 +2,18 @@ import React, { Component } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import { NavDropdown, MenuItem } from "react-bootstrap"; import { NavDropdown, MenuItem, Glyphicon } from "react-bootstrap";
import styled from "styled-components";
import _ from "lodash";
import { BORDER_GRAY_COLOR } from "../../constants/colors";
import { setCurrentUser, changeTeam } from "../../actions/TeamsActions"; import { setCurrentUser, changeTeam } from "../../actions/TeamsActions";
import { getTeamsList } from "../../actions/TeamsActions";
const StyledNavDropdown = styled(NavDropdown)`
border-left: 1px solid ${BORDER_GRAY_COLOR};
border-right: 1px solid ${BORDER_GRAY_COLOR};
`;
class TeamSwitch extends Component { class TeamSwitch extends Component {
constructor(props) { constructor(props) {
@ -12,22 +21,28 @@ class TeamSwitch extends Component {
this.displayTeams = this.displayTeams.bind(this); this.displayTeams = this.displayTeams.bind(this);
} }
componentDidMount() {
this.props.getTeamsList();
}
changeTeam(teamId) { changeTeam(teamId) {
this.props.changeTeam(teamId); this.props.changeTeam(teamId);
} }
displayTeams() { displayTeams() {
if (!_.isEmpty(this.props.all_teams)) {
return this.props.all_teams.filter(team => !team.current_team).map(team => return this.props.all_teams.filter(team => !team.current_team).map(team =>
<MenuItem onSelect={() => this.changeTeam(team.id)} key={team.id}> <MenuItem onSelect={() => this.changeTeam(team.id)} key={team.id}>
{team.name} {team.name}
</MenuItem> </MenuItem>
); );
} }
}
newTeamLink() { newTeamLink() {
return ( return (
<MenuItem href="/users/settings/teams/new" key="addNewTeam"> <MenuItem href="/users/settings/teams/new" key="addNewTeam">
<span className="glyphicon glyphicon-plus" /> <Glyphicon glyph="plus" />&nbsp;
<FormattedMessage id="global_team_switch.new_team" /> <FormattedMessage id="global_team_switch.new_team" />
</MenuItem> </MenuItem>
); );
@ -35,20 +50,26 @@ class TeamSwitch extends Component {
render() { render() {
return ( return (
<NavDropdown <StyledNavDropdown
noCaret noCaret
eventKey={this.props.eventKey} eventKey={this.props.eventKey}
title={this.props.current_team.name} title={
<span>
<i className="fa fa-users" />&nbsp;{this.props.current_team.name}
</span>
}
id="team-switch" id="team-switch"
> >
{this.displayTeams()} {this.displayTeams()}
<MenuItem key="divider" divider />
{this.newTeamLink()} {this.newTeamLink()}
</NavDropdown> </StyledNavDropdown>
); );
} }
} }
TeamSwitch.propTypes = { TeamSwitch.propTypes = {
getTeamsList: PropTypes.func.isRequired,
eventKey: PropTypes.number.isRequired, eventKey: PropTypes.number.isRequired,
changeTeam: PropTypes.func.isRequired, changeTeam: PropTypes.func.isRequired,
all_teams: PropTypes.arrayOf( all_teams: PropTypes.arrayOf(
@ -56,27 +77,31 @@ TeamSwitch.propTypes = {
id: PropTypes.number.isRequired, id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
current_team: PropTypes.bool.isRequired current_team: PropTypes.bool.isRequired
}) }).isRequired
), ),
current_team: PropTypes.shape({ current_team: PropTypes.shape({
id: PropTypes.number.isRequired, id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
current_team: PropTypes.bool.isRequired current_team: PropTypes.bool.isRequired
}) }).isRequired
}; };
// Map the states from store to component // Map the states from store to component
const mapStateToProps = ({ all_teams, current_team }) => { const mapStateToProps = ({ all_teams, current_team }) => ({
return { all_teams, current_team }; current_team,
}; all_teams: _.values(all_teams)
});
// Map the fetch activity action to component // Map the fetch activity action to component
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
setCurrentUser() { setCurrentUser() {
dispatch(setCurrentUser()); dispatch(setCurrentUser());
}, },
changeTeam(team_id) { changeTeam(teamId) {
dispatch(changeTeam(team_id)); dispatch(changeTeam(teamId));
},
getTeamsList() {
dispatch(getTeamsList());
} }
}); });

View file

@ -1,7 +1,7 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { NavDropdown, MenuItem } from "react-bootstrap"; import { NavDropdown, MenuItem, Image } from "react-bootstrap";
import styled from "styled-components"; import styled from "styled-components";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
@ -31,10 +31,10 @@ class UserAccountDropdown extends Component {
id="user_account_dropdown.greeting" id="user_account_dropdown.greeting"
values={{ name: this.props.current_user.fullName }} values={{ name: this.props.current_user.fullName }}
/>&nbsp; />&nbsp;
<img <Image
src={this.props.current_user.avatarPath} src={this.props.current_user.avatarPath}
alt={this.props.current_user.fullName} alt={this.props.current_user.fullName}
className="img-circle" circle
/> />
</span> </span>
} }

View file

@ -9,7 +9,6 @@ import {
BORDER_GRAY_COLOR BORDER_GRAY_COLOR
} from "../constants/colors"; } from "../constants/colors";
import { getActivities } from "../actions/ActivitiesActions"; import { getActivities } from "../actions/ActivitiesActions";
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";
@ -50,10 +49,6 @@ class Navigation extends Component {
this.closeModalCallback = this.closeModalCallback.bind(this); this.closeModalCallback = this.closeModalCallback.bind(this);
} }
componentDidMount() {
this.props.getTeamsList();
}
selectItemCallback(key, ev) { selectItemCallback(key, ev) {
if (key === 4) { if (key === 4) {
ev.preventDefault(); ev.preventDefault();
@ -123,17 +118,13 @@ class Navigation extends Component {
} }
Navigation.propTypes = { Navigation.propTypes = {
fetchActivities: PropTypes.func.isRequired, fetchActivities: PropTypes.func.isRequired
getTeamsList: PropTypes.func.isRequired
}; };
// Map the fetch activity action to component // Map the fetch activity action to component
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
fetchActivities() { fetchActivities() {
dispatch(getActivities()); dispatch(getActivities());
},
getTeamsList() {
dispatch(getTeamsList());
} }
}); });

View file

@ -1,6 +1,6 @@
import { SET_CURRENT_TEAM, GET_LIST_OF_TEAMS } from "../actions/types"; import { SET_CURRENT_TEAM, GET_LIST_OF_TEAMS } from "../actions/types";
const initialState = { name: "", id: 0, current_team: true } const initialState = { name: "", id: 0, current_team: true };
export const setCurrentTeam = (state = initialState, action) => { export const setCurrentTeam = (state = initialState, action) => {
if (action.type === SET_CURRENT_TEAM) { if (action.type === SET_CURRENT_TEAM) {
return Object.assign({}, state, action.user); return Object.assign({}, state, action.user);
@ -8,9 +8,9 @@ export const setCurrentTeam = (state = initialState, action) => {
return state; return state;
}; };
export const getListOfTeams = (state = [initialState], action) => { export const getListOfTeams = (state = [], action) => {
if (action.type === GET_LIST_OF_TEAMS) { if (action.type === GET_LIST_OF_TEAMS) {
return [...state, ...action.payload] return Object.assign({}, state, action.payload);
} }
return state; return state;
}; };

View file

@ -0,0 +1,55 @@
//==============================================================================
// Colors
//==============================================================================
// Theme colors
$color-theme-primary: #37a0d9;
$color-theme-secondary: #8fd13f;
$color-theme-dark: #6d6e71;
// Grayscale colors
$color-white: #fff;
$color-alabaster: #fcfcfc;
$color-snow: #f9f9f9;
$color-wild-sand: #f5f5f5;
$color-concrete: #f2f2f2;
$color-gallery: #eee;
$color-gainsboro: #e3e3e3;
$color-alto: #d2d2d2;
$color-silver: #c5c5c5;
$color-dark-gray: #adadad;
$color-silver-chalice: #a0a0a0;
$color-gray: #909088;
$color-dove-gray: #666;
$color-emperor: #555;
$color-mine-shaft: #333;
$color-nero: #262626;
$color-black: #000;
$color-cloud: rgba(0, 0, 0, .1);
$color-gray-light-yadcf: #ccc;
$color-gray-dark-yadcf: #a9a9a9;
// Miscelaneous colors
$color-mystic: #eaeff2;
$color-candlelight: #ffda23;
$color-orange: #ff900b;
$color-saturated-green: #008600;
$color-blue-yadcf: #337ab7;
// Red colors
$color-mojo: #cf4b48;
$color-apple-blossom: #a94442;
$color-milano-red: #a70b05;
// Colors for specific intents
$color-visited-link: #23527c;
// Overlay shade for drag'n dropdown
$color-drag-overlay: rgba(0, 0, 0, .4);
//==============================================================================
// Other
//==============================================================================
// Some big value which is still supported by all browsers
$infinity: 9999999;

View file

@ -0,0 +1,8 @@
@import 'constants';
body {
background-color: $color-concrete;
color: $color-emperor;
font-family: "Open Sans",Arial,Helvetica,sans-serif;
font-size: 13px;
}

View file

@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<%= stylesheet_link_tag 'bootstrap/css/bootstrap.min' %> <%= stylesheet_link_tag 'bootstrap/css/bootstrap.min' %>
<%= stylesheet_link_tag 'font-awesome/css/font-awesome.min' %> <%= stylesheet_link_tag 'font-awesome/css/font-awesome.min' %>
<%= stylesheet_pack_tag 'styles/main' %>
<%= favicon_link_tag "favicon.ico" %> <%= favicon_link_tag "favicon.ico" %>
<%= favicon_link_tag "favicon-16.png", type: "image/png", size: "16x16" %> <%= favicon_link_tag "favicon-16.png", type: "image/png", size: "16x16" %>
<%= favicon_link_tag "favicon-32.png", type: "image/png", size: "32x32" %> <%= favicon_link_tag "favicon-32.png", type: "image/png", size: "32x32" %>