Commit 4691e5d5 authored by Oleksii Savran's avatar Oleksii Savran
Browse files

Merge branch 'code-review' into 'master'

Code review

See merge request !7
parents 80262411 9470521c
......@@ -14,19 +14,41 @@
},
"plugins": [
"@typescript-eslint",
"@typescript-eslint/tslint",
"prefer-arrow"
"prefer-arrow",
"react"
],
"settings": {
"react": {
"version": "detect"
}
// "import/resolver": {
// "node": {
// "paths": ["src"]
// }
// }
},
"rules": {
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": "off",
"@typescript-eslint/ban-types": "error",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/ban-types": [
"error",
{
"types": {
"object": false
}
}
],
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "variable",
"format": null
},
{
"selector": "function",
"format": ["camelCase", "PascalCase"]
}
],
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/explicit-member-accessibility": [
......@@ -35,6 +57,7 @@
"accessibility": "explicit"
}
],
// "@typescript-eslint/indent": ["error", 2],
"@typescript-eslint/member-delimiter-style": [
"error",
{
......@@ -72,13 +95,16 @@
"@typescript-eslint/triple-slash-reference": "error",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unified-signatures": "error",
"react/jsx-curly-spacing": [2, "always"],
"arrow-body-style": "off",
"arrow-parens": [
"error",
"always"
],
"brace-style": ["error", "1tbs", {"allowSingleLine": true }],
"camelcase": "off",
"capitalized-comments": "off",
"comma-dangle": ["error", "always-multiline"],
"complexity": "off",
"constructor-super": "error",
"curly": "error",
......@@ -93,6 +119,8 @@
"import/no-extraneous-dependencies": "off",
"import/no-internal-modules": "off",
"import/order": "off",
"indent": [2, 2, {"SwitchCase": 1}],
// "no-restricted-imports": ["error", {"patterns": ["../*"]}],
"max-classes-per-file": [
"error",
10
......@@ -135,15 +163,15 @@
],
"no-sparse-arrays": "error",
"no-template-curly-in-string": "error",
// "no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef-init": "error",
// "no-underscore-dangle": "error",
"no-unneeded-ternary": "error",
"no-unsafe-finally": "error",
"no-unused-expressions": "off",
"no-unused-labels": "error",
"no-var": "error",
"object-shorthand": "error",
"object-curly-spacing": ["error", "always"],
"one-var": [
"error",
"never"
......@@ -158,11 +186,14 @@
],
"prefer-const": "error",
"prefer-object-spread": "error",
"quotes": ["error", "single"],
"quote-props": [
"error",
"consistent-as-needed"
],
"radix": "error",
"keyword-spacing": ["error"],
"space-before-blocks": ["error", "always"],
"space-before-function-paren": [
"error",
{
......@@ -173,47 +204,6 @@
],
"spaced-comment": "error",
"use-isnan": "error",
"valid-typeof": "off",
"@typescript-eslint/tslint/config": [
"error",
{
"rules": {
"import-spacing": true,
"jsdoc-format": [
true,
"check-multiline-start"
],
"no-reference-import": true,
"one-line": [
true,
"check-catch",
"check-else",
"check-finally",
"check-open-brace",
"check-whitespace"
],
"prefer-conditional-expression": true,
"trailing-comma": [
true,
{
"esSpecCompliant": true,
"multiline": "always",
"singleline": "never"
}
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type",
"check-typecast",
"check-type-operator",
"check-rest-spread"
]
}
}
]
"valid-typeof": "off"
}
}
......@@ -22,9 +22,6 @@
<li class="nav-item">
<a class="nav-link" href="#/overview">Overview</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/api-info">API Info</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/cart">Cart</a>
</li>
......@@ -34,6 +31,9 @@
<li class="nav-item">
<a class="nav-link" href="?es">ES</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/api-info">API Info</a>
</li>
</ul>
<hr />
<div class="container-fluid" id="genesys"></div>
......
......@@ -29,8 +29,11 @@
<a class="nav-link active" href="#/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/api-info">API Info</a>
<a class="nav-link" href="#/overview">Overview</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/cart">Cart</a>
</li>
<li class="nav-item">
<a class="nav-link" href="index.html">EN</a>
</li>
......
......@@ -17,8 +17,9 @@ export const TreeMap = ({ nullLabel = 'NULL', style, data }: IProps) => {
if (typeof window !== 'undefined' && d3) {
const format = d3.format(',d');
const withHeader = false; // Without "Total" header
const name = (d) => d.data.term || d.data.name;
const nameWithPath = (d) => d.ancestors().reverse().map(name).join(' / ');
// const nameWithPath = (d) => d.ancestors().reverse().map(name).join(' / ');
// useEffect
React.useEffect(() => {
......@@ -37,7 +38,7 @@ export const TreeMap = ({ nullLabel = 'NULL', style, data }: IProps) => {
.attr('height', height)
.attr('width', width)
height -= headerHeight;
height -= withHeader ? headerHeight : 0;
const color = d3.scaleOrdinal(d3.quantize(d3.interpolateSpectral, data.children.length + 1));
const tile = (node, x0, y0, x1, y1) => {
......@@ -56,7 +57,7 @@ export const TreeMap = ({ nullLabel = 'NULL', style, data }: IProps) => {
const y = d3.scaleLinear().rangeRound([0, height]);
svg
.attr('viewBox', [0, -headerHeight - 0, width, height + headerHeight])
.attr('viewBox', [ 0, withHeader ? -headerHeight - 0 : 0, width, withHeader ? height + headerHeight : height ])
.style('font', '14px sans-serif');
const old = svg.selectAll('g');
......@@ -74,7 +75,7 @@ export const TreeMap = ({ nullLabel = 'NULL', style, data }: IProps) => {
function render(group, root) {
const node = group
.selectAll('g')
.data(root.children.concat(root))
.data(withHeader ? root.children.concat(root) : root.children)
.join('g');
node.filter((d) => d === root ? d.parent : d.children)
......@@ -82,7 +83,8 @@ export const TreeMap = ({ nullLabel = 'NULL', style, data }: IProps) => {
.on('click', (d) => d === root ? zoomout(root) : zoomin(d));
node.append('title')
.text((d) => `${nameWithPath(d)}\n${format(d.value)}`);
// .text((d) => `${nameWithPath(d)}\n${format(d.value)}`);
.text((d) => `${name(d)}\n${format(d.value)}`);
node.append('rect')
.attr('id', (d) => (d.leafUid = DOM.uid('leaf')).id)
......@@ -98,7 +100,8 @@ export const TreeMap = ({ nullLabel = 'NULL', style, data }: IProps) => {
.attr('clip-path', (d) => d.clipUid)
.attr('font-weight', (d) => d === root ? 'bold' : null)
.selectAll('tspan')
.data((d) => [ (d === root ? nameWithPath(d) : name(d)) ].concat(format(d.value)))
// .data((d) => [ (d === root ? nameWithPath(d) : name(d)) ].concat(format(d.value)))
.data((d) => [ name(d) ].concat(format(d.value)))
.join('tspan')
.attr('x', 3)
.attr('y', (d, i, nodes) => `${(i === nodes.length - 1 ? 1 : 0) * 0.3 + 1.1 + i * 0.9}em`)
......@@ -154,7 +157,7 @@ export const TreeMap = ({ nullLabel = 'NULL', style, data }: IProps) => {
}, [ data ]);
}
console.log('Rendering TreeMap', style, chartRef);
// console.log('Rendering TreeMap', style, chartRef);
return (
<svg style={ style } ref={ chartRef }></svg>
......
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import initI18n from "./i18n";
import initI18n from './i18n';
import { log } from '@genesys/client/utilities/debug';
// import * as cookies from 'es-cookie';
import { reconfigureServiceAxios, LoginService } from '@genesys/client/service';
import App from './ui/App';
import ApiAccessError from './ui/ApiAccessError';
import { Config, DefaultConfig } from "../config/config";
import { Config, DefaultConfig } from '../config/config';
// declare const window: Window & { devToolsExtension: any, __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any, initialLanguage: any, initialI18nStore: any, localeMapping: any };
// const AUTH_COOKIE = 'GENESYS_AUTH';
......@@ -42,7 +42,7 @@ function checkAccessTokens(apiUrl: string, clientId: string, clientSecret: strin
return appLogin;
};
export function showGenesysUI(holdingNode: HTMLElement, config: Config = DefaultConfig, language: string = "en") {
export function showGenesysUI(holdingNode: HTMLElement, config: Config = DefaultConfig, language: string = 'en') {
const { apiUrl, clientId, clientKey, filter } = config;
reconfigureServiceAxios({ apiUrl });
......
......@@ -28,9 +28,8 @@
"datasets": "Datasets",
"subsets": "Subsets",
"overview": {
"title": "Accession overview",
"subTitle": "Summary information about selected accessions",
"about": "About",
"title": "Collection overview",
"about": "About {{count, number}} {{what, lowercase}}",
"total": "Total",
"Other": "Other",
"Not specified": "Not specified",
......
import * as React from 'react';
import {withTranslation, WithTranslation} from 'react-i18next';
import { withTranslation, WithTranslation } from 'react-i18next';
// model
import AccessionOverview from '@genesys/client/model/accession/AccessionOverview';
import PropertiesCard from "ui/PropertiesCard";
import {VocabularyService} from "@genesys/client/service";
import PropertiesCard from 'ui/PropertiesCard';
import { VocabularyService } from '@genesys/client/service';
interface IAccessionOverviewPageState {
countryCodes: object;
......@@ -28,13 +28,13 @@ class AccessionOverviewSection extends React.Component<IAccessionOverviewPagePro
public async componentDidMount() {
const codes = await VocabularyService.decode3166Alpha3Terms(this.props.i18n.language);
this.setState({countryCodes: codes})
this.setState({ countryCodes: codes })
}
public render() {
const {overview, t} = this.props;
const { overview, t } = this.props;
const {countryCodes} = this.state;
const { countryCodes } = this.state;
if (!overview) {
......@@ -47,158 +47,158 @@ class AccessionOverviewSection extends React.Component<IAccessionOverviewPagePro
const overviewEl = overview[key];
const terms = overviewEl && overviewEl.terms ? [].concat(overviewEl.terms) : [];
if (overviewEl && overviewEl.other && overviewEl.other > 0) {
terms.push({term: 'accession.overview.Other', count: overviewEl.other});
terms.push({ term: 'accession.overview.Other', count: overviewEl.other });
}
if (overviewEl && overviewEl.missing && overviewEl.missing > 0) {
terms.push({term: 'accession.overview.Not specified', count: overviewEl.missing});
terms.push({ term: 'accession.overview.Not specified', count: overviewEl.missing });
}
overviewsTerms.set(key, terms);
});
return (
<div className="row pl-5">
{overviewsTerms && overviewsTerms.get('institute.code') &&
<div className="row">
{ overviewsTerms && overviewsTerms.get('crop.shortName') &&
<PropertiesCard
propertiesList={overviewsTerms.get('institute.code')}
title={t(`accession.overview.institute code`)}
propertyItemProps={{numeric: true}}
propertiesList={ overviewsTerms.get('crop.shortName') }
title={ t('accession.overview.crop shortName') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('institute.country.code3') &&
{ overviewsTerms && overviewsTerms.get('cropName') &&
<PropertiesCard
propertiesList={overviewsTerms.get('institute.country.code3')}
countyCodes={countryCodes}
title={t(`accession.overview.institute country code3`)}
propertyItemProps={{numeric: true}}
propertiesList={ overviewsTerms.get('cropName') }
title={ t('accession.overview.cropName') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('crop.shortName') &&
{ overviewsTerms && overviewsTerms.get('taxonomy.genus') &&
<PropertiesCard
propertiesList={overviewsTerms.get('crop.shortName')}
title={t(`accession.overview.crop shortName`)}
propertyItemProps={{numeric: true}}
propertiesList={ overviewsTerms.get('taxonomy.genus') }
title={ t('accession.overview.taxonomy genus') }
propertyItemProps={ { numeric: true, titleStyle: { fontStyle: 'italic' } } }
/>
}
{overviewsTerms && overviewsTerms.get('cropName') &&
{ overviewsTerms && overviewsTerms.get('taxonomy.genusSpecies') &&
<PropertiesCard
propertiesList={overviewsTerms.get('cropName')}
title={t(`accession.overview.cropName`)}
propertyItemProps={{numeric: true}}
/>
}
{overviewsTerms && overviewsTerms.get('taxonomy.genus') &&
<PropertiesCard
propertiesList={overviewsTerms.get('taxonomy.genus')}
title={t(`accession.overview.taxonomy genus`)}
propertyItemProps={{numeric: true, titleStyle: {fontStyle: 'italic'}}}
/>
}
{overviewsTerms && overviewsTerms.get('taxonomy.genusSpecies') &&
<PropertiesCard
propertiesList={overviewsTerms.get('taxonomy.genusSpecies')}
title={t(`accession.overview.taxonomy genusSpecies`)}
propertyItemProps={{numeric: true, titleStyle: {fontStyle: 'italic'}}}
propertiesList={ overviewsTerms.get('taxonomy.genusSpecies') }
title={ t('accession.overview.taxonomy genusSpecies') }
propertyItemProps={ { numeric: true, titleStyle: { fontStyle: 'italic' } } }
/>
}
{overviewsTerms && overviewsTerms.get('taxonomy.grinTaxonomySpecies.name') &&
{ overviewsTerms && overviewsTerms.get('taxonomy.grinTaxonomySpecies.name') &&
<PropertiesCard
propertiesList={overviewsTerms.get('taxonomy.grinTaxonomySpecies.name')}
title={t(`accession.overview.taxonomy grinTaxonomySpecies`)}
propertyItemProps={{numeric: true, titleStyle: {fontStyle: 'italic'}}}
propertiesList={ overviewsTerms.get('taxonomy.grinTaxonomySpecies.name') }
title={ t('accession.overview.taxonomy grinTaxonomySpecies') }
propertyItemProps={ { numeric: true, titleStyle: { fontStyle: 'italic' } } }
/>
}
{overviewsTerms && overviewsTerms.get('taxonomy.currentTaxonomySpecies.name') &&
{ overviewsTerms && overviewsTerms.get('taxonomy.currentTaxonomySpecies.name') &&
<PropertiesCard
propertiesList={overviewsTerms.get('taxonomy.currentTaxonomySpecies.name')}
title={t(`accession.overview.taxonomy currentTaxonomySpecies`)}
propertyItemProps={{numeric: true, titleStyle: {fontStyle: 'italic'}}}
propertiesList={ overviewsTerms.get('taxonomy.currentTaxonomySpecies.name') }
title={ t('accession.overview.taxonomy currentTaxonomySpecies') }
propertyItemProps={ { numeric: true, titleStyle: { fontStyle: 'italic' } } }
/>
}
{overviewsTerms && overviewsTerms.get('sampStat') &&
{ overviewsTerms && overviewsTerms.get('sampStat') &&
<PropertiesCard
propertiesList={overviewsTerms.get('sampStat')}
propertiesList={ overviewsTerms.get('sampStat') }
translationGroup="sampleStatus"
title={t(`accession.overview.sampStat`)}
propertyItemProps={{numeric: true}}
title={ t('accession.overview.sampStat') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('storage') &&
{ overviewsTerms && overviewsTerms.get('storage') &&
<PropertiesCard
propertiesList={overviewsTerms.get('storage')}
propertiesList={ overviewsTerms.get('storage') }
translationGroup="storage"
title={t(`accession.overview.storage`)}
propertyItemProps={{numeric: true}}
title={ t('accession.overview.storage') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('countryOfOrigin.code3') &&
{ overviewsTerms && overviewsTerms.get('countryOfOrigin.code3') &&
<PropertiesCard
propertiesList={overviewsTerms.get('countryOfOrigin.code3')}
countyCodes={countryCodes}
title={t(`accession.overview.countryOfOrigin code3`)}
propertyItemProps={{numeric: true}}
propertiesList={ overviewsTerms.get('countryOfOrigin.code3') }
countyCodes={ countryCodes }
title={ t('accession.overview.countryOfOrigin code3') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('donorCode') &&
{ overviewsTerms && overviewsTerms.get('donorCode') &&
<PropertiesCard
propertiesList={overviewsTerms.get('donorCode')}
title={t(`accession.overview.donorCode`)}
propertyItemProps={{numeric: true}}
propertiesList={ overviewsTerms.get('donorCode') }
title={ t('accession.overview.donorCode') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('duplSite') &&
{ overviewsTerms && overviewsTerms.get('duplSite') &&
<PropertiesCard
propertiesList={overviewsTerms.get('duplSite')}
title={t(`accession.overview.duplSite`)}
propertyItemProps={{numeric: true}}
propertiesList={ overviewsTerms.get('duplSite') }
title={ t('accession.overview.duplSite') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('breederCode') &&
{ overviewsTerms && overviewsTerms.get('breederCode') &&
<PropertiesCard
propertiesList={overviewsTerms.get('breederCode')}
title={t(`accession.overview.breederCode`)}
propertyItemProps={{numeric: true}}
propertiesList={ overviewsTerms.get('breederCode') }
title={ t('accession.overview.breederCode') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('mlsStatus') &&
{ overviewsTerms && overviewsTerms.get('mlsStatus') &&
<PropertiesCard
propertiesList={overviewsTerms.get('mlsStatus')}
propertiesList={ overviewsTerms.get('mlsStatus') }
translationGroup="mlsStatus"
title={t(`accession.overview.mlsStatus`)}
propertyItemProps={{numeric: true}}
title={ t('accession.overview.mlsStatus') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('aegis') &&
{ overviewsTerms && overviewsTerms.get('aegis') &&
<PropertiesCard
propertiesList={overviewsTerms.get('aegis')}
propertiesList={ overviewsTerms.get('aegis') }
translationGroup="aegisStatus"
title={t(`accession.overview.aegis`)}
propertyItemProps={{numeric: true}}
title={ t('accession.overview.aegis') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('available') &&
{ overviewsTerms && overviewsTerms.get('available') &&
<PropertiesCard
propertiesList={overviewsTerms.get('available')}
propertiesList={ overviewsTerms.get('available') }
translationGroup="available"
title={t(`accession.overview.available`)}
propertyItemProps={{numeric: true}}
title={ t('accession.overview.available') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('historic') &&
{ overviewsTerms && overviewsTerms.get('historic') &&
<PropertiesCard
propertiesList={overviewsTerms.get('historic')}
propertiesList={ overviewsTerms.get('historic') }
translationGroup="historic"
title={t(`accession.overview.historic`)}
propertyItemProps={{numeric: true}}
title={ t('accession.overview.historic') }
propertyItemProps={ { numeric: true } }
/>
}
{overviewsTerms && overviewsTerms.get('sgsv') &&
{ overviewsTerms && overviewsTerms.get('sgsv') &&
<PropertiesCard
propertiesList={overviewsTerms.get('sgsv')}
propertiesList={ overviewsTerms.get('sgsv') }
translationGroup="sgsv"
title={t(`accession.overview.sgsv`)}
propertyItemProps={{numeric: true}}
title={ t('accession.overview.sgsv') }
propertyItemProps={ { numeric: true } }
/>
}
{ overviewsTerms && overviewsTerms.get('institute.code') &&
<PropertiesCard
propertiesList={ overviewsTerms.get('institute.code') }
title={ t('accession.overview.institute code') }
propertyItemProps={ { numeric: true } }
/>
}
{ overviewsTerms && overviewsTerms.get('institute.country.code3') &&
<PropertiesCard
propertiesList={ overviewsTerms.get('institute.country.code3') }
countyCodes={ countryCodes }
title={ t('accession.overview.institute country code3') }
propertyItemProps={ { numeric: true } }
/>
}
</div>
......
......@@ -6,7 +6,7 @@ import AccessionList from './AccessionListPage';
import AccessionDetails from './AccessionDetailsPage';
import { createHashHistory } from 'history';
import CartPage from './CartPage';
import OverviewPage from "ui/OverviewPage";
import OverviewPage from 'ui/OverviewPage';
const hashHistory = createHashHistory({});
......@@ -25,10 +25,10 @@ export default class App extends React.Component<IAppProps, any> {
<div>
<Switch>
<Route path="/a/:uuid" exact render={ (props) => <AccessionDetails { ...props } apiUrl={ apiUrl } /> } />
<Route path="/" exact render={ (props) => <AccessionList { ...props } filter={ this.props.filter }/> }/>
<Route path="/" exact render={ (props) => <AccessionList { ...props } filter={ this.props.filter } /> }/>
<Route path="/api-info" exact component={ ApiInfoPage }/>
<Route path="/cart/" exact component={ CartPage }/>
<Route path="/overview" exact component={ OverviewPage }/>
<Route path="/overview" exact render={ (props) => <OverviewPage { ...props } filter={ this.props.filter } /> }/>
<Route component={ NotFound }/>
</Switch>
......@@ -43,4 +43,4 @@ export default class App extends React.Component<IAppProps, any> {
};
}
export { hashHistory as history};