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

// Actions
Matija Obreza's avatar
Matija Obreza committed
8
import { loadInstitute } from 'institutes/actions/public';
Oleksii Savran's avatar
Oleksii Savran committed
9
import { applyFilters, applyOverviewFilters } from 'accessions/actions/public';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
10
11

// Models
Matija Obreza's avatar
Matija Obreza committed
12
import FaoInstituteDetails from 'model/genesys/InstituteDetails';
Oleksii Savran's avatar
Oleksii Savran committed
13
import MapLayer from 'model/genesys/MapTileLayer';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
14
15

// UI
Matija Obreza's avatar
Matija Obreza committed
16
import PageLayout, { MainSection, PageContents, PageSection } from 'ui/layout/PageLayout';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
17
import GridContainer from 'ui/layout/GridContainer';
18
import PropertiesCard from 'ui/common/PropertiesCard.tsx';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
19
import ContentHeader from 'ui/common/heading/ContentHeader';
20
import LocationMap from 'ui/common/LocationMap';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
21
import Loading from 'ui/common/Loading';
22
import Number from 'ui/common/Number';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
23
import { ScrollToTopOnMount } from 'ui/common/page/scrollers';
Matija Obreza's avatar
Matija Obreza committed
24
import { Properties, PropertiesItem } from 'ui/common/Properties';
25
26
import PieChart from 'ui/common/pie-chart';
import PrettyDate from 'ui/common/time/PrettyDate';
Matija Obreza's avatar
Matija Obreza committed
27
import { CountryLink } from 'ui/genesys/Links';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
28
import BarChart from 'ui/common/bar-chart';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
29
30
31
32
import { CardActions } from 'ui/common/Card';
import Button from '@material-ui/core/Button';
import Permissions from 'ui/common/permission/Permissions';
import FaoInstitute from 'model/genesys/FaoInstitute';
Oleksii Savran's avatar
Oleksii Savran committed
33
import ButtonBar from 'ui/common/buttons/ButtonBar';
Matija Obreza's avatar
Matija Obreza committed
34
import DownloadDialog from 'ui/common/download-dialog';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
35
import PageTitle from 'ui/common/PageTitle';
Matija Obreza's avatar
Matija Obreza committed
36
import BlurbText from 'cms/ui/c/BlurbText';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
37

38
interface IDisplayPageProps extends React.ClassAttributes<any> {
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
39
  t: any;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
40
  classes?: any;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
41
  code: string;
42
  institute: FaoInstituteDetails;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
43
  error: any;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
44
  loading: boolean;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
45
  loadInstitute: any;
46
  applyFilters: any;
Oleksii Savran's avatar
Oleksii Savran committed
47
  applyOverviewFilters: any;
48
  userRoles: string[];
Oleksii Savran's avatar
Oleksii Savran committed
49
  mapLayers: MapLayer[];
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
50
51
}

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
52

53
class DisplayPage extends React.Component<IDisplayPageProps, any> {
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
54

55
  protected static needs = [
Matija Obreza's avatar
Matija Obreza committed
56
    ({ params: { wiewsCode } }) => loadInstitute(wiewsCode),
57
58
  ];

59
  constructor(props: IDisplayPageProps, context: any) {
60
    super(props, context);
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
61
62
  }

63
64
65
66
  public state = {
    authenticated: false,
  };

67
68
69
70
71
72
  private applyInstituteCodeFilter = () => {
    const { institute, applyFilters} = this.props;
    const filter = {holder: {code: [ institute.details.code ]}};
    applyFilters(filter);
  }

Oleksii Savran's avatar
Oleksii Savran committed
73
74
75
76
77
78
  private applyFilterForOverview = () => {
    const { institute, applyOverviewFilters } = this.props;
    const filter = {holder: {code: [ institute.details.code ]}};
    applyOverviewFilters(filter);
  }

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  private applyLastModifyDateFilter = (lastUpdateDate) => {
    const { institute, applyFilters} = this.props;
    const startOfDay = new Date(`${lastUpdateDate[0]}-${lastUpdateDate[1]}-${lastUpdateDate[2]}`);
    const endOfDay = new Date(`${lastUpdateDate[0]}-${lastUpdateDate[1]}-${lastUpdateDate[2]}`);
    startOfDay.setHours(0);
    endOfDay.setHours(23, 59, 59);

    const filter = {
      holder: {code: [ institute.details.code ]},
      lastModifiedDate: {
        ge: startOfDay,
        le: endOfDay,
      },
    };
    applyFilters(filter);
  }

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
96
  public componentWillMount() {
97
    const { institute, code, loadInstitute, userRoles } = this.props;
98
    if (code && (! institute || code !== institute.details.code)) {
Matija Obreza's avatar
Matija Obreza committed
99
100
      console.log(`Reloading institute data for code=${code}`, institute);
      loadInstitute(code);
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
101
    }
102
103
104

    const authenticated: boolean = userRoles.findIndex((role) => role === 'ROLE_USER') !== -1;
    this.setState({authenticated});
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
105
106
107
  }

