Commit e86e1593 authored by Viacheslav Pavlov's avatar Viacheslav Pavlov

Crops - public

parent 38d0ff36
import Crop from 'model/Crop';
import {CropService} from 'service/CropService';
import {LOAD_CROPS_CACHE_IDLE, RECEIVE_CROPS} from 'constants/crop';
import {IReducerAction} from 'model/common.model';
import {log} from 'utilities/debug';
const receiveCrops = (crops: Crop[]): IReducerAction => ({
type: RECEIVE_CROPS, payload: crops,
});
export const loadCrops = (forceReload: boolean = false) => (dispatch, getState) => {
const timeSinceLastFetch = getState().crop.lastFetched;
// perform the API call if the data is older than the allowed limit
const isDataStale = Date.now() - timeSinceLastFetch > LOAD_CROPS_CACHE_IDLE;
if (isDataStale || forceReload) {
return CropService.listCrops(getState().login.access_token)
.then((list) => {
dispatch(receiveCrops(list));
})
.catch((error) => {
log('Error', error);
});
}
};
export const saveCrop = (crop: Crop) => (dispatch, getState) => {
return CropService.saveCrop(getState().login.access_token, crop)
.then(() => {
dispatch(loadCrops(true));
}).catch((error) => {
log('Save error', error);
});
};
export const deleteCrop = (crop: Crop) => (dispatch, getState) => {
return CropService.deleteCrop(getState().login.access_token, crop.shortName)
.then(() => {
dispatch(loadCrops(true));
})
.catch((error) => {
log('Error', error);
});
};
export const SAVE_CROP = 'App/Crop/SAVE_CROP';
export const DELETE_CROP = 'App/Crop/DELETE_CROP';
export const LOAD_CROPS = 'App/Crop/LOAD_CROPS';
export const RECEIVE_CROPS = 'App/Crop/RECEIVE_CROPS';
// 300000 ms = 5 min
export const LOAD_CROPS_CACHE_IDLE = 300000;
import update from 'immutability-helper';
import { IReducerAction } from 'model/common.model';
import { RECEIVE_CROPS } from 'constants/crop';
const INITIAL_STATE = {
crops: null,
lastFetched: 0,
};
export default function crop(state = INITIAL_STATE, action: IReducerAction = {type: ''}) {
switch (action.type) {
case RECEIVE_CROPS: {
return update(state, {
crops: {$set: action.payload},
lastFetched: {$set: Date.now()},
});
}
default:
return state;
}
}
......@@ -11,6 +11,7 @@ import filterCode from './filterCode';
import subsets from './subsets';
import accessions from './accessions';
import applicationConfig from './applicationConfig';
import crop from './crop';
import user from './user';
const rootReducer = combineReducers({
......@@ -26,6 +27,7 @@ const rootReducer = combineReducers({
subsets,
accessions,
applicationConfig,
crop,
user,
});
......
import * as UrlTemplate from 'url-template';
import authenticatedRequest from 'utilities/requestUtils';
import { API_ROOT } from 'constants/apiURLS';
import Crop from 'model/Crop';
const URL_LIST_CROPS = UrlTemplate.parse(`${API_ROOT}/api/v0/crops`);
const URL_SAVE_CROP = `${API_ROOT}/api/v0/crops/save`;
const URL_DELETE_CROP = UrlTemplate.parse(`${API_ROOT}/api/v0/crops/{shortName}`);
export class CropService {
/**
* listCrops at /api/v0/crops
*
* @param authToken Authorization token
*/
public static listCrops(authToken: string): Promise<Crop[]> {
const apiUrl = URL_LIST_CROPS.expand();
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return authenticatedRequest(authToken, {
url: apiUrl,
method: 'GET',
...content,
}).then(({ data }) => data as Crop[]);
}
/**
* saveCrop at /api/v0/crops/save
*
* @param authToken Authorization token
* @param cropJson cropJson
*/
public static saveCrop(authToken: string, cropJson: Crop): Promise<Crop> {
const apiUrl = URL_SAVE_CROP;
// console.log(`Fetching from ${apiUrl}`);
const content = { data: cropJson };
return authenticatedRequest(authToken, {
url: apiUrl,
method: 'PUT',
...content,
}).then(({ data }) => data as Crop);
}
/**
* deleteCrop at /api/v0/crops/{shortName}
*
* @param authToken Authorization token
* @param shortName shortName
*/
public static deleteCrop(authToken: string, shortName: string): Promise<Crop> {
const apiUrl = URL_DELETE_CROP.expand({shortName});
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return authenticatedRequest(authToken, {
url: apiUrl,
method: 'DELETE',
...content,
}).then(({ data }) => data as Crop);
}
}
......@@ -3,6 +3,7 @@ import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {updateHistory} from 'actions/history';
import {loadCrops} from 'actions/crop';
import {initMyList} from 'actions/user';
import { withRouter } from 'react-router-dom';
......@@ -14,6 +15,7 @@ TimeAgo.locale(en);
import Snackbar from 'ui/common/snackbar/Snackbar';
import renderRoutes from 'ui/renderRoutes';
import Crop from 'model/Crop';
interface IAppProps extends React.ClassAttributes<any> {
children: any;
......@@ -21,14 +23,28 @@ interface IAppProps extends React.ClassAttributes<any> {
route: any;
location: any;
updateHistory: (path: string) => void;
crops: Crop[];
loadCrops: () => void;
initMyList: () => void;
}
class App extends React.Component<IAppProps, any> {
public static needs = [
() => loadCrops(),
];
public constructor(props: any) {
super(props);
}
public componentWillMount() {
const { crops, loadCrops } = this.props;
if (!crops || crops.length === 0) {
loadCrops();
}
}
public componentDidMount() {
const { initMyList } = this.props;
initMyList();
......@@ -54,11 +70,13 @@ class App extends React.Component<IAppProps, any> {
}
const mapStateToProps = (state) => ({
crops: state.crop.list,
// accessToken: state.login.access_token,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
updateHistory,
loadCrops,
initMyList,
}, dispatch);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment