mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-20 06:35:56 +08:00
setup flow
This commit is contained in:
parent
f8fc2737d5
commit
84f279de22
3
.babelrc
3
.babelrc
|
@ -12,7 +12,8 @@
|
|||
}
|
||||
],
|
||||
"react",
|
||||
"es2015"
|
||||
"es2015",
|
||||
"flow"
|
||||
],
|
||||
"plugins": [
|
||||
"transform-object-rest-spread",
|
||||
|
|
9
.flowconfig
Normal file
9
.flowconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
[ignore]
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
|
||||
[lints]
|
||||
|
||||
[options]
|
|
@ -1,12 +1,11 @@
|
|||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
import { string, number, func, shape, bool, arrayOf } from "prop-types";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { Modal, Button } from "react-bootstrap";
|
||||
import _ from "lodash";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { getActivities } from "../../actions/ActivitiesActions";
|
||||
import { getActivities } from "../../../services/api/activities_api";
|
||||
import ActivityElement from "./ActivityElement";
|
||||
import ActivityDateElement from "./ActivityDateElement";
|
||||
import {
|
||||
|
@ -42,25 +41,26 @@ const StyledBottom = styled(Button)`
|
|||
|
||||
const StyledModalBody = styled(Modal.Body)`
|
||||
background-color: ${COLOR_CONCRETE};
|
||||
color: ${COLOR_MINE_SHAFT};;
|
||||
color: ${COLOR_MINE_SHAFT};
|
||||
`;
|
||||
|
||||
class GlobalActivitiesModal extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { activities: this.props.activites, more: this.props.more };
|
||||
this.displayActivities = this.displayActivities.bind(this);
|
||||
this.addMoreActivities = this.addMoreActivities.bind(this);
|
||||
}
|
||||
|
||||
displayActivities() {
|
||||
if (this.props.activities.length === 0) {
|
||||
if (this.state.activities.length === 0) {
|
||||
return (
|
||||
<li>
|
||||
<FormattedMessage id="activities.no_data" />
|
||||
</li>
|
||||
);
|
||||
}
|
||||
return this.props.activities.map((activity, i, arr) => {
|
||||
return this.state.activities.map((activity, i, arr) => {
|
||||
const newDate = new Date(activity.created_at);
|
||||
if (i > 0) {
|
||||
const prevDate = new Date(arr[i - 1].created_at);
|
||||
|
@ -81,8 +81,13 @@ class GlobalActivitiesModal extends Component {
|
|||
}
|
||||
|
||||
addMoreActivities() {
|
||||
const lastId = _.last(this.props.activities).id;
|
||||
this.props.fetchActivities(lastId);
|
||||
const lastId = _.last(this.state.activities).id;
|
||||
getActivities(lastId).then(response => {
|
||||
this.setState({
|
||||
activities: [...this.state.activities, ...response.activities],
|
||||
more: response.more
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
addMoreButton() {
|
||||
|
@ -123,30 +128,16 @@ class GlobalActivitiesModal extends Component {
|
|||
}
|
||||
|
||||
GlobalActivitiesModal.propTypes = {
|
||||
showModal: PropTypes.bool.isRequired,
|
||||
onCloseModal: PropTypes.func.isRequired,
|
||||
fetchActivities: PropTypes.func.isRequired,
|
||||
more: PropTypes.bool.isRequired,
|
||||
activities: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.number.isRequired,
|
||||
message: PropTypes.string.isRequired,
|
||||
created_at: PropTypes.string.isRequired
|
||||
showModal: bool.isRequired,
|
||||
more: bool.isRequired,
|
||||
activites: arrayOf(
|
||||
shape({
|
||||
id: number.isRequired,
|
||||
message: string.isRequired,
|
||||
created_at: string.isRequired
|
||||
})
|
||||
).isRequired
|
||||
).isRequired,
|
||||
onCloseModal: func.isRequired
|
||||
};
|
||||
|
||||
const mapStateToProps = ({ global_activities }) => {
|
||||
const { activities, more } = global_activities;
|
||||
return { activities, more };
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
fetchActivities(lastId) {
|
||||
dispatch(getActivities(lastId));
|
||||
}
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(
|
||||
GlobalActivitiesModal
|
||||
);
|
||||
export default GlobalActivitiesModal;
|
||||
|
|
|
@ -9,7 +9,8 @@ import {
|
|||
WHITE_COLOR,
|
||||
BORDER_GRAY_COLOR
|
||||
} from "../../config/constants/colors";
|
||||
import { getActivities, destroyActivities } from "../actions/ActivitiesActions";
|
||||
import { getActivities } from "../../services/api/activities_api";
|
||||
|
||||
import TeamSwitch from "./components/TeamSwitch";
|
||||
import GlobalActivitiesModal from "./components/GlobalActivitiesModal";
|
||||
import SearchDropdown from "./components/SearchDropdown";
|
||||
|
@ -44,6 +45,8 @@ class Navigation extends Component {
|
|||
super(props);
|
||||
this.state = {
|
||||
showActivitesModal: false,
|
||||
activities: [],
|
||||
more: false,
|
||||
current_team: { id: 0 }
|
||||
};
|
||||
this.selectItemCallback = this.selectItemCallback.bind(this);
|
||||
|
@ -64,8 +67,15 @@ class Navigation extends Component {
|
|||
case 4:
|
||||
ev.preventDefault();
|
||||
this.setState({ showActivitesModal: !this.state.showActivitesModal });
|
||||
// Call action creator to fetch activities from the server
|
||||
this.props.fetchActivities();
|
||||
// load activites if modal is shown
|
||||
if (this.state.showActivitesModal) {
|
||||
getActivities().then(response => {
|
||||
this.setState({
|
||||
activities: response.activities,
|
||||
more: response.more
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
@ -73,7 +83,6 @@ class Navigation extends Component {
|
|||
|
||||
closeModalCallback() {
|
||||
this.setState({ showActivitesModal: false });
|
||||
this.props.destroyActivities();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -132,6 +141,8 @@ class Navigation extends Component {
|
|||
</Nav>
|
||||
</StyledNavbar>
|
||||
<GlobalActivitiesModal
|
||||
activities={this.state.activites}
|
||||
more={this.state.more}
|
||||
showModal={this.state.showActivitesModal}
|
||||
onCloseModal={this.closeModalCallback}
|
||||
/>
|
||||
|
@ -141,8 +152,6 @@ class Navigation extends Component {
|
|||
}
|
||||
|
||||
Navigation.propTypes = {
|
||||
fetchActivities: PropTypes.func.isRequired,
|
||||
destroyActivities: PropTypes.func.isRequired,
|
||||
current_team: PropTypes.shape({
|
||||
id: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
|
@ -153,14 +162,4 @@ Navigation.propTypes = {
|
|||
// Map the states from store to component props
|
||||
const mapStateToProps = ({ current_team }) => ({ current_team });
|
||||
|
||||
// Map the fetch activity action to component props
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
fetchActivities() {
|
||||
dispatch(getActivities());
|
||||
},
|
||||
destroyActivities() {
|
||||
dispatch(destroyActivities());
|
||||
}
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Navigation);
|
||||
export default connect(mapStateToProps)(Navigation);
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
import axios from "../../config/axios";
|
||||
import { ACTIVITIES_PATH } from "../../config/api_endpoints";
|
||||
import {
|
||||
GLOBAL_ACTIVITIES_DATA,
|
||||
DESTROY_GLOBAL_ACTIVITIES_DATA,
|
||||
SPINNER_ON,
|
||||
SPINNER_OFF
|
||||
} from "../../config/action_types";
|
||||
|
||||
function addActivitiesData(data) {
|
||||
return {
|
||||
type: GLOBAL_ACTIVITIES_DATA,
|
||||
payload: data
|
||||
};
|
||||
}
|
||||
|
||||
export function destroyActivities() {
|
||||
return {
|
||||
type: DESTROY_GLOBAL_ACTIVITIES_DATA
|
||||
};
|
||||
}
|
||||
|
||||
export function getActivities(lastId = 0) {
|
||||
return dispatch => {
|
||||
const path = `${ACTIVITIES_PATH}?from=${lastId}`;
|
||||
axios
|
||||
.get(path, { withCredentials: true })
|
||||
.then(response => {
|
||||
dispatch(addActivitiesData(response.data));
|
||||
})
|
||||
.catch(error => {
|
||||
console.log("get Activites Error: ", error);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function spinnerOn() {
|
||||
return {
|
||||
type: SPINNER_ON
|
||||
};
|
||||
}
|
||||
|
||||
export function spinnerOff() {
|
||||
return {
|
||||
type: SPINNER_OFF
|
||||
};
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
import {
|
||||
GLOBAL_ACTIVITIES_DATA,
|
||||
DESTROY_GLOBAL_ACTIVITIES_DATA,
|
||||
SPINNER_OFF,
|
||||
SPINNER_ON
|
||||
} from "../../config/action_types";
|
||||
|
||||
const initialStateu = { more: true, activities: [], spinner_on: false };
|
||||
|
||||
export function globalActivities(state = initialStateu, action) {
|
||||
switch (action.type) {
|
||||
case GLOBAL_ACTIVITIES_DATA:
|
||||
return {
|
||||
...state,
|
||||
activities: [
|
||||
...state.activities,
|
||||
...action.payload.global_activities.activities
|
||||
],
|
||||
more: action.payload.global_activities.more
|
||||
};
|
||||
case DESTROY_GLOBAL_ACTIVITIES_DATA:
|
||||
return {
|
||||
...state,
|
||||
...initialStateu
|
||||
};
|
||||
case SPINNER_OFF:
|
||||
return Object.assign({}, state, { spinner_on: false });
|
||||
case SPINNER_ON:
|
||||
return Object.assign({}, state, { spinner_on: true });
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -3,10 +3,6 @@ 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";
|
||||
|
||||
// activities
|
||||
export const GLOBAL_ACTIVITIES_DATA = "GLOBAL_ACTIVITIES_DATA";
|
||||
export const DESTROY_GLOBAL_ACTIVITIES_DATA = "DESTROY_GLOBAL_ACTIVITIES_DATA";
|
||||
|
||||
// users
|
||||
export const SET_CURRENT_USER = "SET_CURRENT_USER";
|
||||
export const CHANGE_CURRENT_USER_FULL_NAME = "CHANGE_CURRENT_USER_FULL_NAME";
|
||||
|
@ -39,4 +35,4 @@ export const SPINNER_OFF = "SPINNER_OFF";
|
|||
// alerts
|
||||
export const ADD_ALERT = "ADD_ALERT";
|
||||
export const CLEAR_ALERT = "CLEAR_ALERT";
|
||||
export const CLEAR_ALL_ALERTS = "CLEAR_ALL_ALERTS";
|
||||
export const CLEAR_ALL_ALERTS = "CLEAR_ALL_ALERTS";
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// activities
|
||||
export const ACTIVITIES_PATH = "/client_api/activities";
|
||||
|
||||
// settings
|
||||
export const SETTINGS_PATH = "/settings";
|
||||
|
|
|
@ -4,14 +4,12 @@ import {
|
|||
getListOfTeams,
|
||||
showLeaveTeamModal,
|
||||
} from "../components/reducers/TeamReducers";
|
||||
import { globalActivities } from "../components/reducers/ActivitiesReducers";
|
||||
import { currentUser } from "../components/reducers/UsersReducer";
|
||||
import { alerts } from "../components/reducers/AlertsReducers";
|
||||
|
||||
export default combineReducers({
|
||||
current_team: setCurrentTeam,
|
||||
all_teams: getListOfTeams,
|
||||
global_activities: globalActivities,
|
||||
current_user: currentUser,
|
||||
showLeaveTeamModal,
|
||||
alerts
|
||||
|
|
7
app/javascript/src/services/api/activities_api.js
Normal file
7
app/javascript/src/services/api/activities_api.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { axiosInstance } from "./config";
|
||||
import { ACTIVITIES_PATH } from "./endpoints";
|
||||
|
||||
export function getActivities(lastId = 0) {
|
||||
const path = `${ACTIVITIES_PATH}?from=${lastId}`;
|
||||
axiosInstance.get(path).then(({ data }) => data);
|
||||
}
|
8
app/javascript/src/services/api/config.js
Normal file
8
app/javascript/src/services/api/config.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import axios from "axios";
|
||||
|
||||
export const axiosInstance = axios.create({
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').content
|
||||
}
|
||||
});
|
2
app/javascript/src/services/api/endpoints.js
Normal file
2
app/javascript/src/services/api/endpoints.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
// activities
|
||||
export const ACTIVITIES_PATH = "/client_api/activities";
|
|
@ -1,5 +1,10 @@
|
|||
Rails.application.routes.draw do
|
||||
require 'subdomain'
|
||||
|
||||
def draw(routes_name)
|
||||
instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb")))
|
||||
end
|
||||
|
||||
constraints UserSubdomain do
|
||||
devise_for :users, controllers: { registrations: 'users/registrations',
|
||||
sessions: 'users/sessions',
|
||||
|
@ -13,50 +18,8 @@ Rails.application.routes.draw do
|
|||
get '/settings/*all', to: 'client_api/settings#index'
|
||||
|
||||
namespace :client_api, defaults: { format: 'json' } do
|
||||
# activities
|
||||
get '/activities', to: 'activities#index'
|
||||
|
||||
# teams
|
||||
get '/teams', to: 'teams/teams#index'
|
||||
namespace :teams do
|
||||
get '/new', to: 'teams#new'
|
||||
get '/:team_id/details', to: 'teams#details'
|
||||
post '/', to: 'teams#create'
|
||||
post '/change_team', to: 'teams#change_team'
|
||||
post '/update', to: 'teams#update'
|
||||
end
|
||||
# notifications
|
||||
get '/recent_notifications', to: 'notifications#recent_notifications'
|
||||
|
||||
# users
|
||||
get '/current_user_info', to: 'users/users#current_user_info'
|
||||
|
||||
namespace :users do
|
||||
delete '/remove_user', to: 'user_teams#remove_user'
|
||||
delete '/leave_team', to: 'user_teams#leave_team'
|
||||
put '/update_role', to: 'user_teams#update_role'
|
||||
get '/profile_info', to: 'users#profile_info'
|
||||
get '/statistics_info', to: 'users#statistics_info'
|
||||
get '/preferences_info', to: 'users#preferences_info'
|
||||
delete '/leave_team', to: 'user_teams#leave_team'
|
||||
post '/change_full_name', to: 'users#change_full_name'
|
||||
post '/change_initials', to: 'users#change_initials'
|
||||
post '/change_email', to: 'users#change_email'
|
||||
post '/change_password', to: 'users#change_password'
|
||||
post '/change_timezone', to: 'users#change_timezone'
|
||||
post '/change_assignements_notification',
|
||||
to: 'users#change_assignements_notification'
|
||||
post '/change_assignements_notification_email',
|
||||
to: 'users#change_assignements_notification_email'
|
||||
post '/change_recent_notification',
|
||||
to: 'users#change_recent_notification'
|
||||
post '/change_recent_notification_email',
|
||||
to: 'users#change_recent_notification_email'
|
||||
post '/change_system_notification_email',
|
||||
to: 'users#change_system_notification_email'
|
||||
devise_scope :user do
|
||||
put '/invite_users', to: 'invitations#invite_users'
|
||||
end
|
||||
%i(activities teams notifications users).each do |path|
|
||||
draw path
|
||||
end
|
||||
end
|
||||
|
||||
|
|
2
config/routes/activities.rb
Normal file
2
config/routes/activities.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
# activities
|
||||
get '/activities', to: 'activities#index'
|
2
config/routes/notifications.rb
Normal file
2
config/routes/notifications.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
# notifications
|
||||
get '/recent_notifications', to: 'notifications#recent_notifications'
|
10
config/routes/teams.rb
Normal file
10
config/routes/teams.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
# teams
|
||||
get '/teams', to: 'teams/teams#index'
|
||||
|
||||
namespace :teams do
|
||||
get '/new', to: 'teams#new'
|
||||
get '/:team_id/details', to: 'teams#details'
|
||||
post '/', to: 'teams#create'
|
||||
post '/change_team', to: 'teams#change_team'
|
||||
post '/update', to: 'teams#update'
|
||||
end
|
30
config/routes/users.rb
Normal file
30
config/routes/users.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
# users
|
||||
get '/current_user_info', to: 'users/users#current_user_info'
|
||||
|
||||
namespace :users do
|
||||
delete '/remove_user', to: 'user_teams#remove_user'
|
||||
delete '/leave_team', to: 'user_teams#leave_team'
|
||||
put '/update_role', to: 'user_teams#update_role'
|
||||
get '/profile_info', to: 'users#profile_info'
|
||||
get '/statistics_info', to: 'users#statistics_info'
|
||||
get '/preferences_info', to: 'users#preferences_info'
|
||||
delete '/leave_team', to: 'user_teams#leave_team'
|
||||
post '/change_full_name', to: 'users#change_full_name'
|
||||
post '/change_initials', to: 'users#change_initials'
|
||||
post '/change_email', to: 'users#change_email'
|
||||
post '/change_password', to: 'users#change_password'
|
||||
post '/change_timezone', to: 'users#change_timezone'
|
||||
post '/change_assignements_notification',
|
||||
to: 'users#change_assignements_notification'
|
||||
post '/change_assignements_notification_email',
|
||||
to: 'users#change_assignements_notification_email'
|
||||
post '/change_recent_notification',
|
||||
to: 'users#change_recent_notification'
|
||||
post '/change_recent_notification_email',
|
||||
to: 'users#change_recent_notification_email'
|
||||
post '/change_system_notification_email',
|
||||
to: 'users#change_system_notification_email'
|
||||
devise_scope :user do
|
||||
put '/invite_users', to: 'invitations#invite_users'
|
||||
end
|
||||
end
|
|
@ -29,6 +29,7 @@
|
|||
"eslint-plugin-jsx-a11y": "^6.0.2",
|
||||
"eslint-plugin-prettier": "^2.1.2",
|
||||
"eslint-plugin-react": "^7.1.0",
|
||||
"flow-bin": "^0.56.0",
|
||||
"prettier": "^1.7.0",
|
||||
"webpack-dev-server": "^2.5.1"
|
||||
},
|
||||
|
@ -68,8 +69,6 @@
|
|||
"react-bootstrap-table": "^4.0.0",
|
||||
"react-bootstrap-timezone-picker": "^1.0.11",
|
||||
"react-data-grid": "^2.0.2",
|
||||
"react-tagsinput": "^3.17.0",
|
||||
"react-transition-group": "^2.2.0",
|
||||
"react-dom": "^15.6.1",
|
||||
"react-intl": "^2.3.0",
|
||||
"react-intl-redux": "^0.6.0",
|
||||
|
@ -78,7 +77,9 @@
|
|||
"react-router-bootstrap": "^0.24.2",
|
||||
"react-router-dom": "^4.1.2",
|
||||
"react-router-prop-types": "^0.0.1",
|
||||
"react-tagsinput": "^3.17.0",
|
||||
"react-timezone": "^0.2.0",
|
||||
"react-transition-group": "^2.2.0",
|
||||
"redux": "^3.7.2",
|
||||
"redux-thunk": "^2.2.0",
|
||||
"resolve-url-loader": "^2.1.0",
|
||||
|
|
|
@ -2357,6 +2357,10 @@ flatten@^1.0.2:
|
|||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
|
||||
|
||||
flow-bin@^0.56.0:
|
||||
version "0.56.0"
|
||||
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.56.0.tgz#ce43092203a344ba9bf63c0cabe95d95145f6cad"
|
||||
|
||||
follow-redirects@^1.2.3:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.4.tgz#355e8f4d16876b43f577b0d5ce2668b9723214ea"
|
||||
|
|
Loading…
Reference in a new issue