Commit 57367762 authored by Matija Obreza's avatar Matija Obreza
Browse files

PGRFA Networks: Code refactored and updated

- Models renamed
- Delete PGRFA network
- Added missing translations changes
parent b3439a26
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
}, },
"holder": { "holder": {
"code": "Holder", "code": "Holder",
"networks": "Network",
"owner": { "owner": {
"uuid": "Data provider" "uuid": "Data provider"
}, },
...@@ -1751,6 +1752,32 @@ ...@@ -1751,6 +1752,32 @@
"menu": "My List" "menu": "My List"
} }
}, },
"networks": {
"public": {
"c": {
"card": {
"title": "Title",
"slug": "Short name",
"createdDate": "Date of creation"
}
},
"p": {
"display": {
"actions": "Browse or download data",
"title": "Network details",
"browseAccessions": "Browse accessions",
"overview": "Accession overview",
"deleteNetwork": "Delete network {{slug}}?"
},
"networkBrowse": {
"title": "Browse networks"
}
}
},
"common": {
"locations": "Members locations"
}
},
"partners": { "partners": {
"admin": { "admin": {
"c": { "c": {
......
...@@ -20,7 +20,7 @@ const ArticleFilters = ({ handleSubmit, initialValues, initialize, t, ...other } ...@@ -20,7 +20,7 @@ const ArticleFilters = ({ handleSubmit, initialValues, initialize, t, ...other }
<StringFilter name="title" label={ t('cms.admin.f.title') } searchType="contains"/> <StringFilter name="title" label={ t('cms.admin.f.title') } searchType="contains"/>
</CollapsibleComponentSearch> </CollapsibleComponentSearch>
<CollapsibleComponentSearch title={ t('cms.admin.f.meta') }> <CollapsibleComponentSearch title={ t('cms.admin.f.meta') }>
<StringArrFilter name="slug" label="cms.admin.f.slug" placeholder="blurp"/> <StringArrFilter name="slug" label="cms.admin.f.slug" placeholder="blurb"/>
<StringArrFilter name="lang" label="cms.admin.f.lang" placeholder="en"/> <StringArrFilter name="lang" label="cms.admin.f.lang" placeholder="en"/>
</CollapsibleComponentSearch> </CollapsibleComponentSearch>
</FiltersBlock> </FiltersBlock>
......
/*
* Defined in Swagger as '#/definitions/OrganizationBlurbJson'
*/
class OrganizationBlurbJson {
public blurp: string;
public locale: string;
public summary: string;
}
export default OrganizationBlurbJson;
import { Permissions, IUserPermissions } from 'model/acl/ACL';
/* /*
* Defined in Swagger as '#/definitions/Organization' * Defined in Swagger as '#/definitions/PGRFANetwork'
*/ */
class Organization { class PGRFANetwork implements IUserPermissions {
public static clazz: string = 'org.genesys2.server.model.impl.PGRFANetwork';
public _permissions: Permissions;
public active: boolean; public active: boolean;
public createdBy: number; public createdBy: number;
public createdDate: Date; public createdDate: Date;
...@@ -13,7 +17,6 @@ class Organization { ...@@ -13,7 +17,6 @@ class Organization {
public title: string; public title: string;
public version: number; public version: number;
} }
export default Organization; export default PGRFANetwork;
import Article from 'model/cms/Article'; import Article from 'model/cms/Article';
import Organization from 'model/network/Organization'; import PGRFANetwork from 'model/network/PGRFANetwork';
import Page from 'model/Page'; import Page from 'model/Page';
import FaoInstitute from 'model/genesys/FaoInstitute'; import FaoInstitute from 'model/genesys/FaoInstitute';
/* /*
* Defined in Swagger as '#/definitions/OrganizationDetails' * Defined in Swagger as '#/definitions/PGRFANetworkDetails'
*/ */
class OrganizationDetails { class PGRFANetworkDetails {
public blurb: Article; public blurb: Article;
public institutes: Page<FaoInstitute>; public institutes: Page<FaoInstitute>;
public organization: Organization; public network: PGRFANetwork;
} }
export default OrganizationDetails; export default PGRFANetworkDetails;
// actions
// constants
// service
import NetworkService from 'service/genesys/NetworkService';
import PGRFANetwork from 'model/network/PGRFANetwork';
export const deleteNetwork = (network: PGRFANetwork) => (dispatch, getState) => {
return NetworkService.deleteNetwork(network.slug, network.version);
};
...@@ -3,14 +3,14 @@ import update from 'immutability-helper'; ...@@ -3,14 +3,14 @@ import update from 'immutability-helper';
import { IReducerAction } from 'model/common.model'; import { IReducerAction } from 'model/common.model';
import Page from 'model/Page'; import Page from 'model/Page';
import ApiCall from 'model/ApiCall'; import ApiCall from 'model/ApiCall';
import Organization from 'model/network/Organization'; import PGRFANetwork from 'model/network/PGRFANetwork';
import OrganizationDetails from 'model/network/OrganizationDetails'; import PGRFANetworkDetails from 'model/network/PGRFANetworkDetails';
// constants // constants
import {APPEND_NETWORK_PAGE, RECEIVE_NETWORK_DETAILS, RECEIVE_NETWORK_INSTITUTES} from 'networks/constants'; import {APPEND_NETWORK_PAGE, RECEIVE_NETWORK_DETAILS, RECEIVE_NETWORK_INSTITUTES} from 'networks/constants';
const INITIAL_STATE: { const INITIAL_STATE: {
networks: ApiCall<Organization[]>, networks: ApiCall<PGRFANetwork[]>,
network: ApiCall<OrganizationDetails>, network: ApiCall<PGRFANetworkDetails>,
} = { } = {
networks: null, networks: null,
network: null, network: null,
......
...@@ -8,8 +8,12 @@ ...@@ -8,8 +8,12 @@
} }
}, },
"p": { "p": {
"display":{ "display": {
"title": "Network details" "actions": "Browse or download data",
"title": "Network details",
"browseAccessions": "Browse accessions",
"overview": "Accession overview",
"deleteNetwork": "Delete network {{slug}}?"
}, },
"networkBrowse": { "networkBrowse": {
"title": "Browse networks" "title": "Browse networks"
......
...@@ -6,7 +6,7 @@ import { translate } from 'react-i18next'; ...@@ -6,7 +6,7 @@ import { translate } from 'react-i18next';
import {listNetworks} from 'networks/actions/public'; import {listNetworks} from 'networks/actions/public';
// model // model
import ApiCall from 'model/ApiCall'; import ApiCall from 'model/ApiCall';
import Organization from 'model/network/Organization'; import PGRFANetwork from 'model/network/PGRFANetwork';
// ui // ui
import PageLayout, {PageContents} from 'ui/layout/PageLayout'; import PageLayout, {PageContents} from 'ui/layout/PageLayout';
import ContentHeader from 'ui/common/heading/ContentHeader'; import ContentHeader from 'ui/common/heading/ContentHeader';
...@@ -16,7 +16,7 @@ import NetworkCard from 'networks/ui/c/NetworkCard'; ...@@ -16,7 +16,7 @@ import NetworkCard from 'networks/ui/c/NetworkCard';
interface IBrowsePageProps extends React.ClassAttributes<any> { interface IBrowsePageProps extends React.ClassAttributes<any> {
apiCall: ApiCall<Organization[]>; apiCall: ApiCall<PGRFANetwork[]>;
listNetworks: () => void; listNetworks: () => void;
t: any; t: any;
} }
...@@ -46,7 +46,7 @@ class BrowsePage extends React.Component<IBrowsePageProps> { ...@@ -46,7 +46,7 @@ class BrowsePage extends React.Component<IBrowsePageProps> {
{ loading ? <Loading /> : { loading ? <Loading /> :
<div className="full-width container-spacing-horizontal"> <div className="full-width container-spacing-horizontal">
{ {
networks && networks.sort((a, b) => a.title.localeCompare(b.title)).map((network: Organization) => ( networks && networks.sort((a, b) => a.title.localeCompare(b.title)).map((network: PGRFANetwork) => (
<NetworkCard compact key={ network.slug } network={ network }/> <NetworkCard compact key={ network.slug } network={ network }/>
)) ))
} }
......
...@@ -5,16 +5,19 @@ import {translate} from 'react-i18next'; ...@@ -5,16 +5,19 @@ import {translate} from 'react-i18next';
// actions // actions
import {loadMoreNetworkInstitutes, loadNetwork} from 'networks/actions/public'; import {loadMoreNetworkInstitutes, loadNetwork} from 'networks/actions/public';
import { deleteNetwork } from 'networks/actions/admin';
import { applyFilters, applyOverviewFilters } from 'accessions/actions/public';
import { navigateTo } from 'actions/navigation';
// model // model
import ApiCall from 'model/ApiCall'; import ApiCall from 'model/ApiCall';
import MapLayer from 'model/genesys/MapTileLayer'; import MapLayer from 'model/genesys/MapTileLayer';
import Page from 'model/Page'; import Page from 'model/Page';
import FaoInstitute from 'model/genesys/FaoInstitute'; import FaoInstitute from 'model/genesys/FaoInstitute';
import OrganizationDetails from 'model/network/OrganizationDetails'; import PGRFANetwork from 'model/network/PGRFANetwork';
import PGRFANetworkDetails from 'model/network/PGRFANetworkDetails';
// ui // ui
import NetworkCard from 'networks/ui/c/NetworkCard';
import InstituteCard from 'institutes/ui/с/InstituteCard'; import InstituteCard from 'institutes/ui/с/InstituteCard';
import PageLayout, {PageContents, PageSection} from 'ui/layout/PageLayout'; import PageLayout, {PageContents, PageSection, MainSection} from 'ui/layout/PageLayout';
import Loading from 'ui/common/Loading'; import Loading from 'ui/common/Loading';
import {ScrollToTopOnMount} from 'ui/common/page/scrollers'; import {ScrollToTopOnMount} from 'ui/common/page/scrollers';
import ContentHeader from 'ui/common/heading/ContentHeader'; import ContentHeader from 'ui/common/heading/ContentHeader';
...@@ -22,13 +25,25 @@ import PageTitle from 'ui/common/PageTitle'; ...@@ -22,13 +25,25 @@ import PageTitle from 'ui/common/PageTitle';
import LocationMap from 'ui/common/LocationMap'; import LocationMap from 'ui/common/LocationMap';
import PagedLoader from 'ui/common/PagedLoader'; import PagedLoader from 'ui/common/PagedLoader';
import {InstituteLink} from 'ui/genesys/Links'; import {InstituteLink} from 'ui/genesys/Links';
import { PropertiesItem, Properties } from 'ui/common/Properties';
import BlurbText from 'cms/ui/c/BlurbText';
import PrettyDate from 'ui/common/time/PrettyDate';
import { CardActions } from 'ui/common/Card';
import ButtonBar from 'ui/common/buttons/ButtonBar';
import { Button } from '@material-ui/core';
import confirmAlert from 'utilities/confirmAlert';
import Authorize from 'ui/common/authorized/Authorize';
interface IDisplayPageProps extends React.ClassAttributes<any> { interface IDisplayPageProps extends React.ClassAttributes<any> {
apiCall: ApiCall<OrganizationDetails>; networkCall: ApiCall<PGRFANetworkDetails>;
mapLayers: MapLayer[]; mapLayers: MapLayer[];
shortName: string; shortName: string;
loadNetwork: (shortName: string, lang: string) => void; loadNetwork: (shortName: string, lang: string) => void;
loadMoreNetworkInstitutes: (shortName: string, page: number) => void; loadMoreNetworkInstitutes: (shortName: string, page: number) => void;
applyFilters: any;
applyOverviewFilters: any;
deleteNetwork: (network: PGRFANetwork) => any;
navigateTo: any;
t: any; t: any;
i18n: any; i18n: any;
} }
...@@ -40,17 +55,17 @@ class DisplayPage extends React.Component<IDisplayPageProps> { ...@@ -40,17 +55,17 @@ class DisplayPage extends React.Component<IDisplayPageProps> {
]; ];
public componentWillMount(): void { public componentWillMount(): void {
const {apiCall, shortName, loadNetwork, i18n} = this.props; const {networkCall, shortName, loadNetwork, i18n} = this.props;
if (!apiCall) { if (!networkCall) {
return loadNetwork(shortName, i18n.language); return loadNetwork(shortName, i18n.language);
} }
const {loading, data: network} = apiCall; const {loading, data: network} = networkCall;
if (!loading && (!network || !network.organization)) { if (!loading && (!network || !network.network)) {
return loadNetwork(shortName, i18n.language); return loadNetwork(shortName, i18n.language);
} }
if (network.organization.slug !== shortName) { if (network.network.slug !== shortName) {
return loadNetwork(shortName, i18n.language); return loadNetwork(shortName, i18n.language);
} }
...@@ -65,10 +80,34 @@ class DisplayPage extends React.Component<IDisplayPageProps> { ...@@ -65,10 +80,34 @@ class DisplayPage extends React.Component<IDisplayPageProps> {
return <InstituteCard key={ s.code } index={ index } institute={ s }/>; return <InstituteCard key={ s.code } index={ index } institute={ s }/>;
} }
private applyNetworkFilter = () => {
const { networkCall: { data: networkDetails }, applyFilters} = this.props;
const filter = {holder: {networks: [ networkDetails.network.slug ]}};
applyFilters(filter);
}
private applyNetworkOverviewFilter = () => {
const { networkCall: { data: networkDetails }, applyOverviewFilters} = this.props;
const filter = {holder: {networks: [ networkDetails.network.slug ]}};
applyOverviewFilters(filter);
}
private onDelete = () => {
const { networkCall: { data: networkDetails }, deleteNetwork, navigateTo, t } = this.props;
confirmAlert(t('networks.public.p.display.deleteNetwork', { slug: networkDetails.network.slug }))
.then(() => {
deleteNetwork(networkDetails.network).then(() => {
navigateTo('/network');
});
}).catch((error) => {
console.log(`Couldn't delete network`, error);
});
}
public render(): React.ReactNode { public render(): React.ReactNode {
const {apiCall, mapLayers, t} = this.props; const {networkCall, mapLayers, t} = this.props;
const {data: networkDetails, loading, error} = apiCall || {data: undefined, loading: true, error: undefined}; const {data: networkDetails, loading, error} = networkCall || {data: undefined, loading: true, error: undefined};
const {organization: network, blurb, institutes } = networkDetails || {organization: undefined, blurb: undefined, institutes: undefined}; const {network, blurb, institutes } = networkDetails || {network: undefined, blurb: undefined, institutes: undefined};
return ( return (
<PageLayout withFooter> <PageLayout withFooter>
...@@ -80,12 +119,32 @@ class DisplayPage extends React.Component<IDisplayPageProps> { ...@@ -80,12 +119,32 @@ class DisplayPage extends React.Component<IDisplayPageProps> {
{ error && <div>{ JSON.stringify(error) }</div> } { error && <div>{ JSON.stringify(error) }</div> }
{ network && { network &&
<PageContents className="pt-1rem"> <PageContents className="pt-1rem">
<NetworkCard key={ network.slug } network={ network } blurbBody={ blurb.body }/> <MainSection title={ t('networks.public.p.display.title') }>
{ blurb &&
<div className="mb-20">
<BlurbText body={ blurb.body } />
</div>
}
<Properties>
<PropertiesItem title={ t('networks.public.c.card.title') }>{ network.title }</PropertiesItem>
<PropertiesItem title={ t('networks.public.c.card.slug') }>{ network.slug }</PropertiesItem>
<PropertiesItem title={ t('networks.public.c.card.createdDate') }><PrettyDate value={ network.createdDate }/></PropertiesItem>
</Properties>
<CardActions className="container-spacing-vertical mt-15">
<ButtonBar barLabelText={ t('networks.public.p.display.actions') }>
<Button onClick={ this.applyNetworkFilter }>{ t('networks.public.p.display.browseAccessions') }</Button>
<Button onClick={ this.applyNetworkOverviewFilter }>{ t('networks.public.p.display.overview') }</Button>
<Authorize role="ROLE_ADMINISTRATOR">
<Button onClick={ this.onDelete }>{ t('common:action.delete') }</Button>
</Authorize>
</ButtonBar>
</CardActions>
</MainSection>
{ institutes && institutes.content && institutes.content.length > 0 && { institutes && institutes.content && institutes.content.length > 0 &&
<PageSection title={ t('networks.common.locations') }> <PageSection title={ t('networks.common.locations') }>
<LocationMap <LocationMap
locations={ institutes.content.map( locations={ institutes.content.map(
(institute) => ({id: institute.id, lat: institute.latitude, lng: institute.longitude, popup: <InstituteLink to={ institute }>{ institute.fullName }</InstituteLink>})) (institute) => ({id: institute.id, lat: institute.latitude, lng: institute.longitude, popup: <InstituteLink key={ institute.code } to={ institute }>{ institute.fullName }</InstituteLink>}))
} }
mapLayers={ mapLayers } mapLayers={ mapLayers }
/> />
...@@ -103,7 +162,7 @@ class DisplayPage extends React.Component<IDisplayPageProps> { ...@@ -103,7 +162,7 @@ class DisplayPage extends React.Component<IDisplayPageProps> {
} }
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
apiCall: state.networks.public.network, networkCall: state.networks.public.network,
memberCodes: state.networks.public.memberCodes, memberCodes: state.networks.public.memberCodes,
blurb: state.networks.public.blurb, blurb: state.networks.public.blurb,
members: state.networks.public.members, members: state.networks.public.members,
...@@ -114,6 +173,10 @@ const mapStateToProps = (state, ownProps) => ({ ...@@ -114,6 +173,10 @@ const mapStateToProps = (state, ownProps) => ({
const mapDispatchToProps = (dispatch) => bindActionCreators({ const mapDispatchToProps = (dispatch) => bindActionCreators({
loadNetwork, loadNetwork,
loadMoreNetworkInstitutes, loadMoreNetworkInstitutes,
deleteNetwork,
applyOverviewFilters,
applyFilters,
navigateTo,
}, dispatch); }, dispatch);
export default translate()((connect(mapStateToProps, mapDispatchToProps)(DisplayPage))); export default translate()((connect(mapStateToProps, mapDispatchToProps)(DisplayPage)));
import * as React from 'react'; import * as React from 'react';
import {translate} from 'react-i18next'; import { translate } from 'react-i18next';
import {withStyles} from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
// model // model
import Organization from 'model/network/Organization'; import PGRFANetwork from 'model/network/PGRFANetwork';
// ui // ui
import PrettyDate from 'ui/common/time/PrettyDate'; import PrettyDate from 'ui/common/time/PrettyDate';
import {Properties, PropertiesItem} from 'ui/common/Properties'; import Card, { CardHeader } from 'ui/common/Card';
import Card, {CardHeader} from 'ui/common/Card'; import { NetworkLink } from 'ui/catalog/Links';
import {NetworkLink} from 'ui/catalog/Links';
import {MainSection} from 'ui/layout/PageLayout';
import BlurbText from 'cms/ui/c/BlurbText';
// import { Properties, PropertiesItem } from 'ui/catalog/Properties'; // import { Properties, PropertiesItem } from 'ui/catalog/Properties';
interface INetworkCardProps extends React.ClassAttributes<any> { interface INetworkCardProps extends React.ClassAttributes<any> {
network: Organization; network: PGRFANetwork;
blurbBody: string;
compact: boolean;
classes: any; classes: any;
t: any; t: any;
} }
...@@ -64,13 +59,13 @@ const styles = (theme) => ({ ...@@ -64,13 +59,13 @@ const styles = (theme) => ({
class NetworkCard extends React.Component<INetworkCardProps, any> { class NetworkCard extends React.Component<INetworkCardProps, any> {
public render() { public render() {
const {network, blurbBody, compact = false, classes, t} = this.props; const {network, classes, t} = this.props;
if (!network) { if (!network) {
return null; return null;
} }
return compact ? ( return (
<Card square> <Card square>
<CardHeader <CardHeader
classes={ { classes={ {
...@@ -81,19 +76,6 @@ class NetworkCard extends React.Component<INetworkCardProps, any> { ...@@ -81,19 +76,6 @@ class NetworkCard extends React.Component<INetworkCardProps, any> {
subheader={ network.createdDate && <span>{ t('common:label.registered') } <PrettyDate value={ network.createdDate }/></span> } subheader={ network.createdDate && <span>{ t('common:label.registered') } <PrettyDate value={ network.createdDate }/></span> }
/> />
</Card> </Card>
) : (
<MainSection title={ t('networks.public.p.display.title') }>
{ blurbBody &&
<div className="mb-20">
<BlurbText body={ blurbBody } />
</div>
}
<Properties>
<PropertiesItem title={ t('networks.public.c.card.title') }>{ network.title }</PropertiesItem>
<PropertiesItem title={ t('networks.public.c.card.slug') }>{ network.slug }</PropertiesItem>
<PropertiesItem title={ t('networks.public.c.card.createdDate') }><PrettyDate value={ network.createdDate }/></PropertiesItem>
</Properties>
</MainSection>
); );
} }
......
...@@ -5,9 +5,8 @@ import { axiosBackend } from 'utilities/requestUtils'; ...@@ -5,9 +5,8 @@ import { axiosBackend } from 'utilities/requestUtils';
import Article from 'model/cms/Article'; import Article from 'model/cms/Article';
import FaoInstitute from 'model/genesys/FaoInstitute'; import FaoInstitute from 'model/genesys/FaoInstitute';
import Organization from 'model/network/Organization'; import PGRFANetwork from 'model/network/PGRFANetwork';
import OrganizationBlurbJson from 'model/network/OrganizationBlurbJson'; import PGRFANetworkDetails from 'model/network/PGRFANetworkDetails';
import OrganizationDetails from 'model/network/OrganizationDetails';
import Page from 'model/Page'; import Page from 'model/Page';
const URL_LIST_NETWORKS = `/api/v1/network`; const URL_LIST_NETWORKS = `/api/v1/network`;
...@@ -33,7 +32,7 @@ class NetworkService { ...@@ -33,7 +32,7 @@ class NetworkService {
* @param page page * @param page page
* @param xhrConfig additional xhr config * @param xhrConfig additional xhr config
*/ */
public static listNetworks(page?: number, xhrConfig?: any): Promise<Organization[]> { public static listNetworks(page?: number, xhrConfig?: any): Promise<PGRFANetwork[]> {
const qs = QueryString.stringify({ const qs = QueryString.stringify({
page: page || undefined, page: page || undefined,
...@@ -47,7 +46,7 @@ class NetworkService { ...@@ -47,7 +46,7 @@ class NetworkService {
url: apiUrl, url: apiUrl,
method: 'GET', method: 'GET',
...content, ...content,
}).then(({ data }) => data as Organization[]); }).then(({ data }) => data as PGRFANetwork[]);
} }
/** /**
...@@ -56,7 +55,7 @@ class NetworkService { ...@@ -56,7 +55,7 @@ class NetworkService {
* @param organizationJson organizationJson * @param organizationJson organizationJson
* @param xhrConfig additional xhr config * @param xhrConfig additional xhr config
*/