DisplayPage.tsx 14.3 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';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
13
14

// UI
Matija Obreza's avatar
Matija Obreza committed
15
import PageLayout, { MainSection, PageContents, PageSection } from 'ui/layout/PageLayout';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
16
import GridContainer from 'ui/layout/GridContainer';
17
import PropertiesCard from 'ui/common/PropertiesCard.tsx';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
18
import ContentHeader from 'ui/common/heading/ContentHeader';
19
import LocationMap from 'ui/common/LocationMap';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
20
import Loading from 'ui/common/Loading';
21
import Number from 'ui/common/Number';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
22
import { ScrollToTopOnMount } from 'ui/common/page/scrollers';
Matija Obreza's avatar
Matija Obreza committed
23
import { Properties, PropertiesItem } from 'ui/common/Properties';
24
25
26
import PieChart from 'ui/common/pie-chart';
import PrettyDate from 'ui/common/time/PrettyDate';
import withWidth from '@material-ui/core/withWidth';
Matija Obreza's avatar
Matija Obreza committed
27
28
import { Breakpoint } from '@material-ui/core/styles/createBreakpoints';
import { CountryLink } from 'ui/genesys/Links';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
29
import BarChart from 'ui/common/bar-chart';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
30
31
32
33
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
34
import ButtonBar from 'ui/common/buttons/ButtonBar';
35
36
37
import Download from 'ui/common/download-acce-dialog';
import {loadArticlePromise} from 'cms/actions/public';
import Article from 'model/cms/Article';
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
38

39
interface IDisplayPageProps extends React.ClassAttributes<any> {
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
40
  t: any;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
41
  classes?: any;
42
  width: Breakpoint;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
43
  code: string;
44
  institute: FaoInstituteDetails;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
45
46
  error: any;
  loadInstitute: any;
47
  applyFilters: any;
Oleksii Savran's avatar
Oleksii Savran committed
48
  applyOverviewFilters: any;
49
50
51
  userRoles: string[];
  loadArticlePromise: (locale: string, slug: string) => Promise<Article>;
  lang: string;
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
52
}
53
const mobile = ['sm', 'xs'] as Breakpoint[];
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
54

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
55

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

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

62
  constructor(props: IDisplayPageProps, context: any) {
63
    super(props, context);
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
64
65
  }

66
67
68
69
70
  public state = {
    downloadArticle: null,
    authenticated: false,
  };

71
72
73
74
75
76
  private applyInstituteCodeFilter = () => {
    const { institute, applyFilters} = this.props;
    const filter = {holder: {code: [ institute.details.code ]}};
    applyFilters(filter);
  }

