diff --git a/app/controllers/client_api/users/invitations_controller.rb b/app/controllers/client_api/users/invitations_controller.rb
index 21636fa71..eef944984 100644
--- a/app/controllers/client_api/users/invitations_controller.rb
+++ b/app/controllers/client_api/users/invitations_controller.rb
@@ -11,6 +11,12 @@ module ClientApi
emails: params[:emails])
invite_results = invite_service.invitation
success_response(invite_results)
+ rescue => error
+ respond_to do |format|
+ format.json do
+ render json: { message: error }, status: :unprocessable_entity
+ end
+ end
end
private
diff --git a/app/javascript/src/components/InviteUsersModal/components/InviteUsersButton.jsx b/app/javascript/src/components/InviteUsersModal/components/InviteUsersButton.jsx
index 7764041a6..1fcf52c43 100644
--- a/app/javascript/src/components/InviteUsersModal/components/InviteUsersButton.jsx
+++ b/app/javascript/src/components/InviteUsersModal/components/InviteUsersButton.jsx
@@ -1,5 +1,4 @@
// @flow
-
import React from "react";
import { FormattedMessage } from "react-intl";
import { DropdownButton, MenuItem } from "react-bootstrap";
@@ -9,26 +8,25 @@ type Props = {
status: boolean
};
-const InviteUsersButton = ({
- handleClick,
- status
-} : Props) => (
- }
- id="invite_users.submit_button"
- disabled={status}
- >
-
-
-
-
-);
+const InviteUsersButton = ({ handleClick, status }: Props) => {
+ return (
+ }
+ id="invite_users.submit_button"
+ disabled={status}
+ >
+
+
+
+
+ );
+};
export default InviteUsersButton;
diff --git a/app/javascript/src/components/InviteUsersModal/index.jsx b/app/javascript/src/components/InviteUsersModal/index.jsx
index 5ad716764..5e854c03d 100644
--- a/app/javascript/src/components/InviteUsersModal/index.jsx
+++ b/app/javascript/src/components/InviteUsersModal/index.jsx
@@ -77,7 +77,8 @@ class InviteUsersModal extends Component {
.then(response => {
(this: any).setState({
inviteResults: response,
- showInviteUsersResults: true
+ showInviteUsersResults: true,
+ inviteUserButtonDisabled: true
});
})
.catch(error => {
diff --git a/app/javascript/src/components/ModalsContainer/index.jsx b/app/javascript/src/components/ModalsContainer/index.jsx
deleted file mode 100644
index 7cf9aff55..000000000
--- a/app/javascript/src/components/ModalsContainer/index.jsx
+++ /dev/null
@@ -1,7 +0,0 @@
-import React from "react";
-import LeaveTeamModal from "./modals/LeaveTeamModal";
-
-export default () =>
-
-
-
;
diff --git a/app/javascript/src/components/actions/TeamsActions.js b/app/javascript/src/components/actions/TeamsActions.js
index ba7fa7262..3784c4693 100644
--- a/app/javascript/src/components/actions/TeamsActions.js
+++ b/app/javascript/src/components/actions/TeamsActions.js
@@ -1,41 +1,33 @@
-import axios from "../../config/axios";
-import _ from "lodash";
-import { TEAMS_PATH, CHANGE_TEAM_PATH } from "../../config/api_endpoints";
-import {
- GET_LIST_OF_TEAMS,
- SET_CURRENT_TEAM,
- SHOW_LEAVE_TEAM_MODAL
-} from "../../config/action_types";
+// @flow
+import type {
+ Teams$Team,
+ Action$AddTeamData,
+ Actopm$SetCurrentTeam
+} from "flow-typed";
+import type { Dispatch } from "redux-thunk";
+import { getTeams, changeCurrentTeam } from "../../services/api/teams_api";
+import { GET_LIST_OF_TEAMS, SET_CURRENT_TEAM } from "../../config/action_types";
-export function leaveTeamModalShow(show = false, team = {}) {
- return {
- payload: { team, show },
- type: SHOW_LEAVE_TEAM_MODAL
- };
-}
-
-export function addTeamsData(data) {
+export function addTeamsData(data: Array): Action$AddTeamData {
return {
type: GET_LIST_OF_TEAMS,
payload: data
};
}
-export function setCurrentTeam(team) {
+export function setCurrentTeam(team: Teams$Team): Actopm$SetCurrentTeam {
return {
team,
type: SET_CURRENT_TEAM
};
}
-export function getTeamsList() {
+export function getTeamsList(): Dispatch {
return dispatch => {
- axios
- .get(TEAMS_PATH, { withCredentials: true })
+ getTeams()
.then(response => {
- const teams = response.data.teams.collection;
+ const { teams, currentTeam } = response;
dispatch(addTeamsData(teams));
- const currentTeam = _.find(teams, team => team.current_team);
dispatch(setCurrentTeam(currentTeam));
})
.catch(error => {
@@ -44,14 +36,12 @@ export function getTeamsList() {
};
}
-export function changeTeam(team_id) {
+export function changeTeam(teamID: number): Dispatch {
return dispatch => {
- axios
- .post(CHANGE_TEAM_PATH, { team_id }, { withCredentials: true })
+ changeCurrentTeam(teamID)
.then(response => {
- const teams = response.data.teams.collection;
+ const { teams, currentTeam } = response;
dispatch(addTeamsData(teams));
- const currentTeam = _.find(teams, team => team.current_team);
dispatch(setCurrentTeam(currentTeam));
})
.catch(error => {
diff --git a/app/javascript/src/components/reducers/TeamReducers.js b/app/javascript/src/components/reducers/TeamReducers.js
index ac889c627..34ff7566c 100644
--- a/app/javascript/src/components/reducers/TeamReducers.js
+++ b/app/javascript/src/components/reducers/TeamReducers.js
@@ -1,7 +1,6 @@
import {
SET_CURRENT_TEAM,
- GET_LIST_OF_TEAMS,
- SHOW_LEAVE_TEAM_MODAL
+ GET_LIST_OF_TEAMS
} from "../../config/action_types";
export const setCurrentTeam = (
@@ -23,13 +22,3 @@ export const getListOfTeams = (state = { collection: [] }, action) => {
}
return state;
};
-
-export const showLeaveTeamModal = (
- state = { show: false, team: { id: 0, name: "", user_team_id: 0 } },
- action
-) => {
- if (action.type === SHOW_LEAVE_TEAM_MODAL) {
- return { ...state, ...action.payload };
- }
- return state;
-};
diff --git a/app/javascript/src/config/action_types.js b/app/javascript/src/config/action_types.js
index 2ae8f4162..a3536e9ad 100644
--- a/app/javascript/src/config/action_types.js
+++ b/app/javascript/src/config/action_types.js
@@ -1,20 +1,18 @@
+// @flow
+
// teams
-export const SET_CURRENT_TEAM = "SET_CURRENT_TEAM";
-export const GET_LIST_OF_TEAMS = "GET_LIST_OF_TEAMS";
-export const SET_TEAM_DETAILS = "SET_TEAM_DETAILS";
+export const SET_CURRENT_TEAM: string = "SET_CURRENT_TEAM";
+export const GET_LIST_OF_TEAMS: string = "GET_LIST_OF_TEAMS";
+export const SET_TEAM_DETAILS: string = "SET_TEAM_DETAILS";
// users
-export const USER_LOGOUT = "USER_LOGOUT";
-export const SET_CURRENT_USER = "SET_CURRENT_USER";
+export const USER_LOGOUT: string = "USER_LOGOUT";
+export const SET_CURRENT_USER: string = "SET_CURRENT_USER";
// user teams
-export const LEAVE_TEAM = "LEAVE_TEAM";
-
-// modals
-export const SHOW_LEAVE_TEAM_MODAL = "SHOW_LEAVE_TEAM_MODAL";
-export const UPDATE_TEAM_DESCRIPTION_MODAL = "UPDATE_TEAM_DESCRIPTION_MODAL";
+export const LEAVE_TEAM: string = "LEAVE_TEAM";
// alerts
-export const ADD_ALERT = "ADD_ALERT";
-export const CLEAR_ALERT = "CLEAR_ALERT";
-export const CLEAR_ALL_ALERTS = "CLEAR_ALL_ALERTS";
+export const ADD_ALERT: string = "ADD_ALERT";
+export const CLEAR_ALERT: string = "CLEAR_ALERT";
+export const CLEAR_ALL_ALERTS: string = "CLEAR_ALL_ALERTS";
diff --git a/app/javascript/src/config/api_endpoints.js b/app/javascript/src/config/api_endpoints.js
deleted file mode 100644
index b760af418..000000000
--- a/app/javascript/src/config/api_endpoints.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// settings
-export const SETTINGS_PATH = "/settings";
-export const SETTINGS_ACCOUNT_PATH = "/settings/account";
-// teams
-export const TEAMS_PATH = "/client_api/teams";
-export const CHANGE_TEAM_PATH = "/client_api/teams/change_team";
-export const TEAM_DETAILS_PATH = "/client_api/teams/:team_id/details";
-export const TEAM_UPDATE_PATH = "/client_api/teams/update";
-
-// search
-export const SEARCH_PATH = "/search";
-
-// notifications
-export const RECENT_NOTIFICATIONS_PATH = "/client_api/recent_notifications";
-// info dropdown_title
-export const CUSTOMER_SUPPORT_LINK = "http://scinote.net/support";
-export const TUTORIALS_LINK = "http://scinote.net/product/tutorials/";
-export const RELEASE_NOTES_LINK = "http://scinote.net/docs/release-notes/";
-export const PREMIUM_LINK = "http://scinote.net/premium/";
-export const CONTACT_US_LINK =
- "http://scinote.net/story-of-scinote/#contact-scinote";
-
-// user teams
-export const LEAVE_TEAM_PATH = "/client_api/users/leave_team";
-
-// settings
-export const SETTINGS_TEAMS = "/settings/teams";
diff --git a/app/javascript/src/config/axios.js b/app/javascript/src/config/axios.js
deleted file mode 100644
index b514b7001..000000000
--- a/app/javascript/src/config/axios.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// @TODO remove this file ASAP the preferences/profile refactoring is merged
-import axios from "axios";
-import store from "./store";
-import { SIGN_IN_PATH } from "./routes";
-import { destroyState } from "../components/actions/UsersActions";
-
-export default axios.create({
- withCredentials: true,
- headers: {
- "X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').content
- },
- validateStatus(status) {
- if (status === 401) {
- store.dispatch(destroyState);
- window.location = SIGN_IN_PATH;
- }
- return status >= 200 && status < 300;
- }
-});
diff --git a/app/javascript/src/config/reducers.js b/app/javascript/src/config/reducers.js
index 1f7cbc866..075aa2e18 100644
--- a/app/javascript/src/config/reducers.js
+++ b/app/javascript/src/config/reducers.js
@@ -2,8 +2,7 @@ import { combineReducers } from "redux";
import { USER_LOGOUT } from "./action_types";
import {
setCurrentTeam,
- getListOfTeams,
- showLeaveTeamModal
+ getListOfTeams
} from "../components/reducers/TeamReducers";
import { currentUser } from "../components/reducers/UsersReducer";
import { alerts } from "../components/reducers/AlertsReducers";
@@ -12,7 +11,6 @@ const appReducer = combineReducers({
current_team: setCurrentTeam,
all_teams: getListOfTeams,
current_user: currentUser,
- showLeaveTeamModal,
alerts
});
diff --git a/app/javascript/src/config/routes.js b/app/javascript/src/config/routes.js
index 74abccff0..a46097b54 100644
--- a/app/javascript/src/config/routes.js
+++ b/app/javascript/src/config/routes.js
@@ -2,8 +2,21 @@ export const ROOT_PATH = "/";
export const SIGN_IN_PATH = "/users/sign_in";
// Settings page
+export const SETTINGS_PATH = "/settings";
export const SETTINGS_TEAMS_ROUTE = "/settings/teams";
export const SETTINGS_TEAM_ROUTE = "/settings/teams/:id";
export const SETTINGS_NEW_TEAM_ROUTE = "/settings/teams/new";
export const SETTINGS_ACCOUNT_PROFILE = "/settings/account/profile";
export const SETTINGS_ACCOUNT_PREFERENCES = "/settings/account/preferences";
+
+// search
+export const SEARCH_PATH = "/search";
+
+
+// info dropdown_title
+export const CUSTOMER_SUPPORT_LINK = "http://scinote.net/support";
+export const TUTORIALS_LINK = "http://scinote.net/product/tutorials/";
+export const RELEASE_NOTES_LINK = "http://scinote.net/docs/release-notes/";
+export const PREMIUM_LINK = "http://scinote.net/premium/";
+export const CONTACT_US_LINK =
+ "http://scinote.net/story-of-scinote/#contact-scinote";
diff --git a/app/javascript/src/index.jsx b/app/javascript/src/index.jsx
index 19e7725f6..335cae4bb 100644
--- a/app/javascript/src/index.jsx
+++ b/app/javascript/src/index.jsx
@@ -9,7 +9,6 @@ import messages from "./config/locales/messages";
import store from "./config/store";
import AlertsContainer from "./components/AlertsContainer";
-import ModalsContainer from "./components/ModalsContainer";
import SettingsPage from "./scenes/SettingsPage";
import Navigation from "./components/Navigation";
@@ -34,7 +33,6 @@ const ScinoteApp = () =>
-
;
diff --git a/app/javascript/src/scenes/SettingsPage/index.jsx b/app/javascript/src/scenes/SettingsPage/index.jsx
index 8125b54ad..82f300155 100644
--- a/app/javascript/src/scenes/SettingsPage/index.jsx
+++ b/app/javascript/src/scenes/SettingsPage/index.jsx
@@ -7,6 +7,7 @@ import { FormattedMessage } from "react-intl";
import {
ROOT_PATH,
+ SETTINGS_PATH,
SETTINGS_TEAMS_ROUTE,
SETTINGS_TEAM_ROUTE,
SETTINGS_ACCOUNT_PROFILE,
@@ -14,8 +15,6 @@ import {
SETTINGS_NEW_TEAM_ROUTE
} from "../../config/routes";
-import { SETTINGS_PATH, SETTINGS_TEAMS } from "../../config/api_endpoints";
-
import PageTitle from "../../components/PageTitle";
import NotFound from "../../components/404/NotFound";
import SettingsProfile from "./scenes/profile";
@@ -74,7 +73,7 @@ export default class SettingsPage extends Component<*, State> {
diff --git a/app/javascript/src/scenes/SettingsPage/scenes/profile/components/InputEnabled.jsx b/app/javascript/src/scenes/SettingsPage/scenes/profile/components/InputEnabled.jsx
index aebda3857..a4c0b7704 100644
--- a/app/javascript/src/scenes/SettingsPage/scenes/profile/components/InputEnabled.jsx
+++ b/app/javascript/src/scenes/SettingsPage/scenes/profile/components/InputEnabled.jsx
@@ -9,8 +9,8 @@ import {
ButtonToolbar,
} from "react-bootstrap";
import update from "immutability-helper";
-import { updateUser } from "../../../../../services/api/users_api";
import { transformName } from "../../../../../services/helpers/string_helper";
+import { updateUser } from "../../../../../services/api/users_api";
import { addAlert } from "../../../../../components/actions/AlertsActions";
import {
@@ -259,6 +259,7 @@ class InputEnabled extends Component {
return (
{
+ constructor(props: Props) {
super(props);
this.state = { description: "" };
- this.onCloseModal = this.onCloseModal.bind(this);
- this.updateDescription = this.updateDescription.bind(this);
- this.handleDescription = this.handleDescription.bind(this);
+ (this: any).onCloseModal = this.onCloseModal.bind(this);
+ (this: any).updateDescription = this.updateDescription.bind(this);
+ (this: any).handleDescription = this.handleDescription.bind(this);
}
- onCloseModal() {
- this.setState({ description: "" });
+ onCloseModal(): void {
+ (this: any).setState({ description: "" });
this.props.hideModal();
}
- handleDescription(el) {
- this.setState({ description: el.target.value });
+ handleDescription(e: SyntheticInputEvent): void {
+ (this: any).setState({ description: e.target.value });
}
- updateDescription() {
- axios({
- method: "post",
- url: TEAM_UPDATE_PATH,
- withCredentials: true,
- data: {
- team_id: this.props.team.id,
- team: { description: this.state.description }
- }
- })
+ updateDescription(): void {
+ updateTeam(this.props.team.id, { description: this.state.description })
.then(response => {
- this.props.updateTeamCallback(response.data.team);
+ this.props.updateTeamCallback(response);
this.onCloseModal();
})
- .catch(error => this.setState({ errorMessage: error.message }));
+ .catch(error => {
+ (this: any).form.setErrorsForTag('description', [error.message])
+ });
}
- render() {
+ render(): Node {
return (
- { this.form = f; }}>
+ {
+ (this: any).form = f;
+ }}
+ >
@@ -98,14 +104,4 @@ class UpdateTeamDescriptionModal extends Component {
}
}
-UpdateTeamDescriptionModal.propTypes = {
- showModal: bool.isRequired,
- hideModal: func.isRequired,
- team: PropTypes.shape({
- id: number.isRequired,
- description: string
- }).isRequired,
- updateTeamCallback: func.isRequired
-};
-
export default UpdateTeamDescriptionModal;
diff --git a/app/javascript/src/scenes/SettingsPage/scenes/team/components/UpdateTeamNameModal.jsx b/app/javascript/src/scenes/SettingsPage/scenes/team/components/UpdateTeamNameModal.jsx
index 6e18cfb24..a82da272c 100644
--- a/app/javascript/src/scenes/SettingsPage/scenes/team/components/UpdateTeamNameModal.jsx
+++ b/app/javascript/src/scenes/SettingsPage/scenes/team/components/UpdateTeamNameModal.jsx
@@ -1,13 +1,8 @@
+// @flow
import React, { Component } from "react";
-import PropTypes, { bool, number, string, func } from "prop-types";
-import {
- Modal,
- Button,
- ControlLabel,
- FormControl,
-} from "react-bootstrap";
+import type { Node } from "react";
+import { Modal, Button, ControlLabel, FormControl } from "react-bootstrap";
import { FormattedMessage } from "react-intl";
-import axios from "../../../../../config/axios";
import {
ValidatedForm,
ValidatedFormGroup,
@@ -15,53 +10,62 @@ import {
ValidatedErrorHelpBlock,
ValidatedSubmitButton
} from "../../../../../components/validation";
-import {
- nameLengthValidator
-} from "../../../../../components/validation/validators/text";
+import { nameLengthValidator } from "../../../../../components/validation/validators/text";
+import { updateTeam } from "../../../../../services/api/teams_api";
-import { TEAM_UPDATE_PATH } from "../../../../../config/api_endpoints";
+type Team = {
+ id: number,
+ name: string
+};
-class UpdateTeamNameModal extends Component {
- constructor(props) {
+type State = {
+ name: string
+};
+
+type Props = {
+ showModal: boolean,
+ hideModal: Function,
+ team: Team,
+ updateTeamCallback: Function
+};
+
+class UpdateTeamNameModal extends Component {
+ constructor(props: Props) {
super(props);
this.state = { name: props.team.name };
- this.onCloseModal = this.onCloseModal.bind(this);
- this.updateName = this.updateName.bind(this);
- this.handleName = this.handleName.bind(this);
+ (this: any).onCloseModal = this.onCloseModal.bind(this);
+ (this: any).updateName = this.updateName.bind(this);
+ (this: any).handleName = this.handleName.bind(this);
}
- onCloseModal() {
- this.setState({ name: "" });
+ onCloseModal(): void {
+ (this: any).setState({ name: "" });
this.props.hideModal();
}
- handleName(e) {
- this.setState({ name: e.target.value });
+ handleName(e: SyntheticInputEvent): void {
+ (this: any).setState({ name: e.target.value });
}
- updateName() {
- axios({
- method: "post",
- url: TEAM_UPDATE_PATH,
- withCredentials: true,
- data: {
- team_id: this.props.team.id,
- team: { name: this.state.name }
- }
- })
+ updateName(): void {
+ updateTeam(this.props.team.id, { name: this.state.name })
.then(response => {
- this.props.updateTeamCallback(response.data.team);
+ this.props.updateTeamCallback(response);
this.onCloseModal();
})
.catch(error => {
- this.form.setErrorsForTag("name", [error.message]);
+ (this: any).form.setErrorsForTag("name", [error.message]);
});
}
- render() {
+ render(): Node {
return (
- { this.form = f; }}>
+ {
+ (this: any).form = f;
+ }}
+ >
@@ -84,10 +88,7 @@ class UpdateTeamNameModal extends Component {
-
+