DisplayPage.tsx 7.66 KB
Newer Older
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
1
2
3
4
5
6
7
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {translate} from 'react-i18next';

// actions
import {loadMoreNetworkInstitutes, loadNetwork} from 'networks/actions/public';
8
9
10
import { deleteNetwork } from 'networks/actions/admin';
import { applyFilters, applyOverviewFilters } from 'accessions/actions/public';
import { navigateTo } from 'actions/navigation';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
11
12
13
// model
import ApiCall from 'model/ApiCall';
import MapLayer from 'model/genesys/MapTileLayer';
Matija Obreza's avatar
Matija Obreza committed
14
import Page, { IPageRequest } from 'model/Page';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
15
import FaoInstitute from 'model/genesys/FaoInstitute';
16
17
import PGRFANetwork from 'model/network/PGRFANetwork';
import PGRFANetworkDetails from 'model/network/PGRFANetworkDetails';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
18
19
// ui
import InstituteCard from 'institutes/ui/с/InstituteCard';
20
import PageLayout, {PageContents, PageSection, MainSection} from 'ui/layout/PageLayout';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
21
22
23
24
25
26
27
import Loading from 'ui/common/Loading';
import {ScrollToTopOnMount} from 'ui/common/page/scrollers';
import ContentHeader from 'ui/common/heading/ContentHeader';
import PageTitle from 'ui/common/PageTitle';
import LocationMap from 'ui/common/LocationMap';
import PagedLoader from 'ui/common/PagedLoader';
import {InstituteLink} from 'ui/genesys/Links';
28
29
30
31
32
33
import { PropertiesItem, Properties } from 'ui/common/Properties';
import BlurbText from 'cms/ui/c/BlurbText';
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';
Matija Obreza's avatar
Matija Obreza committed
34
import AccessionFilter from 'model/accession/AccessionFilter';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
35
36

interface IDisplayPageProps extends React.ClassAttributes<any> {
37
  networkCall: ApiCall<PGRFANetworkDetails>;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
38
39
40
41
  mapLayers: MapLayer[];
  shortName: string;
  loadNetwork: (shortName: string, lang: string) => void;
  loadMoreNetworkInstitutes: (shortName: string, page: number) => void;
Matija Obreza's avatar
Matija Obreza committed
42
43
  applyFilters: (filters: string | AccessionFilter, page?: IPageRequest) => any;
  applyOverviewFilters: (filters: string | AccessionFilter) => any;
44
45
  deleteNetwork: (network: PGRFANetwork) => any;
  navigateTo: any;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
46
47
48
49
50
51
52
53
54
55
56
  t: any;
  i18n: any;
}

class DisplayPage extends React.Component<IDisplayPageProps> {

  protected static needs = [
    ({ params: { shortName }, state }) => loadNetwork(shortName, state.applicationConfig.lang),
  ];

  public componentWillMount(): void {
57
58
    const {networkCall, shortName, loadNetwork, i18n} = this.props;
    if (!networkCall) {
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
59
60
      return loadNetwork(shortName, i18n.language);
    }
61
    const {loading, data: network} = networkCall;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
62

63
    if (!loading && (!network || !network.network)) {
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
64
65
66
      return loadNetwork(shortName, i18n.language);
    }

67
    if (network.network.slug !== shortName) {
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
      return loadNetwork(shortName, i18n.language);
    }

  }

  private loadMoreNetworkMembers = (page: Page<FaoInstitute>) => {
    const {shortName, loadMoreNetworkInstitutes} = this.props;
    return loadMoreNetworkInstitutes(shortName, page.number + 1);
  }

  private renderInstitute = (s: FaoInstitute, index: number) => {
    return <InstituteCard key={ s.code } index={ index } institute={ s }/>;
  }

82
83
  private applyNetworkFilter = () => {
    const { networkCall: { data: networkDetails }, applyFilters} = this.props;
Matija Obreza's avatar
Matija Obreza committed
84
    const filter = { institute: { networks: [networkDetails.network.slug] } };
85
86
87
88
89
    applyFilters(filter);
  }

  private applyNetworkOverviewFilter = () => {
    const { networkCall: { data: networkDetails }, applyOverviewFilters} = this.props;
Matija Obreza's avatar
Matija Obreza committed
90
    const filter = { institute: { networks: [networkDetails.network.slug] } };
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
    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);
    });
  }

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
106
  public render(): React.ReactNode {
107
108
109
    const {networkCall, mapLayers, t} = this.props;
    const {data: networkDetails, loading, error} = networkCall || {data: undefined, loading: true, error: undefined};
    const {network, blurb, institutes } = networkDetails || {network: undefined, blurb: undefined, institutes: undefined};
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
110
111
112
113
114
115
116
117
118
119
120

    return (
      <PageLayout withFooter>
        <ScrollToTopOnMount/>
        <PageTitle title={ !loading && network ? network.title || network.slug : t('common:label.loading', {what: t('networks.public.p.display.title')}) }/>
        <ContentHeader title={ !loading && network ? network.title || network.slug : t('common:label.loading', {what: t('networks.public.p.display.title')}) }/>
        <div>
          { loading && <Loading/> }
          { error && <div>{ JSON.stringify(error) }</div> }
          { network &&
          <PageContents className="pt-1rem">
Oleksii Savran's avatar
Oleksii Savran committed
121
122
123
124
125
126
127
128
129
130
131
132
            <MainSection
              title={ t('networks.public.p.display.title') }
              cardActions={
                <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>
              }
            >
133
134
135
136
137
138
139
140
141
142
              { 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>
              </Properties>
            </MainSection>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
143
144
145
            { institutes && institutes.content && institutes.content.length > 0 &&
            <PageSection title={ t('networks.common.locations') }>
                <LocationMap
Oleksii Savran's avatar
Oleksii Savran committed
146
147
148
149
150
151
152
153
154
                    locations={ institutes.content
                      .filter((institute) => !!institute.latitude && !!institute.longitude)
                      .map(
                      (institute) => ({
                        id: institute.id,
                        lat: institute.latitude,
                        lng: institute.longitude,
                        popup: <InstituteLink key={ institute.code } to={ institute }>{ institute.fullName }</InstituteLink>,
                      }))
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
                    }
                    mapLayers={ mapLayers }
                />
            </PageSection>
            }
            <div className="container-spacing-horizontal pt-1rem">
              <PagedLoader paged={ institutes } itemRenderer={ this.renderInstitute } loadMore={ this.loadMoreNetworkMembers }/>
            </div>
          </PageContents>
          }
        </div>
      </PageLayout>
    );
  }
}

const mapStateToProps = (state, ownProps) => ({
172
  networkCall: state.networks.public.network,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
173
174
175
176
177
178
179
180
181
182
  memberCodes: state.networks.public.memberCodes,
  blurb: state.networks.public.blurb,
  members: state.networks.public.members,
  shortName: ownProps.match.params.shortName,
  mapLayers: state.accessions.public.mapLayers,
});

const mapDispatchToProps = (dispatch) => bindActionCreators({
  loadNetwork,
  loadMoreNetworkInstitutes,
183
184
185
186
  deleteNetwork,
  applyOverviewFilters,
  applyFilters,
  navigateTo,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
187
188
189
}, dispatch);

export default translate()((connect(mapStateToProps, mapDispatchToProps)(DisplayPage)));