Commit b1f6fe02 authored by Maxym Borodenko's avatar Maxym Borodenko Committed by Matija Obreza
Browse files

Geo module

- with i18n
parent bf0da03d
......@@ -87,7 +87,7 @@
"users": {
"role": "Role",
"enabled": "Active",
"expired": "Exptired",
"expired": "Expired",
"locked": "Locked",
"email": "E-mail address",
"uuid": "UUID"
......@@ -170,15 +170,6 @@
}
}
}
},
"geo": {
"common": {
"location": "Location",
"latitude": "Latitude",
"longitude": "Longitude",
"address": "Address",
"country": "Country"
}
}
,"accessions": {
"public": {
......@@ -412,6 +403,57 @@
"cropList": "List of crops"
}
}
,"geo": {
"public": {
"p": {
"countryList": {
"title": "Country list",
"subTitle": "By clicking on a country name, you can find registered institutes in the country as well as statistics on plant genetic resources in the country as a whole.",
"acceCount": "{{count, number}} accessions",
"acceCountAtInstitutes": "{{count, number}} accessions at institutes in this country",
"institutesCountInWIEWS": "{{count, number}} institutes registered in WIEWS",
"instituteLocations": "Institute locations",
"moreInformation": "More information",
"isoCodes": "ISO",
"countryProfile": "Country profile"
},
"regionList": {
"title": "FAO Geographical regions",
"subTitle": "FAO Geographical regions lists below allow you to access the data about accessions collected or maintained in the region.",
"listOfSubRegions": "List of subregions",
"listOfCountries": "List of countries",
"b": {
"listAllFaoRegions": "List all FAO regions",
"showParentRegion": "Show parent region {{what, lowercase}}"
}
}
}
},
"common": {
"location": "Location",
"latitude": "Latitude",
"longitude": "Longitude",
"address": "Address",
"country": "Country",
"menu": "Countries"
}
}
,"list": {
"public": {
"p": {
"browse": {
"title": "Selected accessions",
"subTitle": "As you explore the millions of accessions held in Genesys, you can create your own list to keep track of the results of your search. Your selections are stored here so you can return to them at any time.",
"sendRequest": "Send request",
"noAccessions": "You have not added any accessions to the list."
}
}
},
"common": {
"menu": "My List"
}
}
,"institutes": {
"public": {
"c": {
......@@ -458,21 +500,6 @@
"accessionsInGenesys": "Accessions in Genesys"
}
}
,"list": {
"public": {
"p": {
"browse": {
"title": "Selected accessions",
"subTitle": "As you explore the millions of accessions held in Genesys, you can create your own list to keep track of the results of your search. Your selections are stored here so you can return to them at any time.",
"sendRequest": "Send request",
"noAccessions": "You have not added any accessions to the list."
}
}
},
"common": {
"menu": "My List"
}
}
,"repository": {
"admin": {
"p": {
......
......@@ -207,15 +207,7 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
</Properties>
{ hasLatLon &&
<LocationMap
location={
{
id: accession.geo.id,
lat: accession.geo.latitude,
lng: accession.geo.longitude,
}
}
/>
<LocationMap locations={ [{ id: accession.geo.id, lat: accession.geo.latitude, lng: accession.geo.longitude }] }/>
}
</PageSection>
}
......
......@@ -41,7 +41,7 @@ class BrowsePage extends React.Component<IBrowsePageProps> {
<ContentHeaderWithButton buttons={ <ActionButton title={ t('crop.public.p.browse.createCrop') } action={ this.addNewCropHandle } style={ {margin: '4px', padding: '0'} }/> }/>
</Authorize>
<PageContents>
<GridLayout>
<GridLayout style={ { width: 'auto', margin: '8px 6px' } }>
{ crops && crops.sort((a, b) => a.name.localeCompare(b.name)).map((crop) => <CropCard key={ crop.shortName } crop={ crop } compact />) }
</GridLayout>
</PageContents>
......
import {log} from 'utilities/debug';
import GeoService from 'service/genesys/GeoService';
import {IReducerAction} from 'model/common.model';
import {RECEIVE_COUNTRIES, RECEIVE_COUNTRY_DETAILS, RECEIVE_REGION_DETAILS, RECEIVE_REGIONS} from 'geo/constants';
import CountryDetails from 'model/geo/CountryDetails';
import Country from 'model/geo/Country';
import GeoRegion from 'model/geo/GeoRegion';
import RegionDetails from 'model/geo/RegionDetails';
const receiveCountries = (countries: Country[]): IReducerAction => ({
type: RECEIVE_COUNTRIES, payload: countries,
});
const receiveCountryDetails = (countryDetails: CountryDetails): IReducerAction => ({
type: RECEIVE_COUNTRY_DETAILS, payload: countryDetails,
});
const receiveRegions = (regions: GeoRegion[]): IReducerAction => ({
type: RECEIVE_REGIONS, payload: regions,
});
const receiveRegionDetails = (regionDetails: RegionDetails): IReducerAction => ({
type: RECEIVE_REGION_DETAILS, payload: regionDetails,
});
export const loadCountries = () => (dispatch, getState) => {
return GeoService.listCountries()
.then((list: Country[]) => {
dispatch(receiveCountries(list));
})
.catch((error) => {
log('Error', error);
});
};
export const loadRegions = () => (dispatch, getState) => {
return GeoService.getGeoRegions()
.then((list: GeoRegion[]) => {
dispatch(receiveRegions(list));
})
.catch((error) => {
log('Error', error);
});
};
export const loadCountryDetails = (iso3code: string) => (dispatch, getState) => {
return GeoService.getCountryDetails(iso3code)
.then((details: CountryDetails) => {
dispatch(receiveCountryDetails(details));
})
.catch((error) => {
log('Error', error);
});
};
export const loadRegionDetails = (isoCode: string) => (dispatch, getState) => {
return GeoService.getGeoRegion(isoCode)
.then((details: RegionDetails) => {
dispatch(receiveRegionDetails(details));
})
.catch((error) => {
log('Error', error);
});
};
export const RECEIVE_COUNTRIES = 'App/Geo/RECEIVE_COUNTRIES';
export const RECEIVE_REGIONS = 'App/Geo/RECEIVE_REGIONS';
export const RECEIVE_COUNTRY_DETAILS = 'App/Geo/RECEIVE_COUNTRY_DETAILS';
export const RECEIVE_REGION_DETAILS = 'App/Geo/RECEIVE_REGION_DETAILS';
import { combineReducers } from 'redux';
import geoPublic from './public';
const rootReducer = combineReducers({
public: geoPublic,
});
export default rootReducer;
import update from 'immutability-helper';
import { IReducerAction } from 'model/common.model';
import {RECEIVE_COUNTRIES, RECEIVE_COUNTRY_DETAILS, RECEIVE_REGIONS, RECEIVE_REGION_DETAILS} from 'geo/constants';
const INITIAL_STATE = {
countryList: null,
countryDetails: null,
regionList: null,
regionDetails: null,
};
export default function geo(state = INITIAL_STATE, action: IReducerAction = {type: ''}) {
switch (action.type) {
case RECEIVE_COUNTRIES: {
return update(state, {
countryList: {$set: action.payload},
});
}
case RECEIVE_COUNTRY_DETAILS: {
return update(state, {
countryDetails: {$set: action.payload},
});
}
case RECEIVE_REGIONS: {
return update(state, {
regionList: {$set: action.payload},
});
}
case RECEIVE_REGION_DETAILS: {
return update(state, {
regionDetails: {$set: action.payload},
});
}
default:
return state;
}
}
// Root
import CountryListPage from 'geo/ui/CountryListPage';
import CountryDisplayPage from 'geo/ui/CountryDisplayPage';
import RegionListPage from 'geo/ui/RegionListPage';
import RegionDisplayPage from 'geo/ui/RegionDisplayPage';
const publicRoutes = [
// Root
{
path: '/geo/regions',
component: RegionListPage,
exact: true,
},
{
path: '/geo/region/:isoCode',
component: RegionDisplayPage,
exact: true,
},
{
path: '/geo/:isoCode',
component: CountryDisplayPage,
exact: true,
},
{
path: '/geo/',
component: CountryListPage,
exact: true,
},
];
export {publicRoutes as geoPublicRoutes};
{
"public": {
"p": {
"countryList": {
"title": "Country list",
"subTitle": "By clicking on a country name, you can find registered institutes in the country as well as statistics on plant genetic resources in the country as a whole.",
"acceCount": "{{count, number}} accessions",
"acceCountAtInstitutes": "{{count, number}} accessions at institutes in this country",
"institutesCountInWIEWS": "{{count, number}} institutes registered in WIEWS",
"instituteLocations": "Institute locations",
"moreInformation": "More information",
"isoCodes": "ISO",
"countryProfile": "Country profile"
},
"regionList": {
"title": "FAO Geographical regions",
"subTitle": "FAO Geographical regions lists below allow you to access the data about accessions collected or maintained in the region.",
"listOfSubRegions": "List of subregions",
"listOfCountries": "List of countries",
"b": {
"listAllFaoRegions": "List all FAO regions",
"showParentRegion": "Show parent region {{what, lowercase}}"
}
}
}
},
"common": {
"location": "Location",
"latitude": "Latitude",
"longitude": "Longitude",
"address": "Address",
"country": "Country",
"menu": "Countries"
}
}
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { translate } from 'react-i18next';
// Actions
import {loadCountryDetails} from 'geo/actions/public';
import {applyFilters} from 'accessions/actions/public';
// Model
import CountryDetails from 'model/geo/CountryDetails';
import FaoInstitute from 'model/genesys/FaoInstitute';
// UI
import PageLayout, {MainSection, PageContents, PageSection} from 'ui/layout/PageLayout';
import {Properties, PropertiesItem} from 'ui/common/Properties';
import {InstituteLink} from 'ui/genesys/Links';
import {ExternalLink} from 'ui/common/Links';
import ContentHeader from 'ui/common/heading/ContentHeader';
import LocationMap from 'ui/common/LocationMap';
import Loading from 'ui/common/Loading';
import Number from 'ui/common/Number';
interface ICountryDisplayPageProps extends React.ClassAttributes<any> {
details: CountryDetails;
isoCode: string;
t: any;
loadCountryDetails: (isoCode: string) => void;
applyFilters: any;
}
class CountryDisplayPage extends React.Component<ICountryDisplayPageProps> {
protected static needs = [
({ params: { isoCode } }) => {
return isoCode ? loadCountryDetails(isoCode) : null;
},
];
constructor(props) {
super(props);
}
public componentWillMount() {
const { loadCountryDetails, isoCode } = this.props;
if (isoCode) {
loadCountryDetails(isoCode);
}
}
private getLocations = (institutes: FaoInstitute[]) => {
const instLocations = [];
institutes.forEach((inst) => {
if (inst.longitude != null && inst.longitude != null) {
instLocations.push({ id: inst.id, lat: inst.latitude, lng: inst.longitude });
}
});
return instLocations;
}
private applyCountryOfOriginFilter = (iso3Code: string) => {
const filter = {
origin: {iso3: [ iso3Code ]},
};
this.props.applyFilters(filter);
}
public render() {
const {details, t} = this.props;
const stillLoading: boolean = (! details);
return (
<PageLayout>
<ContentHeader title={ `${t(`geo.public.p.countryList.countryProfile`) }` }/>
<div>
{ stillLoading ? <Loading /> :
<PageContents>
<MainSection title={ `${details.name}` }>
<Properties>
<PropertiesItem title={ t(`geo.public.p.countryList.moreInformation`) }>
<ExternalLink link={ details.wikiLink }>{ details.wikiLink }</ExternalLink>
</PropertiesItem>
<PropertiesItem title={ `${t(`geo.public.p.countryList.isoCodes`)}` }>
<span>{ `ISO-3166 3-alpha: ${details.code3}, ISO-3166 2-alpha: ${details.code2}` }</span>
</PropertiesItem>
<PropertiesItem title={ t(`institutes.common.accessionsInGenesys`) }>
<a onClick={ () => this.applyCountryOfOriginFilter(details.code3) }><Number value={ details.accessionCount || 0 } /></a>
</PropertiesItem>
</Properties>
</MainSection>
{ details.genesysInstitutes && details.genesysInstitutes.length > 0 &&
<PageSection title={ `${t(`geo.public.p.countryList.acceCountAtInstitutes`, {count: details.countByLocation}) }` }>
<Properties>
{ details.genesysInstitutes.map((institute, index) => (
<PropertiesItem key={ `${institute.id}-${institute.code}-genesys` } numeric
title={
<span>
{ `${index + 1}` } <br/>
<InstituteLink to={ institute }>
{ `${institute.code}${institute.fullName}` }
</InstituteLink>
</span>
}>{ `${t(`geo.public.p.countryList.acceCount`, {count: institute.accessionCount}) }` }</PropertiesItem>
)) }
</Properties>
</PageSection>
}
{ details.faoInstitutes && details.faoInstitutes.length > 0 &&
<PageSection title={ `${t(`geo.public.p.countryList.institutesCountInWIEWS`, {count: details.faoInstitutes.length}) }` }>
<Properties>
{ details.faoInstitutes.map((fao, index) => (
<PropertiesItem key={ `${fao.id}-${fao.code}-fao` }
title={
<span>
{ `${index + 1}` } <br/>
<InstituteLink to={ fao }>
{ `${fao.code}${fao.fullName}` }
</InstituteLink>
</span>
} keepEmpty/>
)) }
</Properties>
</PageSection>
}
{ details.genesysInstitutes && details.genesysInstitutes.length > 0 &&
<PageSection title={ t(`geo.public.p.countryList.instituteLocations`) }>
<LocationMap locations={ this.getLocations(details.genesysInstitutes) } />
</PageSection>
}
</PageContents>
}
</div>
</PageLayout>
);
}
}
const mapStateToProps = (state, ownProps) => ({
details: state.geo.public.countryDetails || undefined,
isoCode: ownProps.match.params.isoCode,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadCountryDetails,
applyFilters,
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(translate()(CountryDisplayPage));
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { translate } from 'react-i18next';
// Models
import Country from 'model/geo/Country';
// Actions
import {loadCountries} from 'geo/actions/public';
// UI
import PageLayout, { PageContents } from 'ui/layout/PageLayout';
import ContentHeader from 'ui/common/heading/ContentHeader';
import GridLayout from 'ui/layout/GridLayout';
import CountryCard from 'geo/ui/c/CountryCard';
import Loading from 'ui/common/Loading';
interface ICountryListPageProps extends React.ClassAttributes<any> {
t: any;
countries: Country[];
loadCountries: () => void;
}
class CountryListPage extends React.Component<ICountryListPageProps> {
public static needs = [
() => loadCountries(),
];
constructor(props) {
super(props);
}
public componentWillMount() {
const { loadCountries, countries } = this.props;
if (!countries) {
loadCountries();
}
}
public render() {
const {countries, t} = this.props;
const stillLoading: boolean = (! countries);
return (
<PageLayout>
<ContentHeader
title={ t(`geo.public.p.countryList.title`) }
subTitle={ t(`geo.public.p.countryList.subTitle`) }
/>
<PageContents>
{ stillLoading ? <Loading /> :
<GridLayout style={ { width: 'auto', margin: '8px 6px' } }>
{
countries && countries.sort((a, b) => a.name.localeCompare(b.name)).map((country: Country) => (
<CountryCard key={ country.name } country={ country }/>
))
}
</GridLayout>
}
</PageContents>
</PageLayout>
);
}
}
const mapStateToProps = (state, ownProps) => ({
countries: state.geo.public.countryList || undefined,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadCountries,
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(translate()(CountryListPage));
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { translate } from 'react-i18next';
// Models
import GeoRegion from 'model/geo/GeoRegion';
import Country from 'model/geo/Country';
import RegionDetails from 'model/geo/RegionDetails';
// Actions
import {loadRegionDetails} from 'geo/actions/public';
import navigateTo from 'actions/navigation';
// UI
import PageLayout, { PageContents } from 'ui/layout/PageLayout';
import ContentHeader from 'ui/common/heading/ContentHeader';
import ContentHeaderWithButton from 'ui/common/heading/ContentHeaderWithButton';
import GridLayout from 'ui/layout/GridLayout';
import Loading from 'ui/common/Loading';
import GeoRegionCard from 'geo/ui/c/GeoRegionCard';
import CountryCard from 'geo/ui/c/CountryCard';
import ActionButton from 'ui/common/buttons/ActionButton';
interface IRegionDisplayPageProps extends React.ClassAttributes<any> {
details: RegionDetails;
isoCode: string;
t: any;
i18n: any;
loadRegionDetails: (isoCode: string) => void;
navigateTo: (path: string) => void;
}
class RegionDisplayPage extends React.Component<IRegionDisplayPageProps> {
protected static needs = [
({ params: { isoCode } }) => {
return isoCode ? loadRegionDetails(isoCode) : null;