Oleksii Savran's avatar
Oleksii Savran committed
77
78
79
80
81
82
  private applyFilterForOverview = () => {
    const { institute, applyOverviewFilters } = this.props;
    const filter = {holder: {code: [ institute.details.code ]}};
    applyOverviewFilters(filter);
  }

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  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
100
  public componentWillMount() {
101
    const { institute, code, loadInstitute, lang, userRoles, loadArticlePromise } = this.props;
102
    if (code && (! institute || code !== institute.details.code)) {
Matija Obreza's avatar
Matija Obreza committed
103
104
      console.log(`Reloading institute data for code=${code}`, institute);
      loadInstitute(code);
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
105
    }
106
107
108
109
110
111
112

    const authenticated: boolean = userRoles.findIndex((role) => role === 'ROLE_USER') !== -1;
    this.setState({authenticated});
    const slug: string = authenticated ? 'download-authenticated' : 'download-anonymous';
    if (!this.state.downloadArticle || (this.state.downloadArticle.slug !== slug)) {
      loadArticlePromise(lang, slug).then((data) => this.setState({downloadArticle: data}));
    }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
113
114
115
  }

  public render() {
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
116
    const { error, institute, code, width, t } = this.props;
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    const stillLoading: boolean = ! error && (! institute || (code && institute && institute.details.code !== code));
    const isMobile = mobile.indexOf(width) !== -1;

    let cropShortNameOverview;
    let cropNameOverview;
    let taxonomyGenusOverview;
    let taxonomyGenusSpeciesOverview;
    if (!stillLoading) {
      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
134
135

    return (
Oleksii Savran's avatar
Oleksii Savran committed
136
      <PageLayout withFooter>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
137
        <ScrollToTopOnMount />
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
138
        <ContentHeader title={ t('institutes.public.p.display.title') }/>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
139

140
141
142
143
144
        { stillLoading ? <Loading /> :
          <div>
            { error && <div>{ JSON.stringify(error) }</div> }

            { institute &&
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
145
            <PageContents className="pt-1rem">
146
147
                <MainSection title={ `${institute.details.fullName}` }>
                  <Properties>
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
148
149
150
                    <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>
151
                    { institute.details.url &&
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
152
                      <PropertiesItem title={ t('institutes.public.p.display.webLink') }>
153
154
                        <a href={ institute.details.url }> { institute.details.url }</a>
                      </PropertiesItem>
155
                    }
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
156
                    <PropertiesItem title={ t('institutes.common.accessionsInGenesys') }>
157
158
                      <a onClick={ this.applyInstituteCodeFilter }><Number value={ institute.details.accessionCount } /></a>
                    </PropertiesItem>
159
                  </Properties>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
160

Oleksii Savran's avatar
Oleksii Savran committed
161
                  <CardActions className="container-spacing-vertical mt-15">
162
                    <ButtonBar barLabelText={ t('institutes.public.p.display.actions') }>
Oleksii Savran's avatar
Oleksii Savran committed
163
164
                      <Button onClick={ this.applyInstituteCodeFilter }>{ t('institutes.public.p.display.browseAccessions') }</Button>
                      <Button onClick={ this.applyFilterForOverview }>{ t('accessions.tab.overview') }</Button>
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
                      { this.state.authenticated &&
                        <Download dataType="mcpd"
                          article={ this.state.downloadArticle }
                          param={ code }
                          from="wiews"
                          buttonTitle={ `${t('common:action.download')} ${t('institutes.public.p.display.MCPD')}` } />
                      }
                      { this.state.authenticated &&
                          <Download dataType="pdci"
                            param={ code }
                            from="wiews"
                            article={ this.state.downloadArticle }
                            buttonTitle={ `${t('common:action.download')} ${t('institutes.public.p.display.PDCI_short')}` } />
                      }
                      <Download dataType="dwca"
                        article={ this.state.downloadArticle }
                        param={ code }
                        from="wiews"
                        buttonTitle={ `${t('common:action.download')} ${t('institutes.public.p.display.zip')}` } />
Oleksii Savran's avatar
Oleksii Savran committed
184
185
186
                      { 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
187
                  </CardActions>
188
                </MainSection>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
189
190

                { institute.blurb && institute.blurb.body &&
Matija Obreza's avatar
Matija Obreza committed
191
                  <PageSection title={ t('institutes.public.p.display.about') }>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
192
193
194
195
196
197
                    <Properties>
                      <div style={ !isMobile ? {columnCount: 2} : {} } dangerouslySetInnerHTML={ {__html: institute.blurb.body} }/>
                    </Properties>
                  </PageSection>
                }

198
                { institute.details.latitude !== null && institute.details.longitude !== null &&
Matija Obreza's avatar
Matija Obreza committed
199
                  <PageSection title={ t('geo.common.location') }>
200
                    <LocationMap
Maxym Borodenko's avatar
Maxym Borodenko committed
201
                      locations={ [{ id: institute.details.id, lat: institute.details.latitude, lng: institute.details.longitude }] }
202
                    />
Matija Obreza's avatar
Matija Obreza committed
203
204
205
206
                    <Properties>
                      <PropertiesItem title={ t('geo.common.latitude') }>{ institute.details.latitude }</PropertiesItem>
                      <PropertiesItem title={ t('geo.common.longitude') }>{ institute.details.longitude }</PropertiesItem>
                    </Properties>
207
208
209
                  </PageSection>
                }

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
210
                <GridContainer className="mb-15">
211
212
                  { cropShortNameOverview && cropShortNameOverview.terms && cropShortNameOverview.terms.length > 0 &&
                    <PropertiesCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
213
                      title={ t('institutes.public.p.display.representedCrops') }
214
215
216
                      propertiesList={ cropShortNameOverview.terms.map((term) => ({title: term.term, value: term.count})) }
                      small
                    />
217
                  }
218

219
220
                  { cropNameOverview && cropNameOverview.terms && cropNameOverview.terms.length > 0 &&
                    <PropertiesCard
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
221
                      title={ t('institutes.public.p.display.representedCropNames') }
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
                      propertiesList={ cropNameOverview.terms.slice(0, 5).map((term) => ({title: term.term, value: term.count})) }
                      small
                    >
                      <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
240
                      title={ t('institutes.public.p.display.representedGenera') }
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
                      propertiesList={  taxonomyGenusOverview.terms.slice(0, 5).map((term) => ({title: term.term, value: term.count})) }
                      small
                    >
                      <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
259
                      title={ t('institutes.public.p.display.representedSpecies') }
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
                      propertiesList={  taxonomyGenusSpeciesOverview.terms.slice(0, 5).map((term) => ({title: term.term, value: term.count})) }
                      small
                    >
                      <PieChart
                        data={
                          taxonomyGenusSpeciesOverview.terms.map(
                            (term) => ({
                              value: term.count,
                              label: term.term,
                            }),
                          )
                        }
                      />
                    </PropertiesCard>
                  }

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

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

Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
291
                { institute.pdciStats && institute.pdciStats.histogram && institute.pdciStats.histogram.length > 0 &&
Matija Obreza's avatar
Matija Obreza committed
292
                  <PageSection title={ t('institutes.public.p.display.PDCI') }>
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
293
                    <BarChart data={ institute.pdciStats.histogram.map((item, i) => ({key: i % 2 === 0 ? i / 2 : '', value: item })) }/>
Viacheslav Pavlov's avatar
i18n    
Viacheslav Pavlov committed
294
295
                    <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>
296
297
298
                  </PageSection>
                }
              </PageContents>
299
            }
300
          </div>
301
        }
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
302
303
304
305
306
307
      </PageLayout>
    );
  }
}

const mapStateToProps = (state, ownProps) => ({
308
309
  institute: state.institutes.public.institute,
  error: state.institutes.public.instituteError,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
310
  code: ownProps.match.params.wiewsCode,
311
312
  userRoles: state.login.authorities,
  lang: state.applicationConfig.lang,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
313
314
315
316
});

const mapDispatchToProps = (dispatch) => bindActionCreators({
  loadInstitute,
317
  applyFilters,
Oleksii Savran's avatar
Oleksii Savran committed
318
  applyOverviewFilters,
319
  loadArticlePromise,
Viacheslav Pavlov's avatar
Viacheslav Pavlov committed
320
321
322
}, dispatch);


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