Merge branch 'decoupling-settings-page' of https://github.com/biosistemika/scinote-web into zd_SCI_1731

This commit is contained in:
zmagod 2017-11-03 09:56:44 +01:00
commit 5bc38414d1
52 changed files with 8642 additions and 937 deletions

View file

@ -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

View file

@ -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) => (
<DropdownButton
bsStyle={"primary"}
title={<FormattedMessage id="invite_users.dropdown_button.invite" />}
id="invite_users.submit_button"
disabled={status}
>
<MenuItem onClick={() => handleClick("guest")}>
<FormattedMessage id="invite_users.dropdown_button.guest" />
</MenuItem>
<MenuItem onClick={() => handleClick("normal_user")}>
<FormattedMessage id="invite_users.dropdown_button.normal_user" />
</MenuItem>
<MenuItem onClick={() => handleClick("admin")}>
<FormattedMessage id="invite_users.dropdown_button.admin" />
</MenuItem>
</DropdownButton>
);
const InviteUsersButton = ({ handleClick, status }: Props) => {
return (
<DropdownButton
bsStyle="primary"
title={<FormattedMessage id="invite_users.dropdown_button.invite" />}
id="invite_users.submit_button"
disabled={status}
>
<MenuItem onClick={() => handleClick("guest")}>
<FormattedMessage id="invite_users.dropdown_button.guest" />
</MenuItem>
<MenuItem onClick={() => handleClick("normal_user")}>
<FormattedMessage id="invite_users.dropdown_button.normal_user" />
</MenuItem>
<MenuItem onClick={() => handleClick("admin")}>
<FormattedMessage id="invite_users.dropdown_button.admin" />
</MenuItem>
</DropdownButton>
);
};
export default InviteUsersButton;

View file

@ -77,7 +77,8 @@ class InviteUsersModal extends Component<Props, State> {
.then(response => {
(this: any).setState({
inviteResults: response,
showInviteUsersResults: true
showInviteUsersResults: true,
inviteUserButtonDisabled: true
});
})
.catch(error => {

View file

@ -1,7 +0,0 @@
import React from "react";
import LeaveTeamModal from "./modals/LeaveTeamModal";
export default () =>
<div>
<LeaveTeamModal />
</div>;

View file

@ -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<Teams$Team>): 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 => {

View file

@ -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;
};

View file

@ -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";

View file

@ -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";

View file

@ -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;
}
});

View file

@ -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
});

View file

@ -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";

View file

@ -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 = () =>
</ContentWrapper>
</div>
</BrowserRouter>
<ModalsContainer />
</div>
</IntlProvider>
</Provider>;

View file

