Commit 2549a290 authored by Viacheslav Pavlov's avatar Viacheslav Pavlov Committed by Matija Obreza
Browse files

Added institutePicker for partner

parent 19149319
......@@ -1303,6 +1303,9 @@
"phonePlaceholder": "+1 555 1231 Ext. 13",
"shortName": "Short name or acronym",
"websites": "Data provider websites"
},
"institutePicker": {
"search": "Institute WIEWS code"
}
}
},
......
import Country from 'model/geo/Country';
import { SortDirection } from 'model/Page';
import Partner from 'model/genesys/Partner';
import { IUserPermissions, Permissions } from 'model/acl/ACL';
/*
......@@ -26,6 +27,7 @@ class FaoInstitute implements IUserPermissions {
public settings: any;
public type: string;
public uniqueAcceNumbs: boolean;
public owner: Partner;
public url: string;
public urls: string[];
public vCode: string;
......
import { push } from 'react-router-redux';
// Actions
import { receivePartner, receivePartnerInstitutes } from 'partners/actions/public';
import { loadPartner } from 'partners/actions/editor';
import { loadPartnerNames } from 'actions/uuidDecoder';
// Constants
import { DASHBOARD_GET_PARTNER, DASHBOARD_RECEIVE_PARTNER, DASHBOARD_CREATE_PARTNER, DASHBOARD_RECEIVE_MY_PARTNERLIST } from 'partners/constants';
import { DASHBOARD_CREATE_PARTNER, DASHBOARD_RECEIVE_MY_PARTNERLIST } from 'partners/constants';
// Model
import Partner from 'model/genesys/Partner';
......@@ -17,9 +19,6 @@ import PartnerService from 'service/catalog/PartnerService';
// Util
import { log } from 'utilities/debug';
const receivePartner = (partner: Partner): IReducerAction => ({
type: DASHBOARD_RECEIVE_PARTNER, payload: partner,
});
const receiveMyPartnerList = (partners: Partner[]): IReducerAction => ({
type: DASHBOARD_RECEIVE_MY_PARTNERLIST, payload: partners,
});
......@@ -36,21 +35,6 @@ export const loadMyPartners = () => (dispatch, getState) => {
});
};
// Just load a record
export const loadPartner = (uuid: string) => (dispatch, getState) => {
log('Loading partner', uuid);
dispatch({ type: DASHBOARD_GET_PARTNER, payload: uuid });
return PartnerService.getPartner(uuid)
// receive the current partner
.then((partner) => {
return dispatch(receivePartner(partner));
}).catch((error) => {
log(`No partner with uuid ${uuid}`, error);
});
};
// Create a new record
export const createPartner = () => (dispatch) => {
log('Create new partner');
......@@ -61,5 +45,7 @@ export const createPartner = () => (dispatch) => {
export const editPartner = (uuid: string) => (dispatch, getState) => {
dispatch(loadPartner(uuid));
dispatch(receivePartner(null));
dispatch(receivePartnerInstitutes(null));
dispatch(push(`/admin/partners/${uuid}/edit`));
};
......@@ -2,11 +2,13 @@ import { push } from 'react-router-redux';
import { SubmissionError } from 'redux-form';
// Constants
import { DASHBOARD_RECEIVE_PARTNER } from 'partners/constants';
import { DASHBOARD_GET_PARTNER, DASHBOARD_RECEIVE_PARTNER, DASHBOARD_RECEIVE_PARTNER_INSTITUTES, DASHBOARD_REMOVE_PARTNER_INSTITUTES } from 'partners/constants';
// Model
import Partner from 'model/genesys/Partner';
import { IReducerAction } from 'model/common.model';
import Page from 'model/Page';
import FaoInstitute from 'model/genesys/FaoInstitute';
// Service
import PartnerService from 'service/catalog/PartnerService';
......@@ -18,6 +20,15 @@ const receivePartner = (partner: Partner): IReducerAction => ({
type: DASHBOARD_RECEIVE_PARTNER, payload: partner,
});
const receivePartnerInstitutes = (institutes: Page<FaoInstitute>): IReducerAction => ({
type: DASHBOARD_RECEIVE_PARTNER_INSTITUTES, payload: institutes,
});
const removePartnerInstitutesFromState = (institutes: string[]): IReducerAction => ({
type: DASHBOARD_REMOVE_PARTNER_INSTITUTES, payload: institutes,
});
const showPartner = (uuid: string) => (dispatch) => {
log('Navigating to Partner details');
dispatch(push(`/partners/${uuid}`));
......@@ -46,3 +57,48 @@ export const deletePartner = (partner: Partner) => (dispatch, getState) => {
log('Error', error);
});
};
// Just load a record
export const loadPartner = (uuid: string) => (dispatch, getState) => {
log('Loading partner', uuid);
dispatch({ type: DASHBOARD_GET_PARTNER, payload: uuid });
return PartnerService.getPartner(uuid)
// receive the current partner
.then((partner) => {
const partnerInstitutes = getState().partner.dashboard.partnerInstitutes;
if (partnerInstitutes && partnerInstitutes.content && partnerInstitutes.content.length > 0 && partnerInstitutes.content[0].owner.uuid !== uuid) {
dispatch(loadPartnerInstitutes(partner.uuid));
}
return dispatch(receivePartner(partner));
}).catch((error) => {
log(`No partner with uuid ${uuid}`, error);
});
};
export const loadPartnerInstitutes = (uuid: string) => (dispatch) => {
return PartnerService.listInstitutes(uuid)
.then((institutes) => dispatch(receivePartnerInstitutes(institutes)));
};
export const addPartnerInstitutes = (uuid: string, instCodes: string[]) => (dispatch) => {
return PartnerService.addInstitutes(uuid, instCodes)
.then((partner) => {
dispatch(receivePartnerInstitutes(null));
return partner;
});
};
export const removePartnerInstitutes = (partnerUuid: string, instCodes: string[]) => (dispatch) => {
return PartnerService.removeInstitutes(partnerUuid, instCodes)
.then((partner) => {
dispatch(receivePartner(partner));
dispatch(removePartnerInstitutesFromState(instCodes));
});
};
export const removePartnerInstitute = (partnerUuid: string, instCode: string) => (dispatch) => {
return dispatch(removePartnerInstitutes(partnerUuid, [instCode]));
};
......@@ -5,11 +5,12 @@ import navigateTo from 'actions/navigation';
import { showSnackbar } from 'actions/snackbar';
// Constants
import { GET_PARTNER, RECEIVE_PARTNER, RECEIVE_PARTNERS, APPEND_PARTNERS } from 'partners/constants';
import {GET_PARTNER, RECEIVE_PARTNER, RECEIVE_PARTNERS, APPEND_PARTNERS, RECEIVE_PARTNER_INSTITUTES} from 'partners/constants';
// Model
import { IReducerAction } from 'model/common.model';
import FaoInstitute from 'model/genesys/FaoInstitute';
import Page from 'model/Page';
import Partner from 'model/genesys/Partner';
import PartnerFilter from 'model/genesys/PartnerFilter';
......@@ -37,6 +38,10 @@ const receivePartner = (partner: Partner): IReducerAction => ({
type: RECEIVE_PARTNER, payload: partner,
});
const receivePartnerInstitutes = (institutes: Page<FaoInstitute>): IReducerAction => ({
type: RECEIVE_PARTNER_INSTITUTES, payload: institutes,
});
// Just load a record
export const loadPartner = (uuid: string) => (dispatch, getState) => {
log('Loading partner', uuid);
......@@ -90,8 +95,13 @@ const loadMorePartners = (paged: FilteredPage<Vocabulary>) => (dispatch, getStat
});
};
export const loadPartnerInstitutes = (uuid: string) => (dispatch) => {
return PartnerService.listInstitutes(uuid)
.then((institutes) => dispatch(receivePartnerInstitutes(institutes)));
};
export {
loadPartners, receivePartner, loadMorePartners,
loadPartners, receivePartner, loadMorePartners, receivePartnerInstitutes,
};
export const updateRoute = (paged: FilteredPage<Partner>) => (dispatch) => {
......
......@@ -3,6 +3,7 @@ export const CREATE_PARTNER = 'App/Partner/CREATE_PARTNER';
export const PARTNER_FORM = 'Form/Partner/PARTNER_FORM';
export const GET_PARTNER = 'App/Partner/GET_PARTNER';
export const RECEIVE_PARTNER = 'App/Partner/RECEIVE_PARTNER';
export const RECEIVE_PARTNER_INSTITUTES = 'App/Partner/RECEIVE_PARTNER_INSTITUTES';
// export const FINISH_EDIT_PARTNER = 'App/Partner/FINISH_EDIT_PARTNER';
// export const DELETE_PARTNER = 'App/DELETE_PARTNER';
......@@ -18,6 +19,8 @@ export const RECEIVE_MY_PARTNERLIST = 'App/Partner/RECEIVE_MY_PARTNERLIST';
// dashboard
export const DASHBOARD_GET_PARTNER = 'partner/dashboard/GET_PARTNER';
export const DASHBOARD_RECEIVE_PARTNER = 'partner/dashboard/RECEIVE_PARTNER';
export const DASHBOARD_RECEIVE_PARTNER_INSTITUTES = 'partner/dashboard/RECEIVE_PARTNER_INSTITUTES';
export const DASHBOARD_REMOVE_PARTNER_INSTITUTES = 'partner/dashboard/REMOVE_PARTNER_INSTITUTES';
export const DASHBOARD_CREATE_PARTNER = 'partner/dashboard/CREATE_PARTNER';
export const DASHBOARD_RECEIVE_MY_PARTNERLIST = 'partner/dashboard/RECEIVE_MY_PARTNERLIST';
......@@ -2,11 +2,12 @@ import update from 'immutability-helper';
import { IReducerAction } from 'model/common.model';
import Partner from 'model/genesys/Partner';
import { DASHBOARD_CREATE_PARTNER, DASHBOARD_GET_PARTNER, DASHBOARD_RECEIVE_PARTNER, DASHBOARD_RECEIVE_MY_PARTNERLIST } from 'partners/constants';
import { DASHBOARD_REMOVE_PARTNER_INSTITUTES, DASHBOARD_CREATE_PARTNER, DASHBOARD_GET_PARTNER, DASHBOARD_RECEIVE_PARTNER, DASHBOARD_RECEIVE_MY_PARTNERLIST, DASHBOARD_RECEIVE_PARTNER_INSTITUTES } from 'partners/constants';
const INITIAL_STATE = {
myPartners: [], // contains list of user's Partners
currentPartner: null,
partnerInstitutes: null,
loading: null,
};
......@@ -27,6 +28,23 @@ export default function partner(state = INITIAL_STATE, action: IReducerAction =
});
}
case DASHBOARD_RECEIVE_PARTNER_INSTITUTES: {
return update(state, {
partnerInstitutes: { $set: action.payload },
});
}
case DASHBOARD_REMOVE_PARTNER_INSTITUTES: {
const instCodesToRemove = action.payload;
const newInstitutes = state.partnerInstitutes.content.filter((inst) => !instCodesToRemove.includes(inst));
return update(state, {
partnerInstitutes: {
content: {$set: newInstitutes},
},
});
}
// set the currentPartner to a blank new object
case DASHBOARD_CREATE_PARTNER: {
return update(state, {
......
import update from 'immutability-helper';
import { IReducerAction } from 'model/common.model';
import { GET_PARTNER, RECEIVE_PARTNER, LIST_PARTNERS, RECEIVE_PARTNERS, APPEND_PARTNERS } from 'partners/constants';
import { GET_PARTNER, RECEIVE_PARTNER, LIST_PARTNERS, RECEIVE_PARTNERS, APPEND_PARTNERS, RECEIVE_PARTNER_INSTITUTES } from 'partners/constants';
const INITIAL_STATE = {
currentPartner: null,
partnerInstitutes: null,
paged: null,
pagedQuery: null,
loading: null,
......@@ -32,6 +33,11 @@ export default function partner(state = INITIAL_STATE, action: IReducerAction =
loading: { $set: null },
});
}
case RECEIVE_PARTNER_INSTITUTES: {
return update(state, {
partnerInstitutes: { $set: action.payload },
});
}
// set the paged to whatever came in
case RECEIVE_PARTNERS: {
// log('Marking loaded pagedQuery', action.payload);
......
......@@ -8,6 +8,9 @@
"phonePlaceholder": "+1 555 1231 Ext. 13",
"shortName": "Short name or acronym",
"websites": "Data provider websites"
},
"institutePicker": {
"search": "Institute WIEWS code"
}
}
},
......
......@@ -4,9 +4,12 @@ import { bindActionCreators } from 'redux';
import { translate } from 'react-i18next';
import { deletePartner } from 'partners/actions/editor';
import { loadPartner, editPartner } from 'partners/actions/dashboard';
import { editPartner } from 'partners/actions/dashboard';
import { loadPartner, loadPartnerInstitutes } from 'partners/actions/public';
import Partner from 'model/genesys/Partner';
import FaoInstitute from 'model/genesys/FaoInstitute';
import Page from 'model/Page';
import confirm from 'utilities/confirmAlert';
import Loading from 'ui/common/Loading';
......@@ -19,7 +22,6 @@ import Card, { CardHeader, CardContent, CardActions } from 'ui/common/Card';
import Button from '@material-ui/core/Button';
import Permissions from 'ui/common/permission/Permissions';
import PageLayout from 'ui/layout/PageLayout';
import PartnerService from 'service/catalog/PartnerService';
interface IPartnerPageProps extends React.ClassAttributes<any> {
classes: any;
......@@ -27,8 +29,10 @@ interface IPartnerPageProps extends React.ClassAttributes<any> {
uuid?: string;
partner?: Partner;
partnerInstitutes: Page<FaoInstitute>;
loading?: any;
loadPartner: any;
loadPartnerInstitutes: any;
editPartner: any;
deletePartner: any;
}
......@@ -38,12 +42,9 @@ class PartnerPage extends React.Component<IPartnerPageProps, any> {
protected static needs = [
({ params: { uuid } }) => loadPartner(uuid),
({ params: { uuid } }) => loadPartnerInstitutes(uuid),
];
public state = {
partnerInstitutes: null,
};
private onEditPartner = (e) => {
const { partner, editPartner } = this.props;
editPartner(partner.uuid);
......@@ -63,32 +64,33 @@ class PartnerPage extends React.Component<IPartnerPageProps, any> {
}
public componentWillMount() {
const { uuid, partner, loadPartner } = this.props;
const {uuid, partner, loadPartner, partnerInstitutes, loadPartnerInstitutes} = this.props;
if (uuid && (!partner || partner.uuid !== uuid)) {
console.log(`cwm: Loading partner ${uuid}`, partner);
loadPartner(uuid);
// TODO temporary solution
PartnerService.listInstitutes(uuid).then((partnerInstitutes) => this.setState({partnerInstitutes}));
if (uuid && (!partnerInstitutes || partnerInstitutes.content && partnerInstitutes.content.length > 0 && partnerInstitutes.content[0].owner.uuid !== uuid)) {
loadPartnerInstitutes(uuid);
}
}
}
public componentWillReceiveProps(nextProps) {
const { uuid, partner, loading, loadPartner } = nextProps;
const {uuid, partner, loading, loadPartner, partnerInstitutes, loadPartnerInstitutes} = nextProps;
if (uuid && (!partner || partner.uuid !== uuid)) {
if (!loading || loading.uuid !== uuid) {
console.log(`cwrp: Loading partner ${uuid}`, partner, loading);
loadPartner(uuid);
// TODO temporary solution
PartnerService.listInstitutes(uuid).then((partnerInstitutes) => this.setState({partnerInstitutes}));
}
if (uuid && partner && (!partnerInstitutes || partnerInstitutes.content && partnerInstitutes.content.length > 0 && partnerInstitutes.content[0].owner.uuid !== partner.uuid)) {
loadPartnerInstitutes(uuid);
}
}
}
public render() {
const { t, uuid, partner } = this.props;
const { partnerInstitutes } = this.state;
const { t, uuid, partner, partnerInstitutes } = this.props;
const stillLoading: boolean = (!partner || (uuid && (partner.uuid !== uuid)));
......@@ -118,7 +120,7 @@ class PartnerPage extends React.Component<IPartnerPageProps, any> {
{ partnerInstitutes && partnerInstitutes.content && partnerInstitutes.content.length > 0 && (
<PropertiesItem title={ t('partners.common.wiewsCodes') }>
{ partnerInstitutes.content.map((institute) => (
<div key={ institute.uuid }><FaoWiewsLink wiewsCode={ institute.code }>{ institute.code }</FaoWiewsLink></div>
<div key={ institute.code } style={ {marginTop: '.25em', width: '100%'} }><FaoWiewsLink wiewsCode={ institute.code }>{ institute.code }</FaoWiewsLink></div>
)) }
</PropertiesItem>
) }
......@@ -162,12 +164,14 @@ class PartnerPage extends React.Component<IPartnerPageProps, any> {
const mapStateToProps = (state, ownProps) => ({
uuid: ownProps.match.params.uuid,
partner: state.partner.dashboard.currentPartner,
loading: state.partner.dashboard.loading,
partner: state.partner.public.currentPartner,
partnerInstitutes: state.partner.public.partnerInstitutes,
loading: state.partner.public.loading,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadPartner,
loadPartnerInstitutes,
editPartner,
deletePartner,
}, dispatch);
......
......@@ -3,20 +3,27 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { translate } from 'react-i18next';
import { savePartner } from 'partners/actions/editor';
import { loadPartner } from 'partners/actions/dashboard';
import {savePartner, loadPartner, loadPartnerInstitutes, removePartnerInstitute, addPartnerInstitutes } from 'partners/actions/editor';
import Partner from 'model/genesys/Partner';
import Page from 'model/Page';
import FaoInstitute from 'model/genesys/FaoInstitute';
import PartnerForm from './c/PartnerForm';
import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';
import Loading from 'ui/common/Loading';
interface IPartnerEditPageProps extends React.ClassAttributes<any> {
classes: any;
uuid?: string;
loading?: any;
partner?: Partner;
partnerInstitutes: Page<FaoInstitute>;
loadPartner: any;
addPartnerInstitutes: any;
loadPartnerInstitutes: any;
removePartnerInstitute: any;
savePartner: any;
t: any;
}
......@@ -26,36 +33,62 @@ class PartnerEditPage extends React.Component<IPartnerEditPageProps, any> {
protected static needs = [
({ params: { uuid } }) => loadPartner(uuid),
({ params: { uuid } }) => loadPartnerInstitutes(uuid),
];
public onSave = (partner) => {
const { savePartner } = this.props;
const {savePartner, addPartnerInstitutes} = this.props;
savePartner(partner);
addPartnerInstitutes(partner.uuid, partner.institutes.map((inst) => inst.code))
.then((newPartner) => {
partner.version = newPartner.version;
savePartner(partner);
});
}
public componentWillMount() {
const { uuid, partner, loadPartner } = this.props;
const {uuid, partner, loadPartner, partnerInstitutes, loadPartnerInstitutes} = this.props;
if (uuid && !partner) {
if (uuid && ! partner) {
loadPartner(uuid);
}
if (uuid && (!partnerInstitutes || (partnerInstitutes.content && partnerInstitutes.content.length > 0 && partnerInstitutes.content[0].owner.uuid !== uuid))) {
loadPartnerInstitutes(uuid);
}
}
public componentWillReceiveProps(nextProps) {
const {uuid, partner, loading, loadPartner, partnerInstitutes, loadPartnerInstitutes} = nextProps;
if (uuid && ! partner && !loading) {
loadPartner(uuid);
}
if (uuid && partner && (!partnerInstitutes || (partnerInstitutes.content && partnerInstitutes.content.length > 0 && partnerInstitutes.content[0].owner.uuid !== uuid))) {
loadPartnerInstitutes(uuid);
}
}
public render() {
const { t } = this.props;
const { t, partnerInstitutes, removePartnerInstitute } = this.props;
let { partner } = this.props;
if (!partner) {
partner = new Partner();
}
const institutes = partnerInstitutes && partnerInstitutes.content;
return (
<Grid item xs={ 12 }>
<Paper className="p-20">
<PartnerForm
initialValues={ partner }
onSubmit={ this.onSave }
t={ t }/>
{ partner && partnerInstitutes ?
<PartnerForm
initialValues={ {...partner, institutes} }
onSubmit={ this.onSave }
removePartnerInstitute={ removePartnerInstitute }
t={ t }
/>
:
<Loading/>
}
</Paper>
</Grid>
);
......@@ -64,11 +97,16 @@ class PartnerEditPage extends React.Component<IPartnerEditPageProps, any> {
const mapStateToProps = (state, ownProps) => ({
uuid: ownProps.match.params.uuid,
loading: state.partner.dashboard.loading,
partner: state.partner.dashboard.currentPartner,
partnerInstitutes: state.partner.dashboard.partnerInstitutes,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadPartner,
loadPartnerInstitutes,
addPartnerInstitutes,
removePartnerInstitute,
savePartner,
}, dispatch);
......
import * as React from 'react';
import { translate } from 'react-i18next';
import { Field } from 'redux-form';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import Input from '@material-ui/core/Input';
import TextField from '@material-ui/core/TextField';
import FormControl from 'ui/common/forms/FormControl';
import Select from '@material-ui/core/Select';
import Markdown from 'ui/common/markdown';
import VocabularyService from 'service/catalog/VocabularyService';
interface ISelectFaoInstituteInternal extends React.ClassAttributes<any> {
input: any;
label: string;
meta?: any;
t: any;
}
class SelectFaoInstituteInternal extends React.Component<ISelectFaoInstituteInternal, any> {
protected handleInputChange = (event) => {
this.setState({searchText: event.target.value});
if (event.target.value) {
VocabularyService.autocompleteWiewsTerm(event.target.value).then((suggestions) => {
this.setState({suggestions});
});
}
}
protected handleClick = (event) => {
this.setState({open: true, anchorEl: event.currentTarget});
}
protected handleRequestClose = () => {
this.setState({open: false});
}
protected select = (value) => (event) => {
const {input} = this.props;
const institute = this.state.suggestions.find((inst) => inst.code === value);
if (institute) {
input.onChange({code: institute.code});
this.setState({
open: false,
pickerList: {code: institute.code, title: institute.title},
});
} else {
input.onChange('');
this.setState({
open: false,
pickerList: null,
});
}
}
private constructor(props, context) {
super(props, context);
this.state = {
disabled: false,
pickerList: null,
open: false,
anchorEl: null,
searchText: '',
suggestions: [],
};
}
public componentWillMount() {
const {input: {value}} = this.props;
if (value) {
this.setState({
pickerList: {
code: value.code,
title: value.fullName || value.code,
},
disabled: true,
});
}