mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-01-28 02:27:57 +08:00
adds edit team name modal
This commit is contained in:
parent
1a00b53034
commit
83647d81b4
6 changed files with 191 additions and 13 deletions
|
@ -40,7 +40,7 @@ module ClientApi
|
|||
private
|
||||
|
||||
def team_params
|
||||
params.require(:team).permit(:description)
|
||||
params.require(:team).permit(:description, :name)
|
||||
end
|
||||
|
||||
def success_response(template, locals)
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
export const ENTER_KEY_CODE = 13;
|
||||
export const TEXT_MAX_LENGTH = 10000;
|
||||
export const NAME_MAX_LENGTH = 255;
|
||||
|
|
|
@ -83,6 +83,10 @@ export default {
|
|||
title: "Edit team description",
|
||||
label: "Description"
|
||||
},
|
||||
update_team_name_modal: {
|
||||
title: "Edit team name",
|
||||
label: "Name"
|
||||
},
|
||||
single_team: {
|
||||
created_on: "Created on: <strong>{created_at}</strong>",
|
||||
created_by: "Created by: <strong>{created_by}</strong>",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { Component } from "react";
|
||||
import ReactRouterPropTypes from "react-router-prop-types";
|
||||
import { Link } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import { Row, Col, Glyphicon, Well } from "react-bootstrap";
|
||||
import { FormattedHTMLMessage, FormattedMessage } from "react-intl";
|
||||
|
@ -7,7 +8,7 @@ import moment from "moment";
|
|||
import prettysize from "prettysize";
|
||||
import axios from "../../../../app/axios";
|
||||
|
||||
import { TEAM_DETAILS_PATH } from "../../../../app/routes";
|
||||
import { TEAM_DETAILS_PATH, SETTINGS_TEAMS } from "../../../../app/routes";
|
||||
import {
|
||||
BORDER_LIGHT_COLOR,
|
||||
COLOR_CONCRETE
|
||||
|
@ -15,6 +16,7 @@ import {
|
|||
|
||||
import TeamsMembers from "./components/TeamsMembers";
|
||||
import UpdateTeamDescriptionModal from "./components/UpdateTeamDescriptionModal";
|
||||
import UpdateTeamNameModal from "./components/UpdateTeamNameModal";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
background: white;
|
||||
|
@ -25,10 +27,7 @@ const Wrapper = styled.div`
|
|||
padding: 16px 15px 50px 15px;
|
||||
`;
|
||||
|
||||
const TabTitle = styled.div`
|
||||
background-color: ${COLOR_CONCRETE};
|
||||
padding: 15px;
|
||||
`;
|
||||
const TabTitle = styled.div`padding: 15px;`;
|
||||
|
||||
const BadgeWrapper = styled.div`
|
||||
font-size: 1.4em;
|
||||
|
@ -45,11 +44,21 @@ const StyledWell = styled(Well)`
|
|||
}
|
||||
`;
|
||||
|
||||
const StyledH3 = styled.h3`
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledOl = styled.ol`padding: 15px;`;
|
||||
|
||||
class SettingsTeamPageContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showModal: false,
|
||||
showDescriptionModal: false,
|
||||
showNameModal: false,
|
||||
users: [],
|
||||
team: {
|
||||
id: 0,
|
||||
|
@ -66,6 +75,8 @@ class SettingsTeamPageContainer extends Component {
|
|||
);
|
||||
this.updateTeamCallback = this.updateTeamCallback.bind(this);
|
||||
this.updateUsersCallback = this.updateUsersCallback.bind(this);
|
||||
this.showNameModal = this.showNameModal.bind(this);
|
||||
this.hideNameModalCallback = this.hideNameModalCallback.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -78,11 +89,19 @@ class SettingsTeamPageContainer extends Component {
|
|||
}
|
||||
|
||||
showDescriptionModal() {
|
||||
this.setState({ showModal: true });
|
||||
this.setState({ showDescriptionModal: true });
|
||||
}
|
||||
|
||||
hideDescriptionModalCallback() {
|
||||
this.setState({ showModal: false });
|
||||
this.setState({ showDescriptionModal: false });
|
||||
}
|
||||
|
||||
showNameModal() {
|
||||
this.setState({ showNameModal: true });
|
||||
}
|
||||
|
||||
hideNameModalCallback() {
|
||||
this.setState({ showNameModal: false });
|
||||
}
|
||||
|
||||
updateTeamCallback(team) {
|
||||
|
@ -105,9 +124,20 @@ class SettingsTeamPageContainer extends Component {
|
|||
render() {
|
||||
return (
|
||||
<Wrapper>
|
||||
<StyledOl className="breadcrumb">
|
||||
<li>
|
||||
<Link to={SETTINGS_TEAMS}>
|
||||
<FormattedMessage id="settings_page.all_teams" />
|
||||
</Link>
|
||||
</li>
|
||||
<li className="active">
|
||||
{this.state.team.name}
|
||||
</li>
|
||||
</StyledOl>
|
||||
<TabTitle>
|
||||
<FormattedMessage id="settings_page.all_teams" />
|
||||
{` / ${this.state.team.name}`}
|
||||
<StyledH3 onClick={this.showNameModal}>
|
||||
{this.state.team.name}
|
||||
</StyledH3>
|
||||
</TabTitle>
|
||||
<Row>
|
||||
<Col xs={6} sm={3}>
|
||||
|
@ -166,11 +196,17 @@ class SettingsTeamPageContainer extends Component {
|
|||
team={this.state.team}
|
||||
/>
|
||||
<UpdateTeamDescriptionModal
|
||||
showModal={this.state.showModal}
|
||||
showModal={this.state.showDescriptionModal}
|
||||
hideModal={this.hideDescriptionModalCallback}
|
||||
team={this.state.team}
|
||||
updateTeamCallback={this.updateTeamCallback}
|
||||
/>
|
||||
<UpdateTeamNameModal
|
||||
showModal={this.state.showNameModal}
|
||||
hideModal={this.hideNameModalCallback}
|
||||
team={this.state.team}
|
||||
updateTeamCallback={this.updateTeamCallback}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ class UpdateTeamDescriptionModal extends Component {
|
|||
withCredentials: true,
|
||||
data: {
|
||||
team_id: this.props.team.id,
|
||||
description: this.state.description
|
||||
team: { description: this.state.description }
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes, { bool, number, string, func } from "prop-types";
|
||||
import {
|
||||
Modal,
|
||||
Button,
|
||||
FormGroup,
|
||||
ControlLabel,
|
||||
FormControl,
|
||||
HelpBlock
|
||||
} from "react-bootstrap";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import _ from "lodash";
|
||||
import styled from "styled-components";
|
||||
import axios from "../../../../../app/axios";
|
||||
|
||||
import { NAME_MAX_LENGTH } from "../../../../../app/constants/numeric";
|
||||
import { TEAM_UPDATE_PATH } from "../../../../../app/routes";
|
||||
import { COLOR_APPLE_BLOSSOM } from "../../../../../app/constants/colors";
|
||||
|
||||
const StyledHelpBlock = styled(HelpBlock)`
|
||||
color: ${COLOR_APPLE_BLOSSOM}
|
||||
`;
|
||||
|
||||
class UpdateTeamNameModal extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { errorMessage: "", name: "" };
|
||||
this.onCloseModal = this.onCloseModal.bind(this);
|
||||
this.updateName = this.updateName.bind(this);
|
||||
this.handleName = this.handleName.bind(this);
|
||||
this.getValidationState = this.getValidationState.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({ name: this.props.team.name });
|
||||
}
|
||||
|
||||
onCloseModal() {
|
||||
this.setState({ errorMessage: "", name: "" });
|
||||
this.props.hideModal();
|
||||
}
|
||||
|
||||
getValidationState() {
|
||||
if (this.state.errorMessage.length > 0) {
|
||||
return "error";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
handleName(el) {
|
||||
const { value } = el.target;
|
||||
if (value.length > NAME_MAX_LENGTH) {
|
||||
this.setState({
|
||||
errorMessage: (
|
||||
<FormattedMessage
|
||||
id="error_messages.text_too_long"
|
||||
values={{ max_length: NAME_MAX_LENGTH }}
|
||||
/>
|
||||
)
|
||||
});
|
||||
} else {
|
||||
this.setState({ errorMessage: "", name: value });
|
||||
}
|
||||
}
|
||||
|
||||
updateName() {
|
||||
axios({
|
||||
method: "post",
|
||||
url: TEAM_UPDATE_PATH,
|
||||
withCredentials: true,
|
||||
data: {
|
||||
team_id: this.props.team.id,
|
||||
team: { name: this.state.name }
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
this.props.updateTeamCallback(response.data.team);
|
||||
this.onCloseModal();
|
||||
})
|
||||
.catch(error => this.setState({ errorMessage: error.message }));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal show={this.props.showModal} onHide={this.onCloseModal}>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>
|
||||
<FormattedMessage id="settings_page.update_team_name_modal.title" />
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<FormGroup
|
||||
controlId="teamName"
|
||||
validationState={this.getValidationState()}
|
||||
>
|
||||
<ControlLabel>
|
||||
<FormattedMessage id="settings_page.update_team_name_modal.label" />
|
||||
</ControlLabel>
|
||||
<FormControl
|
||||
type="text"
|
||||
onChange={this.handleName}
|
||||
value={this.state.name}
|
||||
/>
|
||||
<FormControl.Feedback />
|
||||
<StyledHelpBlock>
|
||||
{this.state.errorMessage}
|
||||
</StyledHelpBlock>
|
||||
</FormGroup>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button onClick={this.onCloseModal}>
|
||||
<FormattedMessage id="general.close" />
|
||||
</Button>
|
||||
<Button
|
||||
bsStyle="success"
|
||||
onClick={this.updateName}
|
||||
disabled={!_.isEmpty(this.state.errorMessage)}
|
||||
>
|
||||
<FormattedMessage id="general.update" />
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateTeamNameModal.propTypes = {
|
||||
showModal: bool.isRequired,
|
||||
hideModal: func.isRequired,
|
||||
team: PropTypes.shape({
|
||||
id: number.isRequired,
|
||||
name: string
|
||||
}).isRequired,
|
||||
updateTeamCallback: func.isRequired
|
||||
};
|
||||
|
||||
export default UpdateTeamNameModal;
|
Loading…
Reference in a new issue