Skip to content

Instantly share code, notes, and snippets.

@redmandarin
Created July 14, 2018 08:37
Show Gist options
  • Save redmandarin/55803153eeec9a5fb4834e227f58fe1f to your computer and use it in GitHub Desktop.
Save redmandarin/55803153eeec9a5fb4834e227f58fe1f to your computer and use it in GitHub Desktop.
import { configureChannel } from './channel';
export const ADD_ACTIONS = 'ADD_ACTIONS';
export const ADD_OFFERS = 'ADD_OFFERS';
export const ADD_DATA = 'ADD_DATA';
export const FILTER_OFFERS_BY_TYPE = 'FILTER_OFFERS_BY_TYPE';
export const UPDATE_OFFERS = 'UPDATE_OFFERS';
export const SHOW_ACTIVE_OFFERS_ACTION = 'SHOW_ACTIVE_OFFERS_ACTION';
export const CHANGE_ONLY_ACTIVE_OFFERS_STATE =
'CHANGE_ONLY_ACTIVE_OFFERS_STATE';
export const CHANGE_FILTER_OFFER_TYPE = 'CHANGE_FILTER_OFFER_TYPE';
export const HANDLE_PAGINATION_CLICK = 'HANDLE_PAGINATION_CLICK';
export const CHANGE_PAGE_STATE = 'CHANGE_PAGE_STATE';
export const UPDATE_PAGES_COUNT = 'UPDATE_PAGES_COUNT';
export const BEGIN_LOADING = 'BEGIN_LOADING';
export const END_LOADING = 'END_LOADING';
let socket = configureChannel();
let channel = socket.channel('terminal', { token: window.userToken });
export function addActions(actions) {
return { type: ADD_ACTIONS, actions };
}
export function addOffers(offers) {
return { type: ADD_OFFERS, offers };
}
export function addData(graphData, statisticData) {
return { type: ADD_DATA, graphData, statisticData };
}
const changeFilterOfferType = type => {
return { type: CHANGE_FILTER_OFFER_TYPE, offerType: type };
};
export const handlePaginationClick = (page, event) => {
return (dispatch, getState) => {
const { offerType, onlyActiveOffers } = getState();
Promise.all([
dispatch({ type: CHANGE_PAGE_STATE, page: page }),
dispatch(getOffersAction(offerType, onlyActiveOffers, page))
]);
};
};
export const filterOffersByType = offerType => {
return (dispatch, getState) => {
const { onlyActiveOffers } = getState();
Promise.all([
dispatch({ type: BEGIN_LOADING }),
dispatch(changeFilterOfferType(offerType)),
dispatch(getOffersAction(offerType, onlyActiveOffers))
]);
};
};
const changeonlyActiveOffersState = () => {
return { type: CHANGE_ONLY_ACTIVE_OFFERS_STATE };
};
export const onlyActiveOffersAction = () => {
return (dispatch, getState) => {
const { onlyActiveOffers, offerType } = getState();
Promise.all([
dispatch(changeonlyActiveOffersState()),
dispatch(getOffersAction(offerType, !onlyActiveOffers))
]);
};
};
const getOffersAction = (offerType, onlyActiveOffers, page = 1) => {
let headers = new Headers({
'Content-Type': 'application/json'
});
return (dispatch, getState) => {
const { itemsOnPage } = getState();
const offset = (page - 1) * itemsOnPage;
const url = `/api/v1/terminal/offers?offer_type=${offerType}&only_active_offers=${onlyActiveOffers}&offset=${offset}`;
return fetch(url, {
method: 'GET',
headers: headers,
credentials: 'same-origin'
})
.then(res => res.json())
.then(res => {
Promise.all([
dispatch({
type: UPDATE_OFFERS,
offers: res.offers
}),
dispatch(updatePagesCount(res.total_count, page)),
dispatch({ type: END_LOADING })
]);
});
};
};
const updatePagesCount = (totalCount, page) => {
return (dispatch, getState) => {
const { itemsOnPage } = getState();
let pagesCount = Math.ceil(totalCount / itemsOnPage);
dispatch({
type: UPDATE_PAGES_COUNT,
totalCount: totalCount,
pagesCount: pagesCount,
page: page
});
};
};
export function fetchData() {
return dispatch => {
channel
.join()
.receive('ok', response => {
dispatch(addActions(response.actions));
dispatch(addOffers(response.offers.companies));
dispatch(
addData(response.offers.graph_data, response.offers.statistic)
);
})
.receive('error', reason => {
console.log('failed join', reason);
});
channel.on('new:action', msg => {
dispatch(addActions([msg]));
});
};
}
import { combineReducers } from 'redux';
import {
ADD_OFFERS,
ADD_ACTIONS,
ADD_DATA,
UPDATE_OFFERS,
CHANGE_FILTER_OFFER_TYPE,
CHANGE_ONLY_ACTIVE_OFFERS_STATE,
SAVE_FILTER_TO_LOCAL_STORAGE,
CHANGE_PAGE_STATE,
UPDATE_PAGES_COUNT,
BEGIN_LOADING,
END_LOADING
} from './actions';
function actions(state = [], action) {
switch (action.type) {
// case ADD_ACTIONS:
// return { ...state, actions: [...state.actions, ...action.actions] };
case ADD_OFFERS:
return { ...state, offers: [...state.offers, ...action.offers] };
case ADD_DATA:
return {
...state,
graphData: action.graphData,
statistic: action.statisticData
};
case UPDATE_OFFERS:
return { ...state, offers: action.offers };
case CHANGE_ONLY_ACTIVE_OFFERS_STATE:
return { ...state, onlyActiveOffers: !state.onlyActiveOffers };
case CHANGE_FILTER_OFFER_TYPE:
return { ...state, offerType: action.offerType };
case CHANGE_PAGE_STATE:
return { ...state, page: action.page };
case BEGIN_LOADING:
return { ...state, loading: true };
case END_LOADING:
return { ...state, loading: false };
case UPDATE_PAGES_COUNT:
return {
...state,
totalCount: action.totalCount,
pagesCount: action.pagesCount,
page: action.page
};
default:
return state;
}
}
export default actions;
import { createStore, applyMiddleware } from 'redux';
import reducers from './reducers';
import thunkMiddleware from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
const initialState = offers => {
const settings = offers.terminal_settings;
const itemsOnPage = 9;
console.log(offers);
return {
actions: [],
offers: offers.companies,
statistic: offers.statistic,
graphData: offers.graph_data,
onlyActiveOffers: settings.only_active_offers,
offerType: settings.offer_type,
totalCount: offers.total_count,
pagesCount: Math.ceil(offers.total_count / itemsOnPage),
itemsOnPage: itemsOnPage,
loading: false,
page: 1
};
};
export const store = offers => {
const store = createStore(
reducers,
initialState(offers),
composeWithDevTools(applyMiddleware(thunkMiddleware))
);
return store;
};
export default store;
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { fetchData } from './actions';
import ActionList from './components/ActionList';
import OfferList from './components/OfferList';
import Pagination from './components/Pagination';
import Graph from './components/Graph';
import { store } from './store';
import * as actionCreators from './actions';
import { bindActionCreators } from 'redux';
class Terminal extends React.Component {
render() {
return (
<div className="terminal__inner">
<div className="terminal__content">
<Graph data={this.props.graphData} statistic={this.props.statistic} />
<OfferList
offers={this.props.offers}
filterOffersByType={this.props.filterOffersByType}
loading={this.props.loading}
offerType={this.props.offerType}
onlyActiveOffersAction={this.props.onlyActiveOffersAction}
onlyActiveOffers={this.props.onlyActiveOffers}
/>
<Pagination
pagesCount={this.props.pagesCount}
handleClick={this.props.handlePaginationClick}
currentPage={this.props.page}
/>
</div>
<div className="terminal__sidebar">
<ActionList actions={this.props.actions} />
</div>
</div>
);
}
}
const mapStateToProps = store => {
return {
actions: store.actions,
offers: store.offers,
graphData: store.graphData,
statistic: store.statistic,
onlyActiveOffers: store.onlyActiveOffers,
offerType: store.offerType,
pagesCount: store.pagesCount,
page: store.page,
total_count: store.totalCount,
loading: store.loading
};
};
const mapDispatchToProps = dispatch => {
return bindActionCreators(
{
...actionCreators
},
dispatch
);
};
export default connect(mapStateToProps, mapDispatchToProps)(Terminal);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment