style global activities

This commit is contained in:
zmagod 2017-08-22 13:20:06 +02:00
parent 685cb42aac
commit 3a2a1205e3
11 changed files with 190 additions and 54 deletions

View file

@ -4,6 +4,7 @@ export const GET_LIST_OF_TEAMS = "GET_LIST_OF_TEAMS";
// activities
export const GLOBAL_ACTIVITIES_DATA = "GLOBAL_ACTIVITIES_DATA";
export const DESTROY_GLOBAL_ACTIVITIES_DATA = "DESTROY_GLOBAL_ACTIVITIES_DATA";
// users
export const SET_CURRENT_USER = "SET_CURRENT_USER";

View file

@ -3,3 +3,7 @@ export const WHITE_COLOR = "#fff";
export const BORDER_GRAY_COLOR = "#d2d2d2";
export const WILD_SAND_COLOR = "#f5f5f5";
export const MYSTIC_COLOR = "#eaeff2";
export const COLOR_CONCRETE = "#f2f2f2";
export const COLOR_MINE_SHAFT = "#333"
export const COLOR_BLACK = "#000";
export const COLOR_GRAY_LIGHT_YADCF = "#ccc";

View file

@ -1,6 +1,9 @@
import axios from "../../app/axios";
import { ACTIVITIES_PATH } from "../../app/routes";
import { GLOBAL_ACTIVITIES_DATA } from "../../app/action_types";
import {
GLOBAL_ACTIVITIES_DATA,
DESTROY_GLOBAL_ACTIVITIES_DATA
} from "../../app/action_types";
function addActivitiesData(data) {
return {
@ -9,9 +12,15 @@ function addActivitiesData(data) {
};
}
export function getActivities(last_id = 0) {
export function destroyActivities() {
return {
type: DESTROY_GLOBAL_ACTIVITIES_DATA
};
}
export function getActivities(lastId = 0) {
return dispatch => {
let path = `${ACTIVITIES_PATH}?from=${last_id}`;
const path = `${ACTIVITIES_PATH}?from=${lastId}`;
axios
.get(path, { withCredentials: true })
.then(response => {

View file

@ -1,11 +1,34 @@
import React from "react";
import PropTypes from "prop-types";
import { FormattedDate } from "react-intl";
import Moment from "react-moment";
import styled from "styled-components";
import { WHITE_COLOR } from "../../../app/constants/colors"
const StyledLi = styled.li`
margin-bottom: 1em;
`
const StyledSpan = styled.span`
display: inline;
padding: 5px 30px;
font-size: 1em;
font-weight: bold;
line-height: 1;
color: ${WHITE_COLOR};
white-space: nowrap;
vertical-align: baseline;
border-radius: .25em;
`;
const ActivityDateElement = ({ date }) =>
<li className="data-element">
<FormattedDate value={date} day="2-digit" month="2-digit" year="numeric" />
</li>;
<StyledLi className="text-center">
<StyledSpan className="label label-primary">
<Moment format="DD.MM.YYYY">
{date}
</Moment>
</StyledSpan>
</StyledLi>;
ActivityDateElement.propTypes = {
date: PropTypes.instanceOf(Date).isRequired

View file

@ -1,24 +1,54 @@
import React from "react";
import PropTypes from "prop-types";
import { FormattedTime } from "react-intl";
import Moment from "react-moment";
import styled from "styled-components";
import {
WHITE_COLOR,
COLOR_CONCRETE,
BORDER_GRAY_COLOR
} from "../../../app/constants/colors";
const StyledLi = styled.li`
border-radius: .25em;
margin-bottom: 1em;
background-color: ${WHITE_COLOR};
border: 1px solid ${COLOR_CONCRETE};
`;
const TimeSpan = styled.span`
min-width: 150px;
display: table-cell;
vertical-align: middle;
border-top-left-radius: .25em;
border-bottom-left-radius: .25em;
border: 3px solid ${BORDER_GRAY_COLOR};
background-color: ${BORDER_GRAY_COLOR};
padding-left: 10px;
padding-right: 10px;
vertical-align: top;
`;
const TextSpan = styled.span`
display: table-cell;
padding: 3px 10px;
text-align: justify;
`
const ActivityElement = ({ activity }) =>
<li>
<span>
<FormattedTime
value={activity.created_at}
hour="numeric"
minute="numeric"
/>
</span>
<span dangerouslySetInnerHTML={{ __html: activity.message }} />
</li>;
<StyledLi>
<TimeSpan>
<Moment format="HH.mm">
{activity.created_at}
</Moment>
</TimeSpan>
<TextSpan dangerouslySetInnerHTML={{ __html: activity.message }} />
</StyledLi>;
ActivityElement.propTypes = {
activity: PropTypes.shape({
message: PropTypes.string.isRequired,
created_at: PropTypes.string.isRequired
})
}).isRequired
};
export default ActivityElement;

View file

@ -4,10 +4,46 @@ import PropTypes from "prop-types";
import { FormattedMessage } from "react-intl";
import { Modal, Button } from "react-bootstrap";
import _ from "lodash";
import styled from "styled-components";
import { getActivities } from "../../actions/ActivitiesActions";
import ActivityElement from "./ActivityElement";
import ActivityDateElement from "./ActivityDateElement";
import {
WHITE_COLOR,
COLOR_CONCRETE,
COLOR_MINE_SHAFT,
COLOR_GRAY_LIGHT_YADCF
} from "../../../app/constants/colors";
const StyledBottom = styled(Button)`
display: inline-block;
margin-bottom: 0;
font-weight: normal;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
border: 1px solid transparent;
white-space: nowrap;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
border-radius: 4px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
color: ${COLOR_MINE_SHAFT};
background-color: ${WHITE_COLOR};
border-color: ${COLOR_GRAY_LIGHT_YADCF};
`;
const StyledModalBody = styled(Modal.Body)`
background-color: ${COLOR_CONCRETE};
color: ${COLOR_MINE_SHAFT};;
`;
class GlobalActivitiesModal extends Component {
constructor(props) {
@ -52,13 +88,14 @@ class GlobalActivitiesModal extends Component {
addMoreButton() {
if (this.props.more) {
return (
<li>
<Button onClick={this.addMoreActivities}>
<li className="text-center">
<StyledBottom onClick={this.addMoreActivities}>
<FormattedMessage id="activities.more_activities" />
</Button>
</StyledBottom>
</li>
);
}
return "";
}
render() {
@ -69,12 +106,12 @@ class GlobalActivitiesModal extends Component {
<FormattedMessage id="activities.modal_title" />
</Modal.Title>
</Modal.Header>
<Modal.Body>
<ul>
<StyledModalBody>
<ul className="list-unstyled">
{this.displayActivities()}
{this.addMoreButton()}
</ul>
</Modal.Body>
</StyledModalBody>
<Modal.Footer>
<Button onClick={this.props.onCloseModal}>
<FormattedMessage id="general.close" />

View file

@ -8,7 +8,7 @@ import {
WHITE_COLOR,
BORDER_GRAY_COLOR
} from "../../app/constants/colors";
import { getActivities } from "../actions/ActivitiesActions";
import { getActivities, destroyActivities } from "../actions/ActivitiesActions";
import TeamSwitch from "./components/TeamSwitch";
import GlobalActivitiesModal from "./components/GlobalActivitiesModal";
import SearchDropdown from "./components/SearchDropdown";
@ -50,16 +50,29 @@ class Navigation extends Component {
}
selectItemCallback(key, ev) {
if (key === 4) {
ev.preventDefault();
this.setState({ showActivitesModal: !this.state.showActivitesModal });
// Call action creator to fetch activities from the server
this.props.fetchActivities();
switch (key) {
case 1:
window.location = "/";
break;
case 2:
window.location = "/protocols";
break;
case 3:
window.location = `/teams/${this.props.current_team.id}/repositories`;
break;
case 4:
ev.preventDefault();
this.setState({ showActivitesModal: !this.state.showActivitesModal });
// Call action creator to fetch activities from the server
this.props.fetchActivities();
break;
default:
}
}
closeModalCallback() {
this.setState({ showActivitesModal: false });
this.props.destroyActivities();
}
render() {
@ -74,21 +87,16 @@ class Navigation extends Component {
</Navbar.Brand>
</Navbar.Header>
<Nav>
<NavItem onClick={() => (window.location = "/")}>
<NavItem eventKey={1}>
<span className="glyphicon glyphicon-home" title="Home" />
</NavItem>
<NavItem onClick={() => (window.location = "/protocols")}>
<NavItem eventKey={2}>
<span
className="glyphicon glyphicon-list-alt"
title="Protocol repositories"
/>
</NavItem>
<NavItem
eventKey={3}
onClick={() =>
(window.location = `/teams/${this.props.current_team
.id}/repositories`)}
>
<NavItem eventKey={3}>
<i
className="fa fa-cubes"
aria-hidden="true"
@ -121,6 +129,7 @@ class Navigation extends Component {
Navigation.propTypes = {
fetchActivities: PropTypes.func.isRequired,
destroyActivities: PropTypes.func.isRequired,
current_team: PropTypes.shape({
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
@ -135,6 +144,9 @@ const mapStateToProps = ({ current_team }) => ({ current_team });
const mapDispatchToProps = dispatch => ({
fetchActivities() {
dispatch(getActivities());
},
destroyActivities() {
dispatch(destroyActivities());
}
});

View file

@ -1,21 +1,27 @@
import {
GLOBAL_ACTIVITIES_DATA,
MORE_GLOBAL_ACTIVITIES
DESTROY_GLOBAL_ACTIVITIES_DATA
} from "../../app/action_types";
export function globalActivities(
state = { more: true, activities: [] },
action
) {
if (action.type === GLOBAL_ACTIVITIES_DATA) {
return {
...state,
activities: [
...state.activities,
...action.payload.global_activities.activities
],
more: action.payload.global_activities.more
};
const initialStateu = { more: true, activities: [] };
export function globalActivities(state = initialStateu, action) {
switch (action.type) {
case GLOBAL_ACTIVITIES_DATA:
return {
...state,
activities: [
...state.activities,
...action.payload.global_activities.activities
],
more: action.payload.global_activities.more
};
case DESTROY_GLOBAL_ACTIVITIES_DATA:
return {
...state,
...initialStateu
};
default:
return state;
}
return state;
}

View file

@ -6,3 +6,7 @@ body {
font-family: "Open Sans",Arial,Helvetica,sans-serif;
font-size: 13px;
}
.label-primary {
background-color: $color-theme-primary;
}

View file

@ -53,6 +53,7 @@
"glob": "^7.1.2",
"js-yaml": "^3.9.0",
"lodash": "^4.17.4",
"moment": "^2.18.1",
"node-sass": "^4.5.3",
"path-complete-extname": "^0.1.0",
"postcss-loader": "^2.0.6",
@ -65,6 +66,7 @@
"react-dom": "^15.6.1",
"react-intl": "^2.3.0",
"react-intl-redux": "^0.6.0",
"react-moment": "^0.6.4",
"react-redux": "^5.0.5",
"react-router-bootstrap": "^0.24.2",
"react-router-dom": "^4.1.2",

View file

@ -3596,6 +3596,10 @@ mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkd
dependencies:
minimist "0.0.8"
moment@^2.18.1:
version "2.18.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@ -4692,6 +4696,10 @@ react-intl@^2.3.0:
intl-relativeformat "^1.3.0"
invariant "^2.1.1"
react-moment@^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/react-moment/-/react-moment-0.6.4.tgz#5e531d47ad7b0bff6f6b7175093e98659f5e667b"
react-overlays@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.7.0.tgz#531898ff566c7e5c7226ead2863b8cf9fbb5a981"