Commit 7795c6d1 authored by Valeriy Panov's avatar Valeriy Panov Committed by Matija Obreza
Browse files

Crop editing

parent b4a5879b
This diff is collapsed.
import {push} from 'react-router-redux';
import {Crop} from 'model/crop.model';
import {CropService} from 'service/CropService';
import {CREATE_CROP, GET_CROP, RECEIVE_CROP, RECEIVE_CROPS} from 'constants/crop';
import {IReducerAction} from 'model/common.model';
export const createCrop = () => (dispatch) => {
dispatch({type: CREATE_CROP});
return dispatch(push('/dashboard/crops/edit'));
};
const receiveCrop = (crop: Crop): IReducerAction => ({
type: RECEIVE_CROP, payload: crop,
});
const receiveCrops = (crops: Crop[]): IReducerAction => ({
type: RECEIVE_CROPS, payload: crops,
});
export const loadCrop = (uuid: string) => (dispatch, getState) => {
const token = getState().login.access_token;
dispatch({type: GET_CROP, payload: uuid});
return CropService.getCrop(token, uuid)
.then((crop) => {
return dispatch(receiveCrop(crop));
}).catch((error) => {
console.log(`No crop with uuid ${uuid}`, error);
});
};
export const editCrop = (uuid: string) => (dispatch, getState) => {
dispatch(loadCrop(uuid));
dispatch(push(`/dashboard/crops/${uuid}/edit`));
};
// const showCrop = (uuid: string) => (dispatch) => {
// dispatch(push(`/dashboard/crops/${uuid}`));
// };
export const listCrops = () => (dispatch, getState) => {
return CropService.listCrops(getState().login.access_token)
.then((list) => {
dispatch(receiveCrops(list));
})
.catch((error) => {
console.log('Error', error);
});
};
export const saveCrop = (crop: Crop) => (dispatch, getState) => {
return CropService.saveCrop(getState().login.access_token, crop)
.then((saved) => {
dispatch(receiveCrop(saved));
dispatch(push('/dashboard/crops'));
}).catch((error) => {
console.log('Save error', error);
});
};
export const deleteCrop = (crop: Crop) => (dispatch, getState) => {
return CropService.deleteCrop(getState().login.access_token, crop)
.then((crop) => {
dispatch(push('/dashboard/crops'));
})
.catch((error) => {
console.log('Error', error);
});
};
export const CREATE_CROP = 'App/Crop/CREATE_CROP';
export const GET_CROP = 'App/Crop/GET_CROP';
export const RECEIVE_CROP = 'App/Crop/RECEIVE_CROP';
export const DELETE_CROP = 'App/Crop/DELETE_CROP';
export const LIST_CROPS = 'App/Crop/LIST_CROPS';
export const RECEIVE_CROPS = 'App/Crop/RECEIVE_CROPS';
export const CROP_FORM = 'Form/CROP';
import { UuidModel, CurrentPermissions, IUserPermissions } from './common.model';
class Crop extends UuidModel implements IUserPermissions {
public code: string;
public title: string;
public _permissions: CurrentPermissions;
public constructor(obj?) {
super(obj);
if (obj && obj._permissions) {
this._permissions = new CurrentPermissions(obj._permissions);
}
}
public getClassname(): string {
return 'org.genesys.common.model.Crop';
}
}
export { Crop };
import * as update from 'immutability-helper';
import {IReducerAction} from 'model/common.model';
import {Crop} from 'model/crop.model';
import {CREATE_CROP, RECEIVE_CROP, RECEIVE_CROPS} from 'constants/crop';
const INITIAL_STATE = {
currentCrop: null,
list: null,
};
export default function crop(state = INITIAL_STATE, action: IReducerAction = {type: ''}) {
switch (action.type) {
case CREATE_CROP: {
return update(state, {
currentCrop: {$set: new Crop()},
});
}
case RECEIVE_CROP: {
return update(state, {
currentCrop: {$set: action.payload},
});
}
case RECEIVE_CROPS: {
return update(state, {
list: {$set: action.payload},
});
}
default:
return state;
}
}
......@@ -11,20 +11,22 @@ import pagination from './pagination';
import filter from './filter';
import appMounted from './appMounted';
import vocabulary from './vocabulary';
import crop from './crop';
const rootReducer = combineReducers({
vocabulary,
descriptors,
descriptorList,
partner,
login,
serverInfo,
datasets,
pagination,
filter,
appMounted,
routing: routerReducer,
form: formReducer,
crop,
vocabulary,
descriptors,
descriptorList,
partner,
login,
serverInfo,
datasets,
pagination,
filter,
appMounted,
routing: routerReducer,
form: formReducer,
});
export default rootReducer;
import {Crop} from 'model/crop.model';
import authenticatedRequest from 'utilities/requestUtils';
import {API_BASE_URL} from 'constants/apiURLS';
const API_URL = `${API_BASE_URL}/crops`;
export class CropService {
public static listCrops(token: string): Promise<Crop[]> {
return authenticatedRequest(token, {
url: `${API_URL}/`,
method: 'GET',
}).then(({data}) => data.map((c) => new Crop(c)));
}
public static getCrop(token: string, uuid: string): Promise<Crop> {
return authenticatedRequest(token, {
url: `${API_URL}/${uuid}`,
method: 'GET',
}).then(({data}) => new Crop(data));
}
public static saveCrop(token: string, crop: Crop): Promise<Crop> {
return authenticatedRequest(token, {
url: `${API_URL}/${crop.version === undefined ? 'create' : 'update'}`,
method: 'POST',
data: {
...crop,
},
}).then(({data}) => new Crop(data));
}
public static deleteCrop(token: string, crop: Crop): Promise<Crop> {
return authenticatedRequest(token, {
url: `${API_URL}/${crop.uuid},${crop.version}`,
method: 'DELETE',
data: {
...crop,
},
}).then(({data}) => new Crop(data));
}
}
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {withStyles} from 'material-ui/styles';
import Grid from 'material-ui/Grid';
import Card, {CardHeader, CardContent} from 'material-ui/Card';
import Divider from 'material-ui/Divider';
import {Link} from 'react-router';
import {listCrops} from 'actions/crop';
import {Crop} from 'model/crop.model';
const styles = (theme) => ({
card: {
margin: '20px',
},
});
interface IBrowsePageProps extends React.ClassAttributes<any> {
router: any;
classes: any;
crops?: Crop[];
listCrops: any;
}
class BrowsePage extends React.Component<IBrowsePageProps, any> {
protected static needs = [
() => listCrops(),
];
public componentWillMount() {
this.props.listCrops();
}
public render() {
const {classes, crops} = this.props;
return (
<Grid container>
{ crops &&
crops.map((e, i) => (
<Grid item xs={ 12 } md={ 2 }>
<Card key={ i } className={ classes.card }>
<CardHeader title={ (
<Link to={ `/dashboard/crops/${e.uuid}/edit` }>
{ e.title }
</Link>)
}/>
<Divider/>
<CardContent>
{ e.code }
</CardContent>
</Card>
</Grid>
))
}
</Grid>
);
}
}
const mapStateToProps = (state, ownProps) => ({
crops: state.crop.list,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
listCrops,
}, dispatch);
const styled = withStyles(styles)(BrowsePage);
export default connect(mapStateToProps, mapDispatchToProps)(styled);
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {withStyles} from 'material-ui/styles';
import Grid from 'material-ui/Grid';
import Paper from 'material-ui/Paper';
import {loadCrop, saveCrop} from 'actions/crop';
import {Crop} from 'model/crop.model';
import CropForm from './c/CropForm';
interface IDescriptorEditPageProps extends React.ClassAttributes<any> {
classes: any;
uuid?: string;
loadCrop: (uuid: string) => void;
saveCrop: (crop: Crop) => void;
crop: Crop;
}
const styles = (theme) => ({
contentContainer: {
backgroundColor: '#E8E5E0',
padding: '1rem',
},
form: {
padding: '20px',
margin: '0 0 1rem 0',
},
});
class CropEditPage extends React.Component<IDescriptorEditPageProps, any> {
protected static needs = [
({params: {uuid}}) => loadCrop(uuid),
];
public componentDidMount() {
const {crop, loadCrop, uuid} = this.props;
if (uuid && (!crop || crop.uuid !== uuid)) {
loadCrop(uuid);
}
}
public onSave = (updatedCrop: Crop) => {
this.props.saveCrop(updatedCrop);
}
public render() {
const {classes, uuid} = this.props;
let {crop} = this.props;
if (!crop && !uuid) {
crop = new Crop();
}
if (!crop) {
console.log('No crop.');
return null;
}
return (
<Grid container className={ classes.contentContainer }>
<Grid item xs={ 12 }>
<Paper className={ classes.form }>
<CropForm initialValues={ crop } onSubmit={ this.onSave }/>
</Paper>
</Grid>
</Grid>
);
}
}
const mapStateToProps = (state, ownProps) => ({
uuid: ownProps.params.uuid,
crop: state.crop.currentCrop,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadCrop,
saveCrop,
}, dispatch);
const styled = withStyles(styles)(CropEditPage);
export default connect(mapStateToProps, mapDispatchToProps)(styled);
import * as React from 'react';
import {Link} from 'react-router';
import {Field, reduxForm} from 'redux-form';
import Button from 'material-ui/Button';
import {CROP_FORM} from 'constants/crop';
import {TextField} from 'ui/common/text-field';
const CropForm = ({error, handleSubmit, initialValues}) => {
return (
<form onSubmit={ handleSubmit }>
{ initialValues && initialValues.version && <div>Version: { initialValues.version }</div> }
<Field name="code" label="Crop code" component={ TextField }/>
<Field required name="title" label="Crop title" component={ TextField }/>
<div>{ error && <strong>{ error }</strong> }</div>
<Button raised type="submit">Save changes</Button>
<Link to="/dashboard/crops"><Button type="button">Back to dashboard</Button></Link>
</form>
);
};
export default reduxForm({
enableReinitialize: true,
form: CROP_FORM,
})(CropForm);
......@@ -38,6 +38,9 @@ import DescriptorListDisplayPage from './pages/descriptorlist/DisplayPage';
import DescriptorListEditPage from './pages/descriptorlist/EditPage';
import DescriptorListBrowsePage from './pages/descriptorlist/BrowsePage';
import CropBrowsePage from './pages/crop/BrowsePage';
import CropEditPage from './pages/crop/EditPage';
import guiTestingRoutes from './pages/ui-design';
export default(
......@@ -93,6 +96,11 @@ export default(
<IndexRoute component={ MyDataPage } title="Published data" basePath="/dashboard/data-published" filter={ { published: true } } />
<Route path=":tab" component={ MyDataPage } title="Published data" basePath="/dashboard/data-published" filter={ { published: true } } />
</Route>
<Route path="crops">
<IndexRoute component={ CropBrowsePage }/>
<Route path="create" component={ CropEditPage }/>
<Route path=":uuid/edit" component={ CropEditPage }/>
</Route>
<Route path=":tab" component={ DashboardPage } />
</Route>
</Route>
......
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