mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-02-21 06:15:31 +08:00
Merge pull request #835 from ZmagoD/zd_SCI_1706
disables invite user button if no emails present [fixes SCI-1706]
This commit is contained in:
commit
6702265b1e
7 changed files with 97 additions and 49 deletions
|
@ -1,28 +1,34 @@
|
|||
// @flow
|
||||
|
||||
import React from "react";
|
||||
import { func } from "prop-types";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { DropdownButton, MenuItem } from "react-bootstrap";
|
||||
|
||||
const InviteUsersButton = props => (
|
||||
type Props = {
|
||||
handleClick: Function,
|
||||
status: boolean
|
||||
};
|
||||
|
||||
const InviteUsersButton = ({
|
||||
handleClick,
|
||||
status
|
||||
} : Props) => (
|
||||
<DropdownButton
|
||||
bsStyle={"primary"}
|
||||
title={<FormattedMessage id="invite_users.dropdown_button.invite" />}
|
||||
id="invite_users.submit_button"
|
||||
disabled={status}
|
||||
>
|
||||
<MenuItem onClick={() => props.handleClick("guest")}>
|
||||
<MenuItem onClick={() => handleClick("guest")}>
|
||||
<FormattedMessage id="invite_users.dropdown_button.guest" />
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => props.handleClick("normal_user")}>
|
||||
<MenuItem onClick={() => handleClick("normal_user")}>
|
||||
<FormattedMessage id="invite_users.dropdown_button.normal_user" />
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => props.handleClick("admin")}>
|
||||
<MenuItem onClick={() => handleClick("admin")}>
|
||||
<FormattedMessage id="invite_users.dropdown_button.admin" />
|
||||
</MenuItem>
|
||||
</DropdownButton>
|
||||
);
|
||||
|
||||
InviteUsersButton.propTypes = {
|
||||
handleClick: func.isRequired
|
||||
};
|
||||
|
||||
export default InviteUsersButton;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// @flow
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { bool, func, shape, number, string } from "prop-types";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { Modal, ButtonToolbar, Button } from "react-bootstrap";
|
||||
import styled from "styled-components";
|
||||
import axios from "../../config/axios";
|
||||
import type { Team } from "flow-typed";
|
||||
|
||||
import { inviteUsersToTeam } from "../../services/api/user_team_api";
|
||||
import { getTeamDetails } from "../../services/api/teams_api";
|
||||
|
||||
import {
|
||||
INVITE_USERS_PATH,
|
||||
TEAM_DETAILS_PATH
|
||||
} from "../../config/api_endpoints";
|
||||
import InviteUsersForm from "./components/InviteUsersForm";
|
||||
import InviteUsersResults from "./components/InviteUsersResults";
|
||||
import InviteUsersButton from "./components/InviteUsersButton";
|
||||
|
@ -17,52 +17,68 @@ const StyledButtonToolbar = styled(ButtonToolbar)`
|
|||
float: right;
|
||||
`;
|
||||
|
||||
class InviteUsersModal extends Component {
|
||||
constructor(props) {
|
||||
type Props = {
|
||||
showModal: boolean,
|
||||
onCloseModal: Function,
|
||||
team: Team,
|
||||
updateUsersCallback: Function
|
||||
};
|
||||
|
||||
type State = {
|
||||
inviteUserButtonDisabled: boolean,
|
||||
showInviteUsersResults: boolean,
|
||||
inputTags: Array<string>,
|
||||
inviteResults: Array<string>
|
||||
};
|
||||
|
||||
class InviteUsersModal extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
(this: any).state = {
|
||||
inviteUserButtonDisabled: true,
|
||||
showInviteUsersResults: false,
|
||||
inputTags: [],
|
||||
inviteResults: []
|
||||
};
|
||||
this.handleInputChange = this.handleInputChange.bind(this);
|
||||
this.inviteAs = this.inviteAs.bind(this);
|
||||
this.handleCloseModal = this.handleCloseModal.bind(this);
|
||||
(this: any).handleInputChange = this.handleInputChange.bind(this);
|
||||
(this: any).inviteAs = this.inviteAs.bind(this);
|
||||
(this: any).handleCloseModal = this.handleCloseModal.bind(this);
|
||||
}
|
||||
|
||||
handleCloseModal() {
|
||||
const path = TEAM_DETAILS_PATH.replace(":team_id", this.props.team.id);
|
||||
handleCloseModal(): void {
|
||||
this.props.onCloseModal();
|
||||
this.setState({
|
||||
(this: any).setState({
|
||||
showInviteUsersResults: false,
|
||||
inputTags: [],
|
||||
inviteResults: []
|
||||
});
|
||||
// Update team members table
|
||||
axios.get(path).then(response => {
|
||||
const { users } = response.data.team_details;
|
||||
getTeamDetails(this.props.team.id).then(response => {
|
||||
const { users } = response;
|
||||
this.props.updateUsersCallback(users);
|
||||
});
|
||||
}
|
||||
|
||||
handleInputChange(inputTags) {
|
||||
this.setState({ inputTags });
|
||||
handleInputChange(inputTags: Array<string>): void {
|
||||
if (inputTags.length > 0) {
|
||||
(this: any).setState({ inputTags, inviteUserButtonDisabled: false });
|
||||
} else {
|
||||
(this: any).setState({ inputTags, inviteUserButtonDisabled: true });
|
||||
}
|
||||
}
|
||||
|
||||
inviteAs(role) {
|
||||
axios
|
||||
.put(INVITE_USERS_PATH, {
|
||||
user_role: role,
|
||||
emails: this.state.inputTags,
|
||||
team_id: this.props.team.id
|
||||
})
|
||||
.then(({ data }) => {
|
||||
this.setState({ inviteResults: data, showInviteUsersResults: true });
|
||||
inviteAs(role: number): void {
|
||||
inviteUsersToTeam(role, this.state.inputTags, this.props.team.id)
|
||||
.then(response => {
|
||||
(this: any).setState({
|
||||
inviteResults: response,
|
||||
showInviteUsersResults: true
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.log("Invite As Error: ", error);
|
||||
if (error.response) {
|
||||
console.log("Error message:", error.response.data);
|
||||
console.log("Error message: ", error.response.data);
|
||||
// TO DO: put this error in flash msg
|
||||
}
|
||||
});
|
||||
|
@ -82,7 +98,12 @@ class InviteUsersModal extends Component {
|
|||
teamName={this.props.team.name}
|
||||
/>
|
||||
);
|
||||
inviteButton = <InviteUsersButton handleClick={this.inviteAs} />;
|
||||
inviteButton = (
|
||||
<InviteUsersButton
|
||||
handleClick={this.inviteAs}
|
||||
status={this.state.inviteUserButtonDisabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -119,11 +140,4 @@ class InviteUsersModal extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
InviteUsersModal.propTypes = {
|
||||
showModal: bool.isRequired,
|
||||
onCloseModal: func.isRequired,
|
||||
team: shape({ id: number.isRequired, name: string.isRequired }).isRequired,
|
||||
updateUsersCallback: func.isRequired
|
||||
};
|
||||
|
||||
export default InviteUsersModal;
|
||||
|
|
|
@ -14,8 +14,6 @@ export const SEARCH_PATH = "/search";
|
|||
|
||||
// notifications
|
||||
export const RECENT_NOTIFICATIONS_PATH = "/client_api/recent_notifications";
|
||||
|
||||
export const INVITE_USERS_PATH = "/client_api/users/invite_users";
|
||||
// info dropdown_title
|
||||
export const CUSTOMER_SUPPORT_LINK = "http://scinote.net/support";
|
||||
export const TUTORIALS_LINK = "http://scinote.net/product/tutorials/";
|
||||
|
|
|
@ -38,6 +38,7 @@ export const CONTACT_US_LINK =
|
|||
export const LEAVE_TEAM_PATH = "/client_api/users/leave_team";
|
||||
export const UPDATE_USER_TEAM_ROLE_PATH = "/client_api/users/update_role";
|
||||
export const REMOVE_USER_FROM_TEAM_PATH = "/client_api/users/remove_user";
|
||||
export const INVITE_USERS_PATH = "/client_api/users/invite_users";
|
||||
|
||||
// settings
|
||||
export const SETTINGS_TEAMS = "/settings/teams";
|
||||
|
|
9
app/javascript/src/services/api/teams_api.js
Normal file
9
app/javascript/src/services/api/teams_api.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
// @flow
|
||||
|
||||
import { axiosInstance } from "./config";
|
||||
import { TEAM_DETAILS_PATH } from "./endpoints";
|
||||
|
||||
export const getTeamDetails = (teamID: number): Promise<*> => {
|
||||
const path = TEAM_DETAILS_PATH.replace(":team_id", teamID);
|
||||
return axiosInstance.get(path).then(({ data }) => data.team_details);
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import { axiosInstance } from "./config";
|
||||
import { REMOVE_USER_FROM_TEAM_PATH } from "./endpoints";
|
||||
import { REMOVE_USER_FROM_TEAM_PATH, INVITE_USERS_PATH } from "./endpoints";
|
||||
|
||||
export const removeUserFromTeam = (
|
||||
teamId: number,
|
||||
|
@ -15,3 +16,17 @@ export const removeUserFromTeam = (
|
|||
}
|
||||
}).then(({ data }) => data.team_users);
|
||||
};
|
||||
|
||||
export const inviteUsersToTeam = (
|
||||
role: number,
|
||||
emails: Array<string>,
|
||||
teamID: number
|
||||
): Promise<*> => {
|
||||
return axiosInstance
|
||||
.put(INVITE_USERS_PATH, {
|
||||
user_role: role,
|
||||
team_id: teamID,
|
||||
emails
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
};
|
||||
|
|
5
flow-typed/types.js
vendored
5
flow-typed/types.js
vendored
|
@ -5,3 +5,8 @@ export type Activity = {
|
|||
message: string,
|
||||
created_at :string
|
||||
}
|
||||
|
||||
export type Team = {
|
||||
id: number,
|
||||
name: string
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue