DisplayPage.tsx 15.5 KB
Newer Older
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
1
import * as React from 'react';
2
import { withStyles } from '@material-ui/core/styles';
Matija Obreza's avatar
Matija Obreza committed
3
4
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
5
import { translate } from 'react-i18next';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
6
import { Link } from 'react-router-dom';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
7
8

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

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

// UI
Matija Obreza's avatar
Matija Obreza committed
17
import PageLayout, { MainSection, PageContents, PageSection } from 'ui/layout/PageLayout';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
18
import GridContainer from 'ui/layout/GridContainer';
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';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
25
import PieChartCard from 'ui/common/pie-chart/PieChartCard';
26
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';
Oleksii Savran's avatar
Oleksii Savran committed
29
// import { CardActions } from 'ui/common/Card';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
30
31
32
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';
Matija Obreza's avatar
Matija Obreza committed
37
38
import AccessionFilter from 'model/accession/AccessionFilter';
import { IPageRequest } from 'model/Page';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
39

40
41
42
43
/*tslint:disable*/
const styles = (theme) => ({
  italicProperties: {
    fontStyle: 'italic' as 'italic',
44
45
46
47
48
49
  },
  pdciSubHeader: {
    fontSize: '1rem',
    color: 'black',
    marginTop: '15px',
  },
50
51
52
53
});
/*tslint:enable*/


54
interface IDisplayPageProps extends React.ClassAttributes<any> {
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
55
  t: any;
56
  classes: any;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
57
  code: string;
58
  institute: FaoInstituteDetails;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
59
  error: any;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
60
  loading: boolean;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
61
  loadInstitute: any;
Matija Obreza's avatar
Matija Obreza committed
62
63
  applyFilters: (filters: string | AccessionFilter, page?: IPageRequest) => any;
  applyOverviewFilters: (filters: string | AccessionFilter) => any;
64
  userRoles: string[];
Oleksii Savran's avatar
Oleksii Savran committed
65
  mapLayers: MapLayer[];
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
66
67
}

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
68

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

71
  protected static needs = [
Matija Obreza's avatar
Matija Obreza committed
72
    ({ params: { wiewsCode } }) => loadInstitute(wiewsCode),
73
74
  ];

75
  constructor(props: IDisplayPageProps, context: any) {
76
    super(props, context);
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
77
78
  }

79
80
81
82
  public state = {
    authenticated: false,
  };

83
84
  private applyInstituteCodeFilter = () => {
    const { institute, applyFilters} = this.props;
Matija Obreza's avatar
Matija Obreza committed
85
    const filter = { institute: { code: [institute.details.code] } };
86
87
88
    applyFilters(filter);
  }

Oleksii Savran's avatar
Oleksii Savran committed
89
90
  private applyFilterForOverview = () => {
    const { institute, applyOverviewFilters } = this.props;
Matija Obreza's avatar
Matija Obreza committed
91
    const filter = { institute: { code: [institute.details.code] } };
Oleksii Savran's avatar
Oleksii Savran committed
92
93
94
    applyOverviewFilters(filter);
  }

95
96
97
98
99
100
101
102
  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 = {
Matija Obreza's avatar
Matija Obreza committed
103
      institute: { code: [institute.details.code] },
104
105
106
107
108
109
110
111
      lastModifiedDate: {
        ge: startOfDay,
        le: endOfDay,
      },
    };
    applyFilters(filter);
  }

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
112
  public componentWillMount() {
113
    const { institute, code, loadInstitute, userRoles } = this.props;
114
    if (code && (! institute || code !== institute.details.code)) {
Matija Obreza's avatar
Matija Obreza committed
115
116
      console.log(`Reloading institute data for code=${code}`, institute);
      loadInstitute(code);
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
117
    }
118
119
120

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

  public render() {
124
    const { error, loading, institute, code, userRoles, mapLayers, classes, t } = this.props;
125
    const slug: string = this.state.authenticated ? 'download-authenticated' : 'download-anonymous';
126
127
128
129
130

    let cropShortNameOverview;
    let cropNameOverview;
    let taxonomyGenusOverview;
    let taxonomyGenusSpeciesOverview;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
131
    if (!loading) {
132
133
134
135
136
137
138
139
140
      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
141
142

    return (
Oleksii Savran's avatar
Oleksii Savran committed
143
      <PageLayout withFooter>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
144
        <ScrollToTopOnMount />
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
145
146
        <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
147

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
148
        { loading ? <Loading /> :
149
150
151
152
          <div>
            { error && <div>{ JSON.stringify(error) }</div> }

            { institute &&
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
153
            <PageContents className="pt-1rem">
Oleksii Savran's avatar
Oleksii Savran committed
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
                <MainSection
                  title={ t('institutes.public.p.display.title') }
                  cardActions={
                    <ButtonBar barLabelText={ t('institutes.public.p.display.actions') }>
                      <Button onClick={ this.applyInstituteCodeFilter }>{ t('institutes.public.p.display.browseAccessions') }</Button>
                      { (userRoles.findIndex((role) => role === 'ROLE_ADMINISTRATOR') !== -1 || institute.details._permissions.manage) &&
                        <Link to={ `/dashboard/wiews/${institute.details.code}/files/` }>
                          <Button>{ t('institutes.public.p.display.browseFiles') }</Button>
                        </Link>
                      }
                      <Button onClick={ this.applyFilterForOverview }>{ t('accessions.tab.overview') }</Button>
                      { this.state.authenticated &&
                        <DownloadDialog
                          downloadUrl={ `/proxy/api/v1/wiews/${code}/download` }
                          slug={ slug }
                          postParams={ { mcpd: 'mcpd' } }
                          buttonTitle={ `${t('common:action.download')} ${t('institutes.public.p.display.MCPD')}` }
                        />
                      }
                      { this.state.authenticated &&
                        <DownloadDialog
                          downloadUrl={ `/proxy/api/v1/wiews/${code}/download` }
                          slug={ slug }
                          postParams={ { pdci: 'pdci' } }
                          buttonTitle={ `${t('common:action.download')} ${t('institutes.public.p.display.PDCI_short')}` }
                        />
                      }
                      <DownloadDialog
                        downloadUrl={ `/proxy/api/v1/wiews/${code}/download` }
                        slug={ slug }
                        postParams={ { dwca: 'dwca' } }
                        buttonTitle={ `${t('common:action.download')} ${t('institutes.public.p.display.zip')}` }
                      />
                      { 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>
                  }
                >
Matija Obreza's avatar
Matija Obreza committed
198
                  { institute.blurb && institute.blurb.body &&
Matija Obreza's avatar
Matija Obreza committed
199
                      <div className="mb-20">
Matija Obreza's avatar
Matija Obreza committed
200
                        <BlurbText body={ institute.blurb.body } />
Matija Obreza's avatar
Matija Obreza committed
201
                      </div>
Matija Obreza's avatar
Matija Obreza committed
202
                  }
203
                  <Properties>
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
204
205
206
                    <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>
207
                    { institute.details.url &&
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
208
                      <PropertiesItem title={ t('institutes.public.p.display.webLink') }>
209
210
                        <a href={ institute.details.url }> { institute.details.url }</a>
                      </PropertiesItem>
211
                    }
212
213
214
215
216
                    { 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
217
                    <PropertiesItem title={ t('institutes.common.accessionsInGenesys') }>
218
219
                      <a onClick={ this.applyInstituteCodeFilter }><Number value={ institute.details.accessionCount } /></a>
                    </PropertiesItem>
220
221
                  </Properties>
                </MainSection>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
222

223
                { institute.details.latitude !== null && institute.details.longitude !== null &&
Matija Obreza's avatar
Matija Obreza committed
224
                  <PageSection title={ t('geo.common.location') }>
225
                    <LocationMap
Maxym Borodenko's avatar
Maxym Borodenko committed
226
                      locations={ [{ id: institute.details.id, lat: institute.details.latitude, lng: institute.details.longitude }] }
Oleksii Savran's avatar
Oleksii Savran committed
227
                      mapLayers={ mapLayers }
228
                    />
Matija Obreza's avatar
Matija Obreza committed
229
                    <Properties>
Oleksii Savran's avatar
Oleksii Savran committed
230
                      <PropertiesItem title={ t('geo.common.latitude') }>{ institute.details.latitude }</PropertiesItem>
Matija Obreza's avatar
Matija Obreza committed
231
232
                      <PropertiesItem title={ t('geo.common.longitude') }>{ institute.details.longitude }</PropertiesItem>
                    </Properties>
233
234
235
                  </PageSection>
                }

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
236
                <GridContainer className="mb-15">
237
                  { cropShortNameOverview && cropShortNameOverview.terms && cropShortNameOverview.terms.length > 0 &&
Matija Obreza's avatar
Matija Obreza committed
238
                    <PieChartCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
239
                      title={ t('institutes.public.p.display.representedCrops') }
Matija Obreza's avatar
Matija Obreza committed
240
241
242
                      terms={ cropShortNameOverview.terms }
                      missing={ cropShortNameOverview.missing }
                      total={ cropShortNameOverview.total }
243
                    />
244
                  }
245

246
                  { cropNameOverview && cropNameOverview.terms && cropNameOverview.terms.length > 0 &&
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
247
                    <PieChartCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
248
                      title={ t('institutes.public.p.display.representedCropNames') }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
249
250
251
252
                      terms={ cropNameOverview.terms }
                      missing={ cropNameOverview.missing }
                      total={ cropNameOverview.total }
                    />
253
254
255
                  }

                  { taxonomyGenusOverview && taxonomyGenusOverview.terms && taxonomyGenusOverview.terms.length > 0 &&
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
256
                    <PieChartCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
257
                      title={ t('institutes.public.p.display.representedGenera') }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
258
259
260
                      terms={ taxonomyGenusOverview.terms }
                      missing={ taxonomyGenusOverview.missing }
                      total={ taxonomyGenusOverview.total }
261
                      propertyItemProps={ {classes: {propertiesRowLabel: classes.italicProperties} } }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
262
                    />
263
264
265
                  }

                  { taxonomyGenusSpeciesOverview && taxonomyGenusSpeciesOverview.terms && taxonomyGenusSpeciesOverview.terms.length > 0 &&
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
266
                    <PieChartCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
267
                      title={ t('institutes.public.p.display.representedSpecies') }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
268
269
270
                      terms={ taxonomyGenusSpeciesOverview.terms }
                      missing={ taxonomyGenusSpeciesOverview.missing }
                      total={ taxonomyGenusSpeciesOverview.total }
271
                      propertyItemProps={ {classes: {propertiesRowLabel: classes.italicProperties} } }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
272
                    />
273
274
                  }

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
275
                </GridContainer>
276

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

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
290
                { institute.pdciStats && institute.pdciStats.histogram && institute.pdciStats.histogram.length > 0 &&
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
                  <PageSection
                    title={ t('institutes.public.p.display.PDCI') }
                    subheader={
                      <div className={ classes.pdciSubHeader }>
                        { t('institutes.public.p.display.pdciDescription1') }
                        <a href="https://www.cambridge.org/core/journals/plant-genetic-resources/article/quality-indicators-for-passport-data-in-ex-situ-genebanks/AD391E5CF32DD41BFB49C1FE1D457E2C">
                          { t('institutes.public.p.display.pdciDescriptionLink') }
                        </a>
                        { t('institutes.public.p.display.pdciDescription2') }
                      </div>
                    }
                  >
                    <BarChart
                      data={ institute.pdciStats.histogram.map((item, i) => ({key: i % 2 === 0 ? i / 2 : '', value: item })) }
                      yLabel={ t('institutes.public.p.display.pdciYLabel') }
                      xLabel={ t('institutes.public.p.display.pdciXLabel') }
                    />
                    <div className="mt-20">
                      { t('institutes.public.p.display.pdciScore', {
                        count: institute.pdciStats.count,
                        avg: institute.pdciStats.avg.toFixed(2),
                        min: institute.pdciStats.min.toFixed(2),
                        max: institute.pdciStats.max.toFixed(2),
                      }) }
                    </div>
316
317
318
                  </PageSection>
                }
              </PageContents>
319
            }
320
          </div>
321
        }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
322
323
324
325
326
327
      </PageLayout>
    );
  }
}

const mapStateToProps = (state, ownProps) => ({
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
328
329
330
  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
331
  code: ownProps.match.params.wiewsCode,
332
  userRoles: state.login.authorities,
Oleksii Savran's avatar
Oleksii Savran committed
333
  mapLayers: state.accessions.public.mapLayers,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
334
335
336
337
});

const mapDispatchToProps = (dispatch) => bindActionCreators({
  loadInstitute,
338
  applyFilters,
Oleksii Savran's avatar
Oleksii Savran committed
339
  applyOverviewFilters,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
340
341
342
}, dispatch);


343
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(translate()(DisplayPage)));