  public render() {
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
108
    const { error, loading, institute, code, mapLayers, t } = this.props;
109
    const slug: string = this.state.authenticated ? 'download-authenticated' : 'download-anonymous';
110
111
112
113
114

    let cropShortNameOverview;
    let cropNameOverview;
    let taxonomyGenusOverview;
    let taxonomyGenusSpeciesOverview;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
115
    if (!loading) {
116
117
118
119
120
121
122
123
124
      const cropShortNameKey = 'crop.shortName';
      cropShortNameOverview = institute.overview[cropShortNameKey];
      const cropNameKey = 'cropName';
      cropNameOverview = institute.overview[cropNameKey];
      const taxonomyGenusKey = 'taxonomy.genus';
      taxonomyGenusOverview = institute.overview[taxonomyGenusKey];
      const taxonomyGenusSpeciesKey = 'taxonomy.genusSpecies';
      taxonomyGenusSpeciesOverview = institute.overview[taxonomyGenusSpeciesKey];
    }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
125
126

    return (
Oleksii Savran's avatar
Oleksii Savran committed
127
      <PageLayout withFooter>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
128
        <ScrollToTopOnMount />
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
129
130
        <PageTitle title={ !loading && institute ? institute.details.fullName || institute.details.code : t('common:label.loading', { what: t('institutes.public.p.display.title') }) } />
        <ContentHeader title={ !loading && institute ? institute.details.fullName || institute.details.code : t('common:label.loading', { what: t('institutes.public.p.display.title') }) } />
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
131

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
132
        { loading ? <Loading /> :
133
134
135
136
          <div>
            { error && <div>{ JSON.stringify(error) }</div> }

            { institute &&
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
137
            <PageContents className="pt-1rem">
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
138
                <MainSection title={ t('institutes.public.p.display.title') }>
Matija Obreza's avatar
Matija Obreza committed
139
                  { institute.blurb && institute.blurb.body &&
Matija Obreza's avatar
Matija Obreza committed
140
                      <div className="mb-20">
Matija Obreza's avatar
Matija Obreza committed
141
                        <BlurbText body={ institute.blurb.body } />
Matija Obreza's avatar
Matija Obreza committed
142
                      </div>
Matija Obreza's avatar
Matija Obreza committed
143
                  }
144
                  <Properties>
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
145
146
147
                    <PropertiesItem title={ t('institutes.common.instituteCode') }>{ institute.details.code }</PropertiesItem>
                    <PropertiesItem title={ t('institutes.public.p.display.type') }>{ institute.details.type }</PropertiesItem>
                    <PropertiesItem title={ t('geo.common.country') }>{ <CountryLink country={ institute.details.country }/> }</PropertiesItem>
148
                    { institute.details.url &&
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
149
                      <PropertiesItem title={ t('institutes.public.p.display.webLink') }>
150
151
                        <a href={ institute.details.url }> { institute.details.url }</a>
                      </PropertiesItem>
152
                    }
153
154
155
156
157
                    { institute.details.owner &&
                      <PropertiesItem title={ t('accessions.public.p.display.partner') }>
                        <b>{ institute.details.owner.shortName }</b> { institute.details.owner.name }
                      </PropertiesItem>
                    }
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
158
                    <PropertiesItem title={ t('institutes.common.accessionsInGenesys') }>
159
160
                      <a onClick={ this.applyInstituteCodeFilter }><Number value={ institute.details.accessionCount } /></a>
                    </PropertiesItem>
161
                  </Properties>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
162

Oleksii Savran's avatar
Oleksii Savran committed
163
                  <CardActions className="container-spacing-vertical mt-15">
164
                    <ButtonBar barLabelText={ t('institutes.public.p.display.actions') }>
Oleksii Savran's avatar
Oleksii Savran committed
165
166
                      <Button onClick={ this.applyInstituteCodeFilter }>{ t('institutes.public.p.display.browseAccessions') }</Button>
                      <Button onClick={ this.applyFilterForOverview }>{ t('accessions.tab.overview') }</Button>
167
                      { this.state.authenticated &&
Matija Obreza's avatar
Matija Obreza committed
168
                        <DownloadDialog downloadUrl={ `/proxy/api/v1/wiews/${code}/download` }
169
                          slug={ slug }
Matija Obreza's avatar
Matija Obreza committed
170
                          postParams={ { mcpd: 'mcpd' } }
171
172
173
                          buttonTitle={ `${t('common:action.download')} ${t('institutes.public.p.display.MCPD')}` } />
                      }
                      { this.state.authenticated &&
Matija Obreza's avatar
Matija Obreza committed
174
                          <DownloadDialog downloadUrl={ `/proxy/api/v1/wiews/${code}/download` }
175
                            slug={ slug }
Matija Obreza's avatar
Matija Obreza committed
176
                            postParams={ { pdci: 'pdci' } }
177
178
                            buttonTitle={ `${t('common:action.download')} ${t('institutes.public.p.display.PDCI_short')}` } />
                      }
Matija Obreza's avatar
Matija Obreza committed
179
                      <DownloadDialog downloadUrl={ `/proxy/api/v1/wiews/${code}/download` }
180
                        slug={ slug }
Matija Obreza's avatar
Matija Obreza committed
181
                        postParams={ { dwca: 'dwca' } }
182
                        buttonTitle={ `${t('common:action.download')} ${t('institutes.public.p.display.zip')}` } />
Oleksii Savran's avatar
Oleksii Savran committed
183
184
185
                      { institute.details._permissions.manage && <Link to={ `/dashboard/wiews/${institute.details.code}/edit` }><Button>{ t('common:action.edit') }</Button></Link> }
                      { institute.details._permissions.manage && <Permissions clazz={ FaoInstitute.clazz } id={ institute.details.id }/> }
                    </ButtonBar>
Oleksii Savran's avatar
Oleksii Savran committed
186
                  </CardActions>
187
                </MainSection>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
188

189
                { institute.details.latitude !== null && institute.details.longitude !== null &&
Matija Obreza's avatar
Matija Obreza committed
190
                  <PageSection title={ t('geo.common.location') }>
191
                    <LocationMap
Maxym Borodenko's avatar
Maxym Borodenko committed
192
                      locations={ [{ id: institute.details.id, lat: institute.details.latitude, lng: institute.details.longitude }] }
Oleksii Savran's avatar
Oleksii Savran committed
193
                      mapLayers={ mapLayers }
194
                    />
Matija Obreza's avatar
Matija Obreza committed
195
                    <Properties>
Oleksii Savran's avatar
Oleksii Savran committed
196
                      <PropertiesItem title={ t('geo.common.latitude') }>{ institute.details.latitude }</PropertiesItem>
Matija Obreza's avatar
Matija Obreza committed
197
198
                      <PropertiesItem title={ t('geo.common.longitude') }>{ institute.details.longitude }</PropertiesItem>
                    </Properties>
199
200
201
                  </PageSection>
                }

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
202
                <GridContainer className="mb-15">
203
204
                  { cropShortNameOverview && cropShortNameOverview.terms && cropShortNameOverview.terms.length > 0 &&
                    <PropertiesCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
205
                      title={ t('institutes.public.p.display.representedCrops') }
206
                      propertiesList={ cropShortNameOverview.terms.map((term) => ({title: term.term, value: term.count})) }
207
                      small propertyItemProps={ { numeric: true } }
208
                    />
209
                  }
210

211
212
                  { cropNameOverview && cropNameOverview.terms && cropNameOverview.terms.length > 0 &&
                    <PropertiesCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
213
                      title={ t('institutes.public.p.display.representedCropNames') }
214
                      propertiesList={ cropNameOverview.terms.slice(0, 5).map((term) => ({title: term.term, value: term.count})) }
215
                      small propertyItemProps={ { numeric: true } }
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
                    >
                      <PieChart
                        data={
                          cropNameOverview.terms.map(
                            (term) => ({
                              value: term.count,
                              label: term.term,
                            }),
                          )
                        }
                      />
                    </PropertiesCard>
                  }

                  { taxonomyGenusOverview && taxonomyGenusOverview.terms && taxonomyGenusOverview.terms.length > 0 &&
                    <PropertiesCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
232
                      title={ t('institutes.public.p.display.representedGenera') }
233
                      propertiesList={  taxonomyGenusOverview.terms.slice(0, 5).map((term) => ({title: term.term, value: term.count})) }
234
                      small propertyItemProps={ { numeric: true } }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
                    >
                      <PieChart
                        data={
                          taxonomyGenusOverview.terms.map(
                            (term) => ({
                              value: term.count,
                              label: term.term,
                            }),
                          )
                        }
                      />
                    </PropertiesCard>
                  }

                  { taxonomyGenusSpeciesOverview && taxonomyGenusSpeciesOverview.terms && taxonomyGenusSpeciesOverview.terms.length > 0 &&
                    <PropertiesCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
251
                      title={ t('institutes.public.p.display.representedSpecies') }
252
                      propertiesList={  taxonomyGenusSpeciesOverview.terms.slice(0, 5).map((term) => ({title: term.term, value: term.count})) }
253
                      small propertyItemProps={ { numeric: true } }
254
255
256
257
258
259
260
261
262
263
264
265
266
267
                    >
                      <PieChart
                        data={
                          taxonomyGenusSpeciesOverview.terms.map(
                            (term) => ({
                              value: term.count,
                              label: term.term,
                            }),
                          )
                        }
                      />
                    </PropertiesCard>
                  }

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
268
                </GridContainer>
269

270
                { institute.lastUpdates && institute.lastUpdates.length > 0 &&
Matija Obreza's avatar
Matija Obreza committed
271
                <PageSection title={ t('institutes.public.p.display.lastUpdates') }>
272
273
                  <Properties>
                    { institute.lastUpdates.map((lastUpdate) => (
274
                      <PropertiesItem key={ `${lastUpdate[0]}-${lastUpdate[1]}=${lastUpdate[2]}` }
Matija Obreza's avatar
Matija Obreza committed
275
                        numeric title={ <PrettyDate value={ new Date(lastUpdate[0], lastUpdate[1] - 1, lastUpdate[2]) } /> }>
276
277
                          <a onClick={ () => this.applyLastModifyDateFilter(lastUpdate) }><Number value={ lastUpdate[3] } /></a>
                      </PropertiesItem>
278
279
280
281
282
                    )) }
                  </Properties>
                </PageSection>
                }

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
283
                { institute.pdciStats && institute.pdciStats.histogram && institute.pdciStats.histogram.length > 0 &&
Matija Obreza's avatar
Matija Obreza committed
284
                  <PageSection title={ t('institutes.public.p.display.PDCI') }>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
285
                    <BarChart data={ institute.pdciStats.histogram.map((item, i) => ({key: i % 2 === 0 ? i / 2 : '', value: item })) }/>
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
286
287
                    <p className="mt-20">{ t('institutes.public.p.display.pdciScore', { count: institute.pdciStats.count, avg: institute.pdciStats.avg, min: institute.pdciStats.min, max: institute.pdciStats.max }) }</p>
                    <Link to="/content/passport-data-completeness-index">{ t('institutes.public.p.display.readPDCI') }</Link>
288
289
290
                  </PageSection>
                }
              </PageContents>
291
            }
292
          </div>
293
        }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
294
295
296
297
298
299
      </PageLayout>
    );
  }
}

const mapStateToProps = (state, ownProps) => ({
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
300
301
302
  institute: state.institutes.public.institute ? state.institutes.public.institute.data : undefined,
  error:  state.institutes.public.institute ? state.institutes.public.institute.error : undefined,
  loading:  state.institutes.public.institute ? state.institutes.public.institute.loading : true,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
303
  code: ownProps.match.params.wiewsCode,
304
  userRoles: state.login.authorities,
Oleksii Savran's avatar
Oleksii Savran committed
305
  mapLayers: state.accessions.public.mapLayers,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
306
307
308
309
});

const mapDispatchToProps = (dispatch) => bindActionCreators({
  loadInstitute,
310
  applyFilters,
Oleksii Savran's avatar
Oleksii Savran committed
311
  applyOverviewFilters,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
312
313
314
}, dispatch);


Matija Obreza's avatar
Matija Obreza committed
315
export default connect(mapStateToProps, mapDispatchToProps)(translate()(DisplayPage));