@ -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> {
</NavItem>
</LinkContainer>
<LinkContainer
to={SETTINGS_TEAMS}
to={SETTINGS_TEAMS_ROUTE}
active={this.state.active === "2"}
>
<NavItem eventKey="2">

View file

@ -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 (
<ValidatedFormGroup tag={dataField}>
<ValidatedFormControl
id={transformName(this.props.labelTitle)}
tag={dataField}
type={this.props.inputType}
onChange={this.handleChange}

View file

@ -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,51 +10,62 @@ import {
ValidatedErrorHelpBlock,
ValidatedSubmitButton
} from "../../../../../components/validation";
import {
textMaxLengthValidator
} from "../../../../../components/validation/validators/text";
import { textMaxLengthValidator } from "../../../../../components/validation/validators/text";
import { updateTeam } from "../../../../../services/api/teams_api";
import { TEAM_UPDATE_PATH } from "../../../../../config/api_endpoints";
type Team = {
id: number,
description: string
};
class UpdateTeamDescriptionModal extends Component {
constructor(props) {
type Props = {
showModal: boolean,
hideModal: Function,
team: Team,
updateTeamCallback: Function
};
type State = {
description: string
};
class UpdateTeamDescriptionModal extends Component<Props, State> {
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<HTMLInputElement>): 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 (
<Modal show={this.props.showModal} onHide={this.onCloseModal}>
<ValidatedForm ref={(f) => { this.form = f; }}>
<ValidatedForm
ref={f => {
(this: any).form = f;
}}
>
<Modal.Header closeButton>
<Modal.Title>
<FormattedMessage id="settings_page.update_team_description_modal.title" />
@ -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;

View file

@ -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<Props, State> {
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<HTMLInputElement>): 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 (
<Modal show={this.props.showModal} onHide={this.onCloseModal}>
<ValidatedForm ref={(f) => { this.form = f; }}>
<ValidatedForm
ref={f => {
(this: any).form = f;
}}
>
<Modal.Header closeButton>
<Modal.Title>
<FormattedMessage id="settings_page.update_team_name_modal.title" />
@ -84,10 +88,7 @@ class UpdateTeamNameModal extends Component {
</ValidatedFormGroup>
</Modal.Body>
<Modal.Footer>
<ValidatedSubmitButton
onClick={this.updateName}
bsStyle="primary"
>
<ValidatedSubmitButton onClick={this.updateName} bsStyle="primary">
<FormattedMessage id="general.update" />
</ValidatedSubmitButton>
<Button onClick={this.onCloseModal}>
@ -100,14 +101,4 @@ class UpdateTeamNameModal extends Component {
}
}
UpdateTeamNameModal.propTypes = {
showModal: bool.isRequired,
hideModal: func.isRequired,
team: PropTypes.shape({
id: number.isRequired,
name: string
}).isRequired,
updateTeamCallback: func.isRequired
};
export default UpdateTeamNameModal;

View file

@ -1,48 +1,58 @@
// @flow
import React, { Component } from "react";
import PropTypes, { bool, number, string, func } from "prop-types";
import type { Node } from "react";
import { Modal, Button, Alert, Glyphicon } from "react-bootstrap";
import { FormattedMessage, FormattedHTMLMessage } from "react-intl";
import { connect } from "react-redux";
import axios from "../../../config/axios";
import { leaveTeam } from "../../../../../services/api/teams_api";
import { LEAVE_TEAM_PATH } from "../../../config/api_endpoints";
import {
addTeamsData,
setCurrentTeam,
leaveTeamModalShow
} from "../../actions/TeamsActions";
setCurrentTeam
} from "../../../../../components/actions/TeamsActions";
class LeaveTeamModal extends Component {
constructor(props) {
type Team = {
id: number,
name: string,
user_team_id: number
};
type Props = {
updateTeamsState: Function,
showModal: boolean,
team: Team,
addTeamsData: Function,
hideLeaveTeamModal: Function,
setCurrentTeam: Function
};
class LeaveTeamModal extends Component<Props> {
constructor(props: Props) {
super(props);
this.onCloseModal = this.onCloseModal.bind(this);
this.leaveTeam = this.leaveTeam.bind(this);
(this: any).onCloseModal = this.onCloseModal.bind(this);
(this: any).leaveTeam = this.leaveTeam.bind(this);
}
onCloseModal() {
this.props.leaveTeamModalShow(false);
onCloseModal(): void {
this.props.hideLeaveTeamModal();
}
leaveTeam() {
const teamUrl = `${LEAVE_TEAM_PATH}?team=${this.props.team
.id}&user_team=${this.props.team.user_team_id}`;
axios
.delete(teamUrl, {
withCredentials: true
})
leaveTeam(): void {
const { id, user_team_id } = this.props.team;
leaveTeam(id, user_team_id)
.then(response => {
const teams = response.data.teams.collection;
const { teams, currentTeam } = response;
this.props.updateTeamsState(teams);
this.props.addTeamsData(teams);
const currentTeam = _.find(teams, team => team.current_team);
this.props.setCurrentTeam(currentTeam);
})
.catch(error => {
console.log("error: ", error.response.data.message);
});
this.props.leaveTeamModalShow(false);
this.props.hideLeaveTeamModal();
}
render() {
render(): Node {
return (
<Modal show={this.props.showModal} onHide={this.onCloseModal}>
<Modal.Header closeButton>
@ -89,25 +99,7 @@ class LeaveTeamModal extends Component {
}
}
LeaveTeamModal.propTypes = {
showModal: bool.isRequired,
team: PropTypes.shape({
id: number.isRequired,
name: string.isRequired,
user_team_id: number.isRequired
}).isRequired,
addTeamsData: func.isRequired,
leaveTeamModalShow: func.isRequired,
setCurrentTeam: func.isRequired
};
const mapStateToProps = ({ showLeaveTeamModal }) => ({
showModal: showLeaveTeamModal.show,
team: showLeaveTeamModal.team
});
export default connect(mapStateToProps, {
leaveTeamModalShow,
export default connect(null, {
addTeamsData,
setCurrentTeam
})(LeaveTeamModal);

View file

@ -1,28 +1,61 @@
// @flow
import React, { Component } from "react";
import PropTypes, { func, number, string, bool } from "prop-types";
import { connect } from "react-redux";
import type { Node } from "react";
import type { Teams$Team } from "flow-typed";
import { Button } from "react-bootstrap";
import { Link } from "react-router-dom";
import { FormattedMessage } from "react-intl";
import { leaveTeamModalShow } from "../../../../../components/actions/TeamsActions";
import DataTable from "../../../../../components/data_table";
import { SETTINGS_TEAMS_ROUTE } from "../../../../../config/routes";
import LeaveTeamModal from "./LeaveTeamModal";
class TeamsDataTable extends Component {
constructor(props) {
const DefaultTeam = {
id: 0,
name: "",
current_team: false,
user_team_id: 0,
role: "",
members: 0,
can_be_left: false
};
type Props = {
updateTeamsState: Function,
teams: Array<Teams$Team>
}
type State = {
leaveTeamModalShow: boolean,
team: Teams$Team
}
class TeamsDataTable extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.leaveTeamModal = this.leaveTeamModal.bind(this);
this.leaveTeamButton = this.leaveTeamButton.bind(this);
this.linkToTeam = this.linkToTeam.bind(this);
this.state = {
leaveTeamModalShow: false,
team: DefaultTeam
};
(this: any).leaveTeamModal = this.leaveTeamModal.bind(this);
(this: any).leaveTeamButton = this.leaveTeamButton.bind(this);
(this: any).linkToTeam = this.linkToTeam.bind(this);
(this: any).hideLeaveTeamModal = this.hideLeaveTeamModal.bind(this);
}
leaveTeamModal(e, team) {
this.props.leaveTeamModalShow(true, team);
leaveTeamModal(e: string, team: Teams$Team): void {
(this: any).setState({ leaveTeamModalShow: true, team });
}
leaveTeamButton(id, team) {
if (team.can_be_leaved) {
hideLeaveTeamModal(): void {
(this: any).setState({ leaveTeamModalShow: false, team: DefaultTeam });
}
linkToTeam(name: string, team: Teams$Team): Node {
return <Link to={`${SETTINGS_TEAMS_ROUTE}/${team.id}`}>{name}</Link>;
}
leaveTeamButton(id: string, team: Teams$Team): Node {
if (team.can_be_left) {
return (
<Button onClick={e => this.leaveTeamModal(e, team)}>
<FormattedMessage id="settings_page.leave_team" />
@ -36,11 +69,7 @@ class TeamsDataTable extends Component {
);
}
linkToTeam(name, row) {
return <Link to={`${SETTINGS_TEAMS_ROUTE}/${row.id}`}>{name}</Link>;
}
render() {
render(): Node {
const options = {
defaultSortName: "name",
defaultSortOrder: "desc",
@ -90,28 +119,22 @@ class TeamsDataTable extends Component {
}
];
return (
<DataTable
data={this.props.teams}
columns={columns}
pagination
options={options}
/>
<div>
<DataTable
data={this.props.teams}
columns={columns}
pagination
options={options}
/>
<LeaveTeamModal
updateTeamsState={this.props.updateTeamsState}
showModal={this.state.leaveTeamModalShow}
team={this.state.team}
hideLeaveTeamModal={this.hideLeaveTeamModal}
/>
</div>
);
}
}
TeamsDataTable.propTypes = {
leaveTeamModalShow: func.isRequired,
teams: PropTypes.arrayOf(
PropTypes.shape({
id: number.isRequired,
name: string.isRequired,
current_team: bool.isRequired,
role: string.isRequired,
members: number.isRequired,
can_be_leaved: bool.isRequired
}).isRequired
)
};
export default connect(null, { leaveTeamModalShow })(TeamsDataTable);
export default TeamsDataTable;

View file

@ -47,7 +47,7 @@ TeamsPageDetails.propTypes = {
current_team: bool.isRequired,
role: string.isRequired,
members: number.isRequired,
can_be_leaved: bool.isRequired
can_be_left: bool.isRequired
})
)
};

View file

@ -3,11 +3,8 @@
import React, { Component } from "react";
import styled from "styled-components";
import { Breadcrumb } from "react-bootstrap";
import { connect } from "react-redux";
import { FormattedMessage } from "react-intl";
import type { State } from "flow-typed";
import type { MapStateToProps } from "react-redux";
import { getTeams } from "../../../../services/api/teams_api";
import { BORDER_LIGHT_COLOR } from "../../../../config/constants/colors";
import PageTitle from "../../../../components/PageTitle";
@ -24,22 +21,44 @@ const Wrapper = styled.div`
`;
type Props = {
tabState: Function,
tabState: Function
};
type State = {
teams: Array<Teams$Team>
};
class SettingsTeams extends Component<Props> {
static defaultProps = {
teams: [{ id: 0, name: "", current_team: "", role: "", members: 0 }]
};
class SettingsTeams extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
teams: [
{
id: 0,
name: "",
current_team: true,
role: "",
members: 0,
can_be_left: false
}
]
};
(this: any).updateTeamsState = this.updateTeamsState.bind(this);
}
componentDidMount() {
getTeams().then(({ teams }) => {
this.updateTeamsState(teams);
});
// set team tab on active
this.props.tabState("2");
}
updateTeamsState(teams: Array<Teams$Team>): void {
this.setState({ teams });
}
render() {
const { teams } = this.props;
return (
<PageTitle localeID="page_title.all_teams_page">
<Wrapper>
@ -48,16 +67,15 @@ class SettingsTeams extends Component<Props> {
<FormattedMessage id="settings_page.all_teams" />
</Breadcrumb.Item>
</Breadcrumb>
<TeamsPageDetails teams={teams} />
<TeamsDataTable teams={teams} />
<TeamsPageDetails teams={this.state.teams} />
<TeamsDataTable
teams={this.state.teams}
updateTeamsState={this.updateTeamsState}
/>
</Wrapper>
</PageTitle>
);
}
}
const mapStateToProps: MapStateToProps<*, *, *> = (state: State) => ({
teams: state.all_teams.collection
});
export default connect(mapStateToProps)(SettingsTeams);
export default SettingsTeams;

View file

@ -1,5 +1,5 @@
// @flow
import { axiosInstance } from "./config";
import axiosInstance from "./config";
import { ACTIVITIES_PATH } from "./endpoints";
export function getActivities(

View file

@ -3,7 +3,10 @@ import store from "../../config/store";
import { SIGN_IN_PATH } from "../../config/routes";
import { destroyState } from "../../components/actions/UsersActions";
export const axiosInstance = axios.create({
// estimate time react component needs to rerender after state refresh
const TimeDelay = 500;
const axiosInstance = axios.create({
withCredentials: true,
headers: {
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').content
@ -13,8 +16,33 @@ export const axiosInstance = axios.create({
setTimeout(() => {
store.dispatch(destroyState)
window.location = SIGN_IN_PATH;
}, 500);
}, TimeDelay);
}
return status >= 200 && status < 300;
}
});
// Set global IN_REQUEST variable needed for wait_for_ajax function in cucumber tests
axiosInstance.interceptors.request.use((config) => {
window.IN_REQUEST = true;
return config;
}, (error) => {
setTimeout(() => {
window.IN_REQUEST = false;
}, TimeDelay)
return Promise.reject(error);
});
axiosInstance.interceptors.response.use((response) => {
setTimeout(() => {
window.IN_REQUEST = false;
}, TimeDelay)
return response;
}, (error) => {
setTimeout(() => {
window.IN_REQUEST = false;
}, TimeDelay)
return Promise.reject(error);
});
export default axiosInstance;

View file

@ -6,9 +6,6 @@ export const UNREADED_NOTIFICATIONS_PATH =
// activities
export const ACTIVITIES_PATH = "/client_api/activities";
// 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";
@ -16,9 +13,6 @@ export const TEAM_DETAILS_PATH = "/client_api/teams/:team_id/details";
export const TEAM_UPDATE_PATH = "/client_api/teams/update";
export const CURRENT_USER_PATH = "/client_api/current_user_info"
// search
export const SEARCH_PATH = "/search";
// users
export const USER_PROFILE_INFO = "/client_api/users/profile_info";
export const UPDATE_USER_PATH = "/client_api/users/update";

View file

@ -1,4 +1,4 @@
import { axiosInstance } from "./config";
import axiosInstance from "./config";
import {
RECENT_NOTIFICATIONS_PATH,
UNREADED_NOTIFICATIONS_PATH

View file

@ -1,12 +1,47 @@
// @flow
import type { NewTeam } from "flow-typed";
import { axiosInstance } from "./config";
import { TEAM_DETAILS_PATH, TEAMS_PATH } from "./endpoints";
import type { Teams$NewTeam, Team$Update } from "flow-typed";
import _ from "lodash";
import axiosInstance from "./config";
import {
TEAM_DETAILS_PATH,
TEAM_UPDATE_PATH,
TEAMS_PATH,
CHANGE_TEAM_PATH,
LEAVE_TEAM_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);
};
export const createNewTeam = (team: NewTeam): Promise<*> =>
export const createNewTeam = (team: Teams$NewTeam): Promise<*> =>
axiosInstance.post(TEAMS_PATH, { team }).then(({ data }) => data);
export const updateTeam = (teamID: number, teamData: Team$Update): Promise<*> =>
axiosInstance
.post(TEAM_UPDATE_PATH, { team_id: teamID, team: teamData })
.then(({ data }) => data.team);
export const getTeams = (): Promise<*> =>
axiosInstance.get(TEAMS_PATH).then(({ data }) => {
const teams = data.teams.collection;
const currentTeam = _.find(teams, team => team.current_team);
return { teams, currentTeam };
});
export const changeCurrentTeam = (teamID: number): Promise<*> =>
axiosInstance.post(CHANGE_TEAM_PATH, { team_id: teamID }).then(({ data }) => {
const teams = data.teams.collection;
const currentTeam = _.find(teams, team => team.current_team);
return { teams, currentTeam };
});
export const leaveTeam = (teamID: number, userTeamID: number): Promise<*> => {
const teamUrl = `${LEAVE_TEAM_PATH}?team=${teamID}&user_team=${userTeamID}`;
return axiosInstance.delete(teamUrl).then(({ data }) => {
const teams = data.teams.collection;
const currentTeam = _.find(teams, team => team.current_team);
return { teams, currentTeam };
});
};

View file

@ -1,6 +1,6 @@
// @flow
import { axiosInstance } from "./config";
import axiosInstance from "./config";
import {
REMOVE_USER_FROM_TEAM_PATH,
INVITE_USERS_PATH,

View file

@ -1,4 +1,4 @@
import { axiosInstance } from "./config";
import axiosInstance from "./config";
import {
USER_PROFILE_INFO,
UPDATE_USER_PATH,

View file

@ -11,7 +11,8 @@ module ClientApi
unless @role && UserTeam.roles.keys.include?(@role) &&
@emails && @emails.present?
raise ClientApi::CustomInvitationsError
raise ClientApi::CustomInvitationsError,
I18n.t('client_api.invalid_arguments')
end
@emails = @emails.map(&:downcase)
end

View file

@ -4,7 +4,7 @@ json.teams do
json.name team.name
json.members team.members
json.role retrive_role_name(team.role)
json.can_be_leaved team.can_be_leaved
json.can_be_left team.can_be_left
json.user_team_id team.user_team_id
end
end

View file

@ -6,8 +6,8 @@ json.team_users team_users do |team_user|
json.created_at I18n.l(team_user.created_at, format: :full_date)
json.status team_user.user.active_status_str
json.actions do
json.current_role team_user.role_str
json.team_user_id team_user.id
json.currentRole team_user.role_str
json.teamUserId team_user.id
json.disable team_user.user == current_user
end
end

View file

@ -6,6 +6,6 @@ json.teams do
json.members team.fetch('members')
json.role json.role retrive_role_name(team.fetch('role') { nil })
json.current_team team.fetch('current_team')
json.can_be_leaved team.fetch('can_be_leaved')
json.can_be_left team.fetch('can_be_left')
end
end

View file

@ -17,5 +17,10 @@
</noscript>
<div id="root"></div>
<%= yield %>
<script>
// GLOBALS
window.IN_REQUEST = false;
</script>
</body>
</html>

View file

@ -1817,6 +1817,7 @@ en:
by: 'by'
client_api:
invalid_arguments: "Invalid arguments"
generic_error_message: "Something went wrong! Please try again later."
user_teams:
leave_team_error: "An error occured."

View file

@ -11,7 +11,7 @@ Background:
And "nonadmin@myorg.com" is in "BioSistemika Process" team as a "normal_user"
And is signed in with "nonadmin@myorg.com", "mypassword1234"
@compile @javascript
@javascript
Scenario: Successful navigate to profile page
Given I'm on the home page of "BioSistemika Process" team
And I click on Avatar
@ -23,7 +23,6 @@ Scenario: Unsuccessful avatar image upload, file is too big
Given I'm on the profile page
Then I click on image within ".avatar-container" element
And I attach a "Moon.png" file to "user_avatar_input" field
Then I click "Update" button
And I should see "file too large (maximum size is 0.2 MB)" error message under "user_avatar_input" field
@javascript
@ -31,7 +30,6 @@ Scenario: Unsuccessful avatar image upload, file is invalid
Given I'm on the profile page
Then I click on image within ".avatar-container" element
And I attach a "File.txt" file to "user_avatar_input" field
Then I click "Update" button
And I should see "invalid file extension" error message under "user_avatar_input" field
@javascript
@ -39,7 +37,7 @@ Scenario: Successful upload avatar image
Given I'm on the profile page
Then I click on image within ".avatar-container" element
And I attach a "Star.png" file to "user_avatar_input" field
Then I click "Update" button
Then I click "Upload" button
And I should see "Your account has been updated successfully" flash message
@javascript
@ -55,7 +53,6 @@ Scenario: Unsuccessfully changes user initials, text is too long
Given I'm on the profile page
Then I click on Edit on "settings_page.initials" input field
And I fill in "KNOCK" in "settings_page.initials" input field
Then I click "Update" button
And I should see "is too long (maximum is 4 characters)" error message under "settings_page.initials" field
@javascript
@ -69,11 +66,11 @@ Scenario: Successfully changes user initials
@javascript
Scenario: Successfully changes user email
Given I'm on the profile page
Then I click on Edit on "settings_page.new_email" input field
Then I click on Edit on "settings_page.email" input field
And I change "nonadmin@myorg.com" with "user@myorg.com" email
And I fill in "mypassword1234" in Current password field
Then I click "Update" button
And I should see "user@myorg.com" in "settings_page.new_email" input field
And I should see "user@myorg.com" in "settings_page.email" input field
@javascript
Scenario: Unsuccessful Password Change, password is too short
@ -82,7 +79,6 @@ Scenario: Unsuccessful Password Change, password is too short
And I fill in "mypassword1234" in Current password field
And I fill in "mypass" in New password field
And I fill in "mypass" in New password confirmation field
Then I click "Update" button
And I should see "is too short (minimum is 8 characters)"
@javascript
@ -92,7 +88,6 @@ Scenario: Unsuccessful Password Change, passwords does not match
And I fill in "mypassword1234" in Current password field
And I fill in "mypassword5678" in New password field
And I fill in "mypassword56788" in New password confirmation field
Then I click "Update" button
And I should see "doesn't match"
@javascript

View file

@ -11,18 +11,19 @@ Then(/^I click on Browse button$/) do
end
Then(/^I change "([^"]*)" with "([^"]*)" email$/) do |prev_email, new_email|
find(:xpath, "//input[@value='#{prev_email}']").set(new_email)
wait_for_ajax
find(:css, "input[value='#{prev_email}']").set(new_email)
end
Then(/^I fill in "([^"]*)" in Current password field$/) do |password|
find(:xpath, '//input[@id="settings_page.current_password"]').set(password)
find(:css, 'input[id="settings_page.current_password"]').set(password)
end
Then(/^I fill in "([^"]*)" in New password field$/) do |password|
find(:xpath, '//input[@id="settings_page.new_password"]').set(password)
find(:css, 'input[id="settings_page.new_password"]').set(password)
end
Then(/^I fill in "([^"]*)" in New password confirmation field$/) do |password|
find(:xpath,
'//input[@id="settings_page.new_password_confirmation"]').set(password)
find(:css,
'input[id="settings_page.new_password_confirmation"]').set(password)
end

View file

@ -1,5 +1,5 @@
When(/^I click "(.+)" button$/) do |button|
click_on button
click_on(button)
end
Given(/^Show me the page$/) do
@ -21,6 +21,7 @@ Given(/^I click "(.+)" link within "(.+)"$/) do |link, element|
end
Then(/^I should see "(.+)"$/) do |text|
wait_for_ajax
expect(page).to have_content(text)
end
@ -47,10 +48,14 @@ Given(/^"([^"]*)" is in "([^"]*)" team as a "([^"]*)"$/) do |user_email, team_na
end
Then(/^I attach a "([^"]*)" file to "([^"]*)" field$/) do |file, field_id|
wait_for_ajax
attach_file(field_id, Rails.root.join('features', 'assets', file))
# "expensive" operation needs some time :=)
sleep(0.5)
end
Then(/^I should see "([^"]*)" error message under "([^"]*)" field$/) do |message, field_id|
wait_for_ajax
parent = find_by_id(field_id).first(:xpath, './/..')
expect(parent).to have_content(message)
end
@ -60,25 +65,28 @@ Then(/^I click on "([^"]*)"$/) do |button|
end
Then(/^I click on image within "([^"]*)" element$/) do |container|
sleep 0.5
within(container) do
find('img').click
end
wait_for_ajax
end
Then(/^I should see "([^"]*)" flash message$/) do |message|
wait_for_ajax
expect(find_by_id('alert-flash')).to have_content(message)
end
Then(/^I click on Edit on "([^"]*)" input field$/) do |container_id|
wait_for_ajax
container = page.find_by_id(container_id)
within(container) do
find('button').click
end
end
Then(/^I fill in "([^"]*)" in "([^"]*)" input field$/) do |text, container_id|
container = page.find_by_id(container_id)
container.find('input').set(text)
Then(/^I fill in "([^"]*)" in "([^"]*)" input field$/) do |text, input_id|
page.find_by_id(input_id).set(text)
end
Then(/^I should see "([^"]*)" in "([^"]*)" input field$/) do |text, container_id|

View file

@ -3,6 +3,7 @@
# newer version of cucumber-rails. Consider adding your own code to a new file
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
# files.
ENV['CUCUMBER'] = 'cucumber'
require 'cucumber/rails'
require 'capybara/cucumber'
@ -20,7 +21,7 @@ Capybara::Webkit.configure do |config|
# Allow pages to make requests to any URL without issuing a warning.
config.allow_unknown_urls
# Timeout if requests take longer than 5 seconds
# Timeout if requests take longer than 30 seconds
config.timeout = 30
# Don't raise errors when SSL certificates can't be validated
@ -32,11 +33,18 @@ end
Capybara.javascript_driver = :webkit
Capybara.default_max_wait_time = 30
Capybara.asset_host = 'http://localhost:3001'
Capybara.server_port = 3001
# Precompile webpacker to avoid render bugs in capybara webkit
# global hook throws an error :( https://github.com/cucumber/cucumber/wiki/Hooks
Before('@compile') do
system('NODE_ENV=production bundle exec rails webpacker:compile')
compiled = false
Before do
unless compiled
system('NODE_ENV=production bundle exec rails webpacker:compile')
compiled = true
end
end
# Capybara defaults to CSS3 selectors rather than XPath.
@ -64,6 +72,8 @@ ActionController::Base.allow_rescue = false
# Remove/comment out the lines below if your app doesn't have a database.
# For some databases (like MongoDB and CouchDB) you may need to use :truncation instead.
begin
require 'database_cleaner'
require 'database_cleaner/cucumber'
DatabaseCleaner.strategy = :truncation
rescue NameError
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."

11
features/support/wait.rb Normal file
View file

@ -0,0 +1,11 @@
def wait_for_ajax
counter = 0
while page.evaluate_script('window.IN_REQUEST')
counter += 1
sleep(0.1)
if (0.1 * counter) >= Capybara.default_max_wait_time
raise "AJAX request took longer than " \
"#{Capybara.default_max_wait_time} seconds."
end
end
end

12
flow-typed/action_types.js vendored Normal file
View file

@ -0,0 +1,12 @@
// @flow
import type { Teams$Team } from "flow-typed";
export type Action$AddTeamData = {
payload: Array<Teams$Team>,
type: "GET_LIST_OF_TEAMS"
}
export type Actopm$SetCurrentTeam = {
team: Teams$Team,
action: "SET_CURRENT_TEAM"
}

View file

@ -0,0 +1,32 @@
// flow-typed signature: 94a58ea1333bada1e79278664744bcec
// flow-typed version: <<STUB>>/babel-plugin-transform-react-jsx-source_v^6.22.0/flow_v0.56.0
/**
* This is an autogenerated libdef stub for:
*
* 'babel-plugin-transform-react-jsx-source'
*
* Fill this stub out by replacing all the `any` types.
*
* Once filled out, we encourage you to share your work with the
* community by sending a pull request to:
* https://github.com/flowtype/flow-typed
*/
declare module 'babel-plugin-transform-react-jsx-source' {
declare module.exports: any;
}
/**
* We include stubs for each file inside this npm package in case you need to
* require those files directly. Feel free to delete any files that aren't
* needed.
*/
declare module 'babel-plugin-transform-react-jsx-source/lib/index' {
declare module.exports: any;
}
// Filename aliases
declare module 'babel-plugin-transform-react-jsx-source/lib/index.js' {
declare module.exports: $Exports<'babel-plugin-transform-react-jsx-source/lib/index'>;
}

View file

@ -1,5 +1,5 @@
// flow-typed signature: 7f2ed99d320afda9cbf973047b8b7ef6
// flow-typed version: <<STUB>>/babel-polyfill_v^6.23.0/flow_v0.56.0
// flow-typed signature: 1eab6798ddbdf14d95637c19e547522a
// flow-typed version: <<STUB>>/babel-polyfill_v^6.26.0/flow_v0.56.0
/**
* This is an autogenerated libdef stub for:

137
flow-typed/npm/bootstrap-sass_vx.x.x.js vendored Normal file
View file

@ -0,0 +1,137 @@
// flow-typed signature: 3b2debf5c802e09acb220a975e00957c
// flow-typed version: <<STUB>>/bootstrap-sass_v^3.3.7/flow_v0.56.0
/**
* This is an autogenerated libdef stub for:
*
* 'bootstrap-sass'
*
* Fill this stub out by replacing all the `any` types.
*
* Once filled out, we encourage you to share your work with the
* community by sending a pull request to:
* https://github.com/flowtype/flow-typed
*/
declare module 'bootstrap-sass' {
declare module.exports: any;
}
/**
* We include stubs for each file inside this npm package in case you need to
* require those files directly. Feel free to delete any files that aren't
* needed.
*/
declare module 'bootstrap-sass/assets/javascripts/bootstrap-sprockets' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap.min' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/affix' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/alert' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/button' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/carousel' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/collapse' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/dropdown' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/modal' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/popover' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/scrollspy' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/tab' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/tooltip' {
declare module.exports: any;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/transition' {
declare module.exports: any;
}
declare module 'bootstrap-sass/eyeglass-exports' {
declare module.exports: any;
}
// Filename aliases
declare module 'bootstrap-sass/assets/javascripts/bootstrap-sprockets.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap-sprockets'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap.min.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap.min'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/affix.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/affix'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/alert.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/alert'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/button.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/button'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/carousel.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/carousel'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/collapse.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/collapse'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/dropdown.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/dropdown'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/modal.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/modal'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/popover.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/popover'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/scrollspy.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/scrollspy'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/tab.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/tab'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/tooltip.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/tooltip'>;
}
declare module 'bootstrap-sass/assets/javascripts/bootstrap/transition.js' {
declare module.exports: $Exports<'bootstrap-sass/assets/javascripts/bootstrap/transition'>;
}
declare module 'bootstrap-sass/eyeglass-exports.js' {
declare module.exports: $Exports<'bootstrap-sass/eyeglass-exports'>;
}

18
flow-typed/npm/font-awesome_vx.x.x.js vendored Normal file
View file

@ -0,0 +1,18 @@
// flow-typed signature: c9429fa13146f6e9952156452792cf3a
// flow-typed version: <<STUB>>/font-awesome_v^4.7.0/flow_v0.56.0
/**
* This is an autogenerated libdef stub for:
*
* 'font-awesome'
*
* Fill this stub out by replacing all the `any` types.
*
* Once filled out, we encourage you to share your work with the
* community by sending a pull request to:
* https://github.com/flowtype/flow-typed
*/
declare module 'font-awesome' {
declare module.exports: any;
}

5078
flow-typed/npm/intl_vx.x.x.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,29 +1,29 @@
// flow-typed signature: 793995d08b898744007089d163219dbe
// flow-typed version: 7a7fdd86ed/moment_v2.3.x/flow_>=v0.34.x
// flow-typed signature: a56215e90c2cb9a5f9e106edd857208f
// flow-typed version: 057d3e81b5/moment_v2.3.x/flow_>=v0.34.x
type moment$MomentOptions = {
y?: number|string,
year?: number|string,
years?: number|string,
M?: number|string,
month?: number|string,
months?: number|string,
d?: number|string,
day?: number|string,
days?: number|string,
date?: number|string,
h?: number|string,
hour?: number|string,
hours?: number|string,
m?: number|string,
minute?: number|string,
minutes?: number|string,
s?: number|string,
second?: number|string,
seconds?: number|string,
ms?: number|string,
millisecond?: number|string,
milliseconds?: number|string,
y?: number | string,
year?: number | string,
years?: number | string,
M?: number | string,
month?: number | string,
months?: number | string,
d?: number | string,
day?: number | string,
days?: number | string,
date?: number | string,
h?: number | string,
hour?: number | string,
hours?: number | string,
m?: number | string,
minute?: number | string,
minutes?: number | string,
s?: number | string,
second?: number | string,
seconds?: number | string,
ms?: number | string,
millisecond?: number | string,
milliseconds?: number | string
};
type moment$MomentObject = {
@ -33,18 +33,18 @@ type moment$MomentObject = {
hours: number,
minutes: number,
seconds: number,
milliseconds: number,
milliseconds: number
};
type moment$MomentCreationData = {
input: string,
format: string,
locale: Object,
isUTC: bool,
strict: bool,
isUTC: boolean,
strict: boolean
};
type moment$CalendarFormat = string | (moment: moment$Moment) => string;
type moment$CalendarFormat = string | ((moment: moment$Moment) => string);
type moment$CalendarFormats = {
sameDay?: moment$CalendarFormat,
@ -52,197 +52,276 @@ type moment$CalendarFormats = {
nextWeek?: moment$CalendarFormat,
lastDay?: moment$CalendarFormat,
lastWeek?: moment$CalendarFormat,
sameElse?: moment$CalendarFormat,
sameElse?: moment$CalendarFormat
};
declare class moment$LocaleData {
months(moment: moment$Moment): string;
monthsShort(moment: moment$Moment): string;
monthsParse(month: string): number;
weekdays(moment: moment$Moment): string;
weekdaysShort(moment: moment$Moment): string;
weekdaysMin(moment: moment$Moment): string;
weekdaysParse(weekDay: string): number;
longDateFormat(dateFormat: string): string;
isPM(date: string): bool;
meridiem(hours: number, minutes: number, isLower: bool): string;
calendar(key: 'sameDay'|'nextDay'|'lastDay'|'nextWeek'|'prevWeek'|'sameElse', moment: moment$Moment): string;
relativeTime(number: number, withoutSuffix: bool, key: 's'|'m'|'mm'|'h'|'hh'|'d'|'dd'|'M'|'MM'|'y'|'yy', isFuture: bool): string;
pastFuture(diff: any, relTime: string): string;
ordinal(number: number): string;
preparse(str: string): any;
postformat(str: string): any;
week(moment: moment$Moment): string;
invalidDate(): string;
firstDayOfWeek(): number;
firstDayOfYear(): number;
months(moment: moment$Moment): string,
monthsShort(moment: moment$Moment): string,
monthsParse(month: string): number,
weekdays(moment: moment$Moment): string,
weekdaysShort(moment: moment$Moment): string,
weekdaysMin(moment: moment$Moment): string,
weekdaysParse(weekDay: string): number,
longDateFormat(dateFormat: string): string,
isPM(date: string): boolean,
meridiem(hours: number, minutes: number, isLower: boolean): string,
calendar(
key:
| "sameDay"
| "nextDay"
| "lastDay"
| "nextWeek"
| "prevWeek"
| "sameElse",
moment: moment$Moment
): string,
relativeTime(
number: number,
withoutSuffix: boolean,
key: "s" | "m" | "mm" | "h" | "hh" | "d" | "dd" | "M" | "MM" | "y" | "yy",
isFuture: boolean
): string,
pastFuture(diff: any, relTime: string): string,
ordinal(number: number): string,
preparse(str: string): any,
postformat(str: string): any,
week(moment: moment$Moment): string,
invalidDate(): string,
firstDayOfWeek(): number,
firstDayOfYear(): number
}
declare class moment$MomentDuration {
humanize(suffix?: bool): string;
milliseconds(): number;
asMilliseconds(): number;
seconds(): number;
asSeconds(): number;
minutes(): number;
asMinutes(): number;
hours(): number;
asHours(): number;
days(): number;
asDays(): number;
months(): number;
asMonths(): number;
years(): number;
asYears(): number;
add(value: number|moment$MomentDuration|Object, unit?: string): this;
subtract(value: number|moment$MomentDuration|Object, unit?: string): this;
as(unit: string): number;
get(unit: string): number;
toJSON(): string;
toISOString(): string;
isValid(): bool;
humanize(suffix?: boolean): string,
milliseconds(): number,
asMilliseconds(): number,
seconds(): number,
asSeconds(): number,
minutes(): number,
asMinutes(): number,
hours(): number,
asHours(): number,
days(): number,
asDays(): number,
months(): number,
asMonths(): number,
years(): number,
asYears(): number,
add(value: number | moment$MomentDuration | Object, unit?: string): this,
subtract(value: number | moment$MomentDuration | Object, unit?: string): this,
as(unit: string): number,
get(unit: string): number,
toJSON(): string,
toISOString(): string,
isValid(): boolean
}
declare class moment$Moment {
static ISO_8601: string;
static (string?: string, format?: string|Array<string>, strict?: bool): moment$Moment;
static (string?: string, format?: string|Array<string>, locale?: string, strict?: bool): moment$Moment;
static (initDate: ?Object|number|Date|Array<number>|moment$Moment|string): moment$Moment;
static unix(seconds: number): moment$Moment;
static utc(): moment$Moment;
static utc(number: number|Array<number>): moment$Moment;
static utc(str: string, str2?: string|Array<string>, str3?: string): moment$Moment;
static utc(moment: moment$Moment): moment$Moment;
static utc(date: Date): moment$Moment;
static parseZone(): moment$Moment;
static parseZone(rawDate: string): moment$Moment;
static parseZone(rawDate: string, format: string | Array<string>): moment$Moment;
static parseZone(rawDate: string, format: string, strict: boolean): moment$Moment;
static parseZone(rawDate: string, format: string, locale: string, strict: boolean): moment$Moment;
isValid(): bool;
invalidAt(): 0|1|2|3|4|5|6;
creationData(): moment$MomentCreationData;
millisecond(number: number): this;
milliseconds(number: number): this;
millisecond(): number;
milliseconds(): number;
second(number: number): this;
seconds(number: number): this;
second(): number;
seconds(): number;
minute(number: number): this;
minutes(number: number): this;
minute(): number;
minutes(): number;
hour(number: number): this;
hours(number: number): this;
hour(): number;
hours(): number;
date(number: number): this;
dates(number: number): this;
date(): number;
dates(): number;
day(day: number|string): this;
days(day: number|string): this;
day(): number;
days(): number;
weekday(number: number): this;
weekday(): number;
isoWeekday(number: number): this;
isoWeekday(): number;
dayOfYear(number: number): this;
dayOfYear(): number;
week(number: number): this;
weeks(number: number): this;
week(): number;
weeks(): number;
isoWeek(number: number): this;
isoWeeks(number: number): this;
isoWeek(): number;
isoWeeks(): number;
month(number: number): this;
months(number: number): this;
month(): number;
months(): number;
quarter(number: number): this;
quarter(): number;
year(number: number): this;
years(number: number): this;
year(): number;
years(): number;
weekYear(number: number): this;
weekYear(): number;
isoWeekYear(number: number): this;
isoWeekYear(): number;
weeksInYear(): number;
isoWeeksInYear(): number;
get(string: string): number;
set(unit: string, value: number): this;
set(options: { [unit: string]: number }): this;
static max(...dates: Array<moment$Moment>): moment$Moment;
static max(dates: Array<moment$Moment>): moment$Moment;
static min(...dates: Array<moment$Moment>): moment$Moment;
static min(dates: Array<moment$Moment>): moment$Moment;
add(value: number|moment$MomentDuration|moment$Moment|Object, unit?: string): this;
subtract(value: number|moment$MomentDuration|moment$Moment|string|Object, unit?: string): this;
startOf(unit: string): this;
endOf(unit: string): this;
local(): this;
utc(): this;
utcOffset(offset: number|string): this;
utcOffset(): number;
format(format?: string): string;
fromNow(removeSuffix?: bool): string;
from(value: moment$Moment|string|number|Date|Array<number>, removePrefix?: bool): string;
toNow(removePrefix?: bool): string;
to(value: moment$Moment|string|number|Date|Array<number>, removePrefix?: bool): string;
calendar(refTime?: any, formats?: moment$CalendarFormats): string;
diff(date: moment$Moment|string|number|Date|Array<number>, format?: string, floating?: bool): number;
valueOf(): number;
unix(): number;
daysInMonth(): number;
toDate(): Date;
toArray(): Array<number>;
toJSON(): string;
toISOString(): string;
toObject(): moment$MomentObject;
isBefore(date?: moment$Moment|string|number|Date|Array<number>, units?: ?string): bool;
isSame(date?: moment$Moment|string|number|Date|Array<number>, units?: ?string): bool;
isAfter(date?: moment$Moment|string|number|Date|Array<number>, units?: ?string): bool;
isSameOrBefore(date?: moment$Moment|string|number|Date|Array<number>, units?: ?string): bool;
isSameOrAfter(date?: moment$Moment|string|number|Date|Array<number>, units?: ?string): bool;
static ISO_8601: string,
static (
string?: string,
format?: string | Array<string>,
strict?: boolean
): moment$Moment,
static (
string?: string,
format?: string | Array<string>,
locale?: string,
strict?: boolean
): moment$Moment,
static (
initDate: ?Object | number | Date | Array<number> | moment$Moment | string
): moment$Moment,
static unix(seconds: number): moment$Moment,
static utc(): moment$Moment,
static utc(number: number | Array<number>): moment$Moment,
static utc(
str: string,
str2?: string | Array<string>,
str3?: string
): moment$Moment,
static utc(moment: moment$Moment): moment$Moment,
static utc(date: Date): moment$Moment,
static parseZone(): moment$Moment,
static parseZone(rawDate: string): moment$Moment,
static parseZone(
rawDate: string,
format: string | Array<string>
): moment$Moment,
static parseZone(
rawDate: string,
format: string,
strict: boolean
): moment$Moment,
static parseZone(
rawDate: string,
format: string,
locale: string,
strict: boolean
): moment$Moment,
isValid(): boolean,
invalidAt(): 0 | 1 | 2 | 3 | 4 | 5 | 6,
creationData(): moment$MomentCreationData,
millisecond(number: number): this,
milliseconds(number: number): this,
millisecond(): number,
milliseconds(): number,
second(number: number): this,
seconds(number: number): this,
second(): number,
seconds(): number,
minute(number: number): this,
minutes(number: number): this,
minute(): number,
minutes(): number,
hour(number: number): this,
hours(number: number): this,
hour(): number,
hours(): number,
date(number: number): this,
dates(number: number): this,
date(): number,
dates(): number,
day(day: number | string): this,
days(day: number | string): this,
day(): number,
days(): number,
weekday(number: number): this,
weekday(): number,
isoWeekday(number: number): this,
isoWeekday(): number,
dayOfYear(number: number): this,
dayOfYear(): number,
week(number: number): this,
weeks(number: number): this,
week(): number,
weeks(): number,
isoWeek(number: number): this,
isoWeeks(number: number): this,
isoWeek(): number,
isoWeeks(): number,
month(number: number): this,
months(number: number): this,
month(): number,
months(): number,
quarter(number: number): this,
quarter(): number,
year(number: number): this,
years(number: number): this,
year(): number,
years(): number,
weekYear(number: number): this,
weekYear(): number,
isoWeekYear(number: number): this,
isoWeekYear(): number,
weeksInYear(): number,
isoWeeksInYear(): number,
get(string: string): number,
set(unit: string, value: number): this,
set(options: { [unit: string]: number }): this,
static max(...dates: Array<moment$Moment>): moment$Moment,
static max(dates: Array<moment$Moment>): moment$Moment,
static min(...dates: Array<moment$Moment>): moment$Moment,
static min(dates: Array<moment$Moment>): moment$Moment,
add(
value: number | moment$MomentDuration | moment$Moment | Object,
unit?: string
): this,
subtract(
value: number | moment$MomentDuration | moment$Moment | string | Object,
unit?: string
): this,
startOf(unit: string): this,
endOf(unit: string): this,
local(): this,
utc(): this,
utcOffset(
offset: number | string,
keepLocalTime?: boolean,
keepMinutes?: boolean
): this,
utcOffset(): number,
format(format?: string): string,
fromNow(removeSuffix?: boolean): string,
from(
value: moment$Moment | string | number | Date | Array<number>,
removePrefix?: boolean
): string,
toNow(removePrefix?: boolean): string,
to(
value: moment$Moment | string | number | Date | Array<number>,
removePrefix?: boolean
): string,
calendar(refTime?: any, formats?: moment$CalendarFormats): string,
diff(
date: moment$Moment | string | number | Date | Array<number>,
format?: string,
floating?: boolean
): number,
valueOf(): number,
unix(): number,
daysInMonth(): number,
toDate(): Date,
toArray(): Array<number>,
toJSON(): string,
toISOString(): string,
toObject(): moment$MomentObject,
isBefore(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSame(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isAfter(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSameOrBefore(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isSameOrAfter(
date?: moment$Moment | string | number | Date | Array<number>,
units?: ?string
): boolean,
isBetween(
fromDate: moment$Moment|string|number|Date|Array<number>,
toDate?: ?moment$Moment|string|number|Date|Array<number>,
fromDate: moment$Moment | string | number | Date | Array<number>,
toDate?: ?moment$Moment | string | number | Date | Array<number>,
granularity?: ?string,
inclusion?: ?string
): bool;
isDST(): bool;
isDSTShifted(): bool;
isLeapYear(): bool;
clone(): moment$Moment;
static isMoment(obj: any): bool;
static isDate(obj: any): bool;
static locale(locale: string, localeData?: Object): string;
static updateLocale(locale: string, localeData?: ?Object): void;
static locale(locales: Array<string>): string;
locale(locale: string, customization?: Object|null): moment$Moment;
locale(): string;
static months(): Array<string>;
static monthsShort(): Array<string>;
static weekdays(): Array<string>;
static weekdaysShort(): Array<string>;
static weekdaysMin(): Array<string>;
static months(): string;
static monthsShort(): string;
static weekdays(): string;
static weekdaysShort(): string;
static weekdaysMin(): string;
static localeData(key?: string): moment$LocaleData;
static duration(value: number|Object|string, unit?: string): moment$MomentDuration;
static isDuration(obj: any): bool;
static normalizeUnits(unit: string): string;
static invalid(object: any): moment$Moment;
): boolean,
isDST(): boolean,
isDSTShifted(): boolean,
isLeapYear(): boolean,
clone(): moment$Moment,
static isMoment(obj: any): boolean,
static isDate(obj: any): boolean,
static locale(locale: string, localeData?: Object): string,
static updateLocale(locale: string, localeData?: ?Object): void,
static locale(locales: Array<string>): string,
locale(locale: string, customization?: Object | null): moment$Moment,
locale(): string,
static months(): Array<string>,
static monthsShort(): Array<string>,
static weekdays(): Array<string>,
static weekdaysShort(): Array<string>,
static weekdaysMin(): Array<string>,
static months(): string,
static monthsShort(): string,
static weekdays(): string,
static weekdaysShort(): string,
static weekdaysMin(): string,
static localeData(key?: string): moment$LocaleData,
static duration(
value: number | Object | string,
unit?: string
): moment$MomentDuration,
static isDuration(obj: any): boolean,
static normalizeUnits(unit: string): string,
static invalid(object: any): moment$Moment
}
declare module 'moment' {
declare module "moment" {
declare module.exports: Class<moment$Moment>;
}

View file

@ -0,0 +1,45 @@
// flow-typed signature: 1df6b1361f12b05b8482216160fd1b61
// flow-typed version: <<STUB>>/react-document-title_v^2.0.3/flow_v0.56.0
/**
* This is an autogenerated libdef stub for:
*
* 'react-document-title'
*
* Fill this stub out by replacing all the `any` types.
*
* Once filled out, we encourage you to share your work with the
* community by sending a pull request to:
* https://github.com/flowtype/flow-typed
*/
declare module 'react-document-title' {
declare module.exports: any;
}
/**
* We include stubs for each file inside this npm package in case you need to
* require those files directly. Feel free to delete any files that aren't
* needed.
*/
declare module 'react-document-title/test/browser' {
declare module.exports: any;
}
declare module 'react-document-title/test/common' {
declare module.exports: any;
}
// Filename aliases
declare module 'react-document-title/index' {
declare module.exports: $Exports<'react-document-title'>;
}
declare module 'react-document-title/index.js' {
declare module.exports: $Exports<'react-document-title'>;
}
declare module 'react-document-title/test/browser.js' {
declare module.exports: $Exports<'react-document-title/test/browser'>;
}
declare module 'react-document-title/test/common.js' {
declare module.exports: $Exports<'react-document-title/test/common'>;
}

View file

@ -1,8 +1,5 @@
// flow-typed signature: f0d96df48e9abc14bcc1405ba2a47dde
// flow-typed version: 83053e4020/react-redux_v5.x.x/flow_>=v0.53.x
// flow-typed signature: 8db7b853f57c51094bf0ab8b2650fd9c
// flow-typed version: ab8db5f14d/react-redux_v5.x.x/flow_>=v0.30.x
// flow-typed signature: 59b0c4be0e1408f21e2446be96c79804
// flow-typed version: 9092387fd2/react-redux_v5.x.x/flow_>=v0.54.x
import type { Dispatch, Store } from "redux";
@ -34,6 +31,22 @@ declare module "react-redux" {
declare type Context = { store: Store<*, *> };
declare type ComponentWithDefaultProps<DP: {}, P: {}, CP: P> = Class<
React$Component<CP>
> & { defaultProps: DP };
declare class ConnectedComponentWithDefaultProps<
OP,
DP,
CP
> extends React$Component<OP> {
static defaultProps: DP, // <= workaround for https://github.com/facebook/flow/issues/4644
static WrappedComponent: Class<React$Component<CP>>,
getWrappedInstance(): React$Component<CP>,
props: OP,
state: void
}
declare class ConnectedComponent<OP, P> extends React$Component<OP> {
static WrappedComponent: Class<React$Component<P>>,
getWrappedInstance(): React$Component<P>,
@ -41,13 +54,18 @@ declare module "react-redux" {
state: void
}
declare type ConnectedComponentWithDefaultPropsClass<OP, DP, CP> = Class<
ConnectedComponentWithDefaultProps<OP, DP, CP>
>;
declare type ConnectedComponentClass<OP, P> = Class<
ConnectedComponent<OP, P>
>;
declare type Connector<OP, P> = (
component: React$ComponentType<P>
) => ConnectedComponentClass<OP, P>;
declare type Connector<OP, P> = (<DP: {}, CP: {}>(
component: ComponentWithDefaultProps<DP, P, CP>
) => ConnectedComponentWithDefaultPropsClass<OP, DP, CP>) &
((component: React$ComponentType<P>) => ConnectedComponentClass<OP, P>);
declare class Provider<S, A> extends React$Component<{
store: Store<S, A>,

View file

@ -1,5 +1,5 @@
// flow-typed signature: 86993bd000012d3e1ef10d757d16952d
// flow-typed version: a165222d28/redux_v3.x.x/flow_>=v0.33.x
// flow-typed signature: 33b83b6284653250e74578cf4dbe6124
// flow-typed version: e282e4128f/redux_v3.x.x/flow_>=v0.33.x
declare module 'redux' {
@ -11,15 +11,15 @@ declare module 'redux' {
*/
declare type DispatchAPI<A> = (action: A) => A;
declare type Dispatch<A: { type: $Subtype<string> }> = DispatchAPI<A>;
declare export type DispatchAPI<A> = (action: A) => A;
declare export type Dispatch<A: { type: $Subtype<string> }> = DispatchAPI<A>;
declare type MiddlewareAPI<S, A, D = Dispatch<A>> = {
declare export type MiddlewareAPI<S, A, D = Dispatch<A>> = {
dispatch: D;
getState(): S;
};
declare type Store<S, A, D = Dispatch<A>> = {
declare export type Store<S, A, D = Dispatch<A>> = {
// rewrite MiddlewareAPI members in order to get nicer error messages (intersections produce long messages)
dispatch: D;
getState(): S;
@ -27,58 +27,58 @@ declare module 'redux' {
replaceReducer(nextReducer: Reducer<S, A>): void
};
declare type Reducer<S, A> = (state: S, action: A) => S;
declare export type Reducer<S, A> = (state: S, action: A) => S;
declare type CombinedReducer<S, A> = (state: $Shape<S> & {} | void, action: A) => S;
declare export type CombinedReducer<S, A> = (state: $Shape<S> & {} | void, action: A) => S;
declare type Middleware<S, A, D = Dispatch<A>> =
declare export type Middleware<S, A, D = Dispatch<A>> =
(api: MiddlewareAPI<S, A, D>) =>
(next: D) => D;
declare type StoreCreator<S, A, D = Dispatch<A>> = {
declare export type StoreCreator<S, A, D = Dispatch<A>> = {
(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
};
declare type StoreEnhancer<S, A, D = Dispatch<A>> = (next: StoreCreator<S, A, D>) => StoreCreator<S, A, D>;
declare export type StoreEnhancer<S, A, D = Dispatch<A>> = (next: StoreCreator<S, A, D>) => StoreCreator<S, A, D>;
declare function createStore<S, A, D>(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
declare function createStore<S, A, D>(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
declare export function createStore<S, A, D>(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
declare export function createStore<S, A, D>(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
declare function applyMiddleware<S, A, D>(...middlewares: Array<Middleware<S, A, D>>): StoreEnhancer<S, A, D>;
declare export function applyMiddleware<S, A, D>(...middlewares: Array<Middleware<S, A, D>>): StoreEnhancer<S, A, D>;
declare type ActionCreator<A, B> = (...args: Array<B>) => A;
declare type ActionCreators<K, A> = { [key: K]: ActionCreator<A, any> };
declare export type ActionCreator<A, B> = (...args: Array<B>) => A;
declare export type ActionCreators<K, A> = { [key: K]: ActionCreator<A, any> };
declare function bindActionCreators<A, C: ActionCreator<A, any>, D: DispatchAPI<A>>(actionCreator: C, dispatch: D): C;
declare function bindActionCreators<A, K, C: ActionCreators<K, A>, D: DispatchAPI<A>>(actionCreators: C, dispatch: D): C;
declare export function bindActionCreators<A, C: ActionCreator<A, any>, D: DispatchAPI<A>>(actionCreator: C, dispatch: D): C;
declare export function bindActionCreators<A, K, C: ActionCreators<K, A>, D: DispatchAPI<A>>(actionCreators: C, dispatch: D): C;
declare function combineReducers<O: Object, A>(reducers: O): CombinedReducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;
declare export function combineReducers<O: Object, A>(reducers: O): CombinedReducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;
declare function compose<A, B>(ab: (a: A) => B): (a: A) => B
declare function compose<A, B, C>(
declare export function compose<A, B>(ab: (a: A) => B): (a: A) => B
declare export function compose<A, B, C>(
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => C
declare function compose<A, B, C, D>(
declare export function compose<A, B, C, D>(
cd: (c: C) => D,
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => D
declare function compose<A, B, C, D, E>(
declare export function compose<A, B, C, D, E>(
de: (d: D) => E,
cd: (c: C) => D,
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => E
declare function compose<A, B, C, D, E, F>(
declare export function compose<A, B, C, D, E, F>(
ef: (e: E) => F,
de: (d: D) => E,
cd: (c: C) => D,
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => F
declare function compose<A, B, C, D, E, F, G>(
declare export function compose<A, B, C, D, E, F, G>(
fg: (f: F) => G,
ef: (e: E) => F,
de: (d: D) => E,
@ -86,7 +86,7 @@ declare module 'redux' {
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => G
declare function compose<A, B, C, D, E, F, G, H>(
declare export function compose<A, B, C, D, E, F, G, H>(
gh: (g: G) => H,
fg: (f: F) => G,
ef: (e: E) => F,
@ -95,7 +95,7 @@ declare module 'redux' {
bc: (b: B) => C,
ab: (a: A) => B
): (a: A) => H
declare function compose<A, B, C, D, E, F, G, H, I>(
declare export function compose<A, B, C, D, E, F, G, H, I>(
hi: (h: H) => I,
gh: (g: G) => H,
fg: (f: F) => G,

View file

@ -6,3 +6,7 @@ export type Team$TeamMemeber = {
teamName: string,
teamId: number
};
export type Team$Update = {
description?: string
}

View file

@ -21,12 +21,12 @@ export type Teams$NewTeam = {
description: string
};
export type Teams$Team = {
id: number,
name: string,
current_team: boolean,
role: string,
members: number,
can_be_leaved: boolean
can_be_left: boolean,
user_team_id: number
};

View file

@ -4865,7 +4865,7 @@ prop-types-extra@^1.0.1:
dependencies:
warning "^3.0.0"
prop-types@^15.5.10:
prop-types@^15.5.10, prop-types@^15.5.6:
version "15.6.0"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
dependencies: