Commit 960ca5a4 authored by Alexandros Georgantas's avatar Alexandros Georgantas

global teams component

parent 27d2ba38
module.exports = {
frontend: {
components: [() => require('./src/GlobalTeamsManager')],
},
}
{
"name": "pubsweet-component-editoria-global-teams",
"version": "0.1.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"pubsweet-component",
"pubsweet-client"
],
"author": "",
"license": "ISC",
"dependencies": {
"classnames": "^2.2.5",
"config": "^1.27.0",
"editoria-common": "^0.1.1",
"font-awesome": "4.7.0",
"formik": "^0.11.11",
"lodash": "4.17.4",
"pubsweet-client": "^2.5.5",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-redux": "5.0.4",
"react-router-dom": "4.2.2",
"react-select": "^2.1.1",
"redux": "3.7.2",
"styled-components": "^3.3.0"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"enzyme": "^2.9.1",
"enzyme-to-json": "^1.5.1",
"file-loader": "^0.11.2",
"identity-obj-proxy": "^3.0.0",
"jest": "^20.0.4",
"node-sass": "^4.5.3",
"prop-types": "^15.5.10",
"react-addons-test-utils": "^15.6.0",
"react-styleguidist": "^6.0.24",
"react-test-renderer": "^15.6.1",
"sass-loader": "^6.0.6",
"sinon": "^2.3.6",
"sinon-as-promised": "^4.0.3",
"webpack": "^2.7.0",
"webpack-node-externals": "^1.6.0"
}
}
/* eslint-disable react/prop-types */
import styled from 'styled-components'
import { Form, Formik } from 'formik'
import React, { Component } from 'react'
import Select from 'react-select'
import { sortBy, keys } from 'lodash'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
// TODO -- clean up this import
import Actions from 'pubsweet-client/src/actions'
const TeamHeadingWrapper = styled.h4`
border-bottom: 1px solid black;
font-size: 24px;
line-height: 28px;
margin: 0;
`
const TeamSectionWrapper = styled.div`
padding: calc(8px * 2) 0;
`
const Ribbon = styled.div`
background: green;
border-radius: 3px;
color: #fff;
font-size: 14px;
line-height: 16px;
padding: calc(8px / 2) 0;
margin-top: 8px;
text-align: center;
visibility: ${props => (props.hide ? 'hidden' : 'visible')};
width: 60%;
`
const ButtonWrapper = styled.div`
padding: calc(8px * 2) 0;
`
const StyledSelect = styled(Select)`
margin-top: 8px;
outline: none;
> div:first-of-type {
border-radius: 0;
border: 1px solid black;
box-shadow: none;
&:hover {
border-color: #0b65cb;
}
> div > div > div:last-child {
&:hover {
background: #ff2d1a;
color: #ff2d1a;
}
}
}
`
const PageHeading = styled.h2`
margin: 0;
font-size: 36px;
padding: 0 calc(8px * 2);
`
const PageWrapper = styled.div`
align-items: center;
display: flex;
flex-direction: column;
form {
width: 60%;
}
`
const TeamHeading = props => {
const { name } = props
return <TeamHeadingWrapper>{name}</TeamHeadingWrapper>
}
const TeamSection = props => {
const { name, setFieldValue, type, users, value } = props
const options = users
? users.map(user => ({
label: user.username,
value: user.id,
}))
: []
const selectValue = value.map(userId => {
const user = users.find(u => u.id === userId)
if (user) {
return {
label: user.username,
value: userId,
}
}
return userId
})
const handleChange = newValue => {
setFieldValue(type, newValue)
}
return (
<TeamSectionWrapper>
<TeamHeading name={name} />
<StyledSelect
closeMenuOnSelect={false}
isMulti
name={type}
onChange={handleChange}
options={options}
value={selectValue}
/>
</TeamSectionWrapper>
)
}
const TeamManagerForm = props => {
const { setFieldValue, teams, users, values } = props
return (
<Form>
{teams.map(team => (
<TeamSection
key={team.id}
name={team.name}
setFieldValue={setFieldValue}
type={team.teamType}
users={users}
value={values[team.teamType]}
/>
))}
<ButtonWrapper>
<button disabled={!props.dirty} primary type="submit">
Save
</button>
</ButtonWrapper>
</Form>
)
}
class GlobalTeamsManager extends Component {
constructor(props) {
super(props)
this.state = {
hideRibbon: true,
ready: false,
}
}
componentWillMount() {
const { getUsers, getTeams } = this.props.actions
Promise.all([getUsers(), getTeams()]).then(values => {
this.setState({ ready: true })
})
}
handleSubmit = (formValues, formikBag) => {
const { teams, actions } = this.props
const { updateTeam } = actions
const data = keys(formValues).map(teamType => ({
id: teams.find(t => t.teamType === teamType && t.global).id,
members: formValues[teamType].map(item => {
if (item.id) return item.id
return item.value
}),
}))
console.log('data', data)
const promises = data.map(team => updateTeam(team))
Promise.all(promises).then(res => {
this.showRibbon()
formikBag.resetForm(formValues)
})
}
// TODO -- handle better cases like many quick saves
showRibbon = () => {
this.setState({
hideRibbon: false,
})
setTimeout(
() =>
this.setState({
hideRibbon: true,
}),
4000,
)
}
render() {
const { users, teams } = this.props
const { hideRibbon, ready } = this.state
if (!ready) return null
let globalTeams = teams.filter(team => team.global)
const infoMessage = 'Your teams have been successfully updated'
const initialValues = {}
globalTeams.forEach(team => {
initialValues[team.teamType] = team.members
})
globalTeams = sortBy(globalTeams, 'name')
return (
<PageWrapper>
<PageHeading>Team Manager</PageHeading>
<Ribbon hide={hideRibbon}>{infoMessage}</Ribbon>
<Formik
initialValues={initialValues}
onSubmit={this.handleSubmit}
render={formikProps => (
<TeamManagerForm
teams={globalTeams}
users={users}
{...formikProps}
/>
)}
/>
</PageWrapper>
)
}
}
GlobalTeamsManager.defaultProps = {
teams: null,
users: null,
}
function mapStateToProps(state, { match }) {
const { users, teams } = state
return {
users: users.users,
teams,
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(Actions, dispatch),
}
}
export default connect(
mapStateToProps,
mapDispatchToProps,
)(GlobalTeamsManager)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment