Commit 66e8e81d authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '36-subsets' into 'main'

Subsets

Closes #37 and #36

See merge request !33
parents 2f96278a aa6958e8
......@@ -36,7 +36,7 @@ pages:
- rm -rf public
- mkdir -p public
# Copy files
- cp index.html public/
- cp index.html edge.html public/
- find public
artifacts:
paths:
......
......@@ -12,13 +12,13 @@ Explore the demo at https://genesys-pgr.p.gitlab.croptrust.org/ui-embedded/
Add Javascript dependencies to your page:
```html
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded@1.1.0/dist/genesys-deps.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded@1.1.0/dist/genesys-ui.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded/dist/genesys-deps.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded/dist/genesys-ui.js"></script>
<!-- Recommended: Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" />
<!-- Genesys UI CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded@1.1.0/dist/genesys-deps.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded/dist/genesys-deps.css" />
```
Add a container `<div>` to your HTML page and initialize the Genesys UI with the `<script>`:
......
<!DOCTYPE html>
<html>
<head>
<title>Embedded Genesys: Development version</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes" />
<meta name="author" content="Genesys Team, helpdesk@genesys-pgr.org" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous" />
<!-- Genesys UI CSS-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded@edge/dist/genesys-deps.css" />
</head>
<body>
<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<div class="container">
<div class="jumbotron small">
<h1 class="display-6">Embedded Genesys <code>@edge</code></h1>
<p class="lead">This page demonstrates the development version of <em>Embedded Genesys</em>. You may want
to explore the <a href="index.html" target="genesys-ui-latest">current release</a> instead.<br />
The development release is available as <a
href="https://www.npmjs.com/package/@genesys-pgr/ui-embedded@edge" target="_blank">@genesys-pgr/ui-embedded@edge</a>.</p>
</div>
<ul class="nav">
<li class="nav-item">
<a class="nav-link active" href="#/">Home</a>
</li>
<li class="nav-item">
<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="#/map">Map</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/subsets">Subsets</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/datasets">Datasets</a>
</li>
<li class="nav-item">
<a class="nav-link" href="edge.html">EN</a>
</li>
<li class="nav-item">
<a class="nav-link" href="edge.html?es">ES</a>
</li>
<li class="nav-item">
<a class="nav-link" href="edge.html?zh-TW">ZH-TW</a>
</li>
</ul>
</div>
<hr />
<div class="container mb-5" id="genesys-container"></div>
<hr />
<div class="container">
<p>Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque cursus convallis fermentum. Fusce varius,
massa ut dictum tempor, lacus eros eleifend eros, vel fringilla neque lacus sit amet lacus. Pellentesque habitant
morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus condimentum tincidunt dolor at
interdum. Mauris bibendum tellus quis leo finibus tempus. Nunc aliquam a ligula at mattis. Suspendisse tincidunt
felis nec auctor ultrices.</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded@edge/dist/genesys-deps.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded@edge/dist/genesys-ui.js"></script>
<script type="text/javascript">
// Detect language from query string
const queryLang = document.location.search && document.location.search.substr(1) || undefined;
// Embedded Genesys configuration
const genesysConfig = {
apiUrl: 'https://api.genesys-pgr.org', // Genesys API server
clientId: 'dkDK7.rFJGS6CuMhysUcdFHiGi@api.genesys-pgr.org', // Client ID
clientKey: 'YlbHqhm3QqUaEt6nq7C3oMgBXo64WzLr', // Client key
captchaSiteKey: '6LfD6h0UAAAAAOmsQB3tpAtcWsWaggcrb155aDNT', // Public ReCaptcha site key
language: queryLang,
title: 'Alliance genebanks:', // HTML title prefix
filter: {
institute: { code: ['COL003', 'BEL084'] }, // Genesys data filter
},
accession: {
pdci: true, // Show PDCI
subsets: true, // Show list of subsets
datasets: true, // Show list of datasets
},
shoppingCart: {
enabled: true, // Enable shopping cart
},
map: {
height: '500px',
}
};
// Show UI
genesys.showGenesysUI(document.getElementById('genesys-container'), genesysConfig);
// Or, to display ONLY "Collection Overview" use:
// genesys.showOverview(document.getElementById('genesys-container'), genesysConfig);
</script>
</body>
</html>
......@@ -31,6 +31,12 @@
<li class="nav-item">
<a class="nav-link" href="#/cart">Cart</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/subsets">Subsets</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#/datasets">Datasets</a>
</li>
<li class="nav-item">
<a class="nav-link" href=".">EN</a>
</li>
......
......@@ -9,7 +9,7 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous" />
<!-- Genesys UI CSS-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded@1.1.0/dist/genesys-deps.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded/dist/genesys-deps.css" />
</head>
<body>
......@@ -22,8 +22,9 @@
<h1 class="display-6">Embedded Genesys</h1>
<p class="lead">This page demonstrates embedding Genesys data for <code>COL003</code> and <code>BEL084</code>
from <a href="https://www.genesys-pgr.org" target="_blank">Genesys</a> in a 3rd-party website.<br />
The current release of the Javascript library is available on <a
href="https://www.npmjs.com/package/@genesys-pgr/ui-embedded">npmjs.com</a>.</p>
The current release of the library is available on <a
href="https://www.npmjs.com/package/@genesys-pgr/ui-embedded" target="_blank">npmjs.com</a></p>
<p class="lead">Try out the <a href="edge.html" target="genesys-ui-edge">current development</a> version!</p>
</div>
<ul class="nav">
<li class="nav-item">
......@@ -60,8 +61,8 @@
felis nec auctor ultrices.</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded@1.1.0/dist/genesys-deps.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded@1.1.0/dist/genesys-ui.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded/dist/genesys-deps.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@genesys-pgr/ui-embedded/dist/genesys-ui.js"></script>
<script type="text/javascript">
// Detect language from query string
const queryLang = document.location.search && document.location.search.substr(1) || undefined;
......
{
"name": "@genesys-pgr/ui-embedded",
"version": "1.2.0-alpha",
"version": "1.2.0-alpha1",
"publishConfig": {
"access": "public"
},
......@@ -30,7 +30,8 @@
"serve": "webpack-dev-server --config config/webpack-development.config.js",
"serve:production": "cross-env NODE_ENV=production NODE_OPTIONS=--max_old_space_size=8192 webpack-dev-server --config config/webpack-production.config.js",
"analyze": "webpack --config config/webpack-analyze.config.js",
"eslint": "eslint . --ext .js,.jsx,.ts,.tsx"
"eslint": "eslint . --ext .js,.jsx,.ts,.tsx",
"publish": "echo yarn build && npm publish --tag edge --dry-run"
},
"resolutions": {
"@types/react": "^16.0.0",
......
import React from 'react';
import { connect } from 'react-redux';
import {Link} from "react-router-dom";
import { AccessionService } from '@genesys-pgr/client/service';
import { Property } from 'ui/common/Property';
......@@ -21,7 +22,6 @@ interface AccessionDetailsPageState {
interface AccessionDetailsPageProps {
match: any;
publicWebsiteUrl: string;
}
class AccessionDetailsPage extends React.Component<AccessionDetailsPageProps & WithTranslation & WithConfig, AccessionDetailsPageState> {
......@@ -99,7 +99,7 @@ class AccessionDetailsPage extends React.Component<AccessionDetailsPageProps & W
public render() {
const { accession, cartItems } = this.state;
const { t, appConfig: { apiUrl, shoppingCart, map }, appConfig, publicWebsiteUrl } = this.props;
const { t, appConfig: { apiUrl, shoppingCart, map }, appConfig } = this.props;
let propertyIndex = 0;
......@@ -185,11 +185,9 @@ class AccessionDetailsPage extends React.Component<AccessionDetailsPageProps & W
value={ details.duplSite.map((duplSite, i) => <div key={ `${i}-${duplSite}` }>{duplSite}</div>) }
index={ propertyIndex++ } />
}
{ details.acceUrl &&
<Property title="Accession URL" value={ details.acceUrl } index={ propertyIndex++ }/>
}
{/* {details.crop && <Property title={ t('accession.crop') } value={ details.crop.shortName } index={ propertyIndex++ }/>} */}
{ details.cropName && <Property title={ t('accession.cropName') } value={ details.cropName } index={ propertyIndex++ }/> }
{/* {details.crop && <Property title={ t(['accession.crop', '_.crop']) } value={ details.crop.shortName } index={ propertyIndex++ }/>} */}
{ details.cropName && <Property title={ t(['accession.cropName', '_.cropName']) } value={ details.cropName } index={ propertyIndex++ }/> }
{ details.taxonomy &&
<>
......@@ -281,7 +279,7 @@ class AccessionDetailsPage extends React.Component<AccessionDetailsPageProps & W
<h2 className="mt-4">{ t('accession.subsets') }</h2>
{ accession.subsets.map((subset, idx) => (
<div key={ idx }>
<a target="_blank" href= { `${publicWebsiteUrl}/subsets/${subset.uuid}` }>{ subset.title }</a>
<Link to={`/subsets/${subset.uuid}` }>{ subset.title }</Link>
<p>{ subset.description }</p>
</div>
)) }
......@@ -293,7 +291,7 @@ class AccessionDetailsPage extends React.Component<AccessionDetailsPageProps & W
<h2 className="mt-4">{ t('accession.datasets') }</h2>
{ accession.datasets.map((dataset, idx) => (
<div key={ idx }>
<a target="_blank" href= { `${publicWebsiteUrl}/datasets/${dataset.uuid}` }>{ dataset.title }</a>
<Link to={`/datasets/${dataset.uuid}` }>{ dataset.title }</Link>
<p>{ dataset.description }</p>
</div>
)) }
......@@ -303,7 +301,7 @@ class AccessionDetailsPage extends React.Component<AccessionDetailsPageProps & W
{ appConfig.accession.pdci && pdci && <PdciTable pdci={ pdci } title={ t('accession.details.pdci') }/> }
<h2 className="mt-4">{ t('accession.details.metadata') }</h2>
<Property title={ t('accession.details.uuid') } value={ `urn:uuid:${details.uuid}` } index={ propertyIndex++ }/>
<Property title={ t(['accession.details.uuid', '_.uuid']) } value={ `urn:uuid:${details.uuid}` } index={ propertyIndex++ }/>
<Property title={ t('accession.details.permanentURL') } value={
<a href={ `https://purl.org/germplasm/id/${details.uuid}` }>
{`https://purl.org/germplasm/id/${details.uuid}`}
......
......@@ -196,7 +196,7 @@ class AccessionListPage extends React.Component<AccessionListPageProps & WithTra
/>
</th>
) }
<th>{ t('accession.crop') }</th>
<th>{ t(['accession.crop', '_.crop']) }</th>
<th>{ t('accession.acceNumb') }</th>
<th>{ t('accession.accessionName') }</th>
<th>{ t('accession.taxonomy.scientificName') }</th>
......
......@@ -49,7 +49,7 @@ class AccessionOverviewSection extends React.Component<AccessionOverviewPageProp
{ overviewsTerms && overviewsTerms.get('cropName') &&
<PropertiesCard
propertiesList={ overviewsTerms.get('cropName') }
title={ t('accession.overview.cropName') }
title={ t(['accession.overview.cropName', '_.cropName']) }
propertyItemProps={ { numeric: true } }
/>
}
......
......@@ -54,7 +54,7 @@ class BrowsePage extends React.Component<OverviewPageProps & WithTranslation> {
<PageTitle title={ t('pagetitle.overview') }/>
{ overviewData ?
<>
<h1>{t('accession.overview.title')}</h1>
<h1>{t(['accession.overview.title', '_.title'])}</h1>
<p>
{ t('accession.overview.about', { count: overviewData.accessionCount, what: t('accession.model_plural', { count: overviewData.accessionCount }) }) }
</p>
......
import React from 'react';
import {useTranslation} from 'react-i18next';
import {useSelector} from "react-redux";
import {Link} from "react-router-dom";
// model
import Dataset from "@genesys-pgr/client/model/catalog/Dataset";
import Accession from "@genesys-pgr/client/model/accession/Accession";
// service
import {AccessionService, DatasetService} from '@genesys-pgr/client/service';
// ui
import {Property} from 'ui/common/Property';
import Loading from 'ui/common/Loading';
import PageTitle from 'ui/common/PageTitle';
interface DatasetDetailsPageProps {
match: any;
}
const DatasetDetailsPage = ({match}: DatasetDetailsPageProps) => {
// util
const {t} = useTranslation();
// state
const [dataset, setDataset] = React.useState<Dataset>();
const [accessions, setAccessions] = React.useState<Accession[]>();
const loadData = React.useCallback((uuid: string): Promise<void> => {
return DatasetService
.getDataset(uuid)
.then((data) => {
console.log('dataset: ', data);
setDataset(data);
AccessionService
.list({datasets: [data.uuid]}, {page: 0})
.then((accessions) => setAccessions(accessions.content));
})
.catch((e) => {
console.log('Api call failed: ', e);
});
}, []);
// redux
// const publicWebsiteUrl = useSelector((state: any) => state?.apiInfo?.apiInfo?.publicWebsiteUrl);
const genesysApiUrl = useSelector((state: any) => state?.appConfig?.config?.apiUrl);
React.useEffect(() => {
loadData(match.params.uuid);
}, [loadData, match.params])
if (!dataset) {
return (
<>
<PageTitle title={t('loading')}/>
<Loading/>
</>
);
}
let propertyIndex = 0;
return (
<>
<PageTitle title={t('pagetitle.dataset', {datasetTitle: dataset.title})}/>
<div className="d-flex justify-content-between align-items-center">
<h1>{dataset.title}</h1>
</div>
{dataset.description && <p>{dataset.description}</p> }
{dataset.owner &&
<Property
title={t(['dataset.dataProvider.title', '_.title'])}
value={ dataset.owner.name }
index={propertyIndex++}
/>
}
{dataset.creators && dataset.creators.length > 0 && (
<Property
title={t('dataset.details.creators')}
value={
<>
{dataset.creators.map((creat) => (
<div key={creat.id}><b>{ creat.fullName }</b> ({ t(`creator.role.${creat.role }`) })</div>
))}
</>
}
index={propertyIndex++}
/>
)}
{dataset.crops && dataset.crops.length > 0 &&
<Property
title={t(['dataset.cropName', '_.cropName'])} value={ dataset.crops.join(', ') }
index={propertyIndex++}
/>
}
{ dataset.descriptors && dataset.descriptors.length > 0 &&
<>
{/* <h2 className="mt-4">{t('dataset.details.traits')}</h2>
<ul>
{dataset.descriptors.map((descr) => (
<li key={descr.id}><a href={`${publicWebsiteUrl}/descriptors/${descr.uuid}`}>{`${descr.title}`}</a></li>
))}
</ul> */}
<Property
title={t('dataset.details.traits')} value={ dataset.descriptors.map((descr) => descr.title).join(', ') }
index={propertyIndex++}
/>
</>
}
{!!dataset.accessionCount &&
<Property
title={t('dataset.accessionCount')} value={ dataset.accessionCount }
index={propertyIndex++}
/>
}
{dataset.locations && dataset.locations.length > 0 && (
<>
<Property
title={t('dataset.locations')}
value={ dataset.locations.map((location) => (
<div key={location.id}>
<b>{ location.mapCountry || location.userCountry || ''}</b>
{ location.decimalLatitude !== null && location.decimalLongitude != null ? <> ({location?.decimalLatitude?.toFixed(5)}, {location?.decimalLongitude?.toFixed(5)})</> : null }
</div>
)) }
index={propertyIndex++}
/>
</>
)}
{!!dataset.startDate &&
<Property
title={t('dataset.startDate')} value={ dataset.startDate }
index={propertyIndex++}
/>
}
{!!dataset.endDate &&
<Property
title={t('dataset.endDate')} value={ dataset.endDate }
index={propertyIndex++}
/>
}
{dataset.language &&
<Property
title={t('dataset.language')} value={ dataset.language }
index={propertyIndex++}
/>
}
{dataset.format &&
<Property
title={t('dataset.format')} value={ dataset.format }
index={propertyIndex++}
/>
}
{dataset.source &&
<Property
title={t('dataset.source')} value={<a href={dataset.source}>{dataset.source}</a>}
index={propertyIndex++}
/>
}
{ dataset.repositoryFiles &&
<>
<h2 className="mt-4">{t('dataset.details.repositoryFiles')}</h2>
{dataset.repositoryFiles.map((repoFile) =>
<p key={ repoFile.uuid}>
<form target="_blank" method="post" action={ `${genesysApiUrl}/api/v1/dataset/${dataset.uuid}/download${
repoFile.originalFilename === 'Metadata.xlsx'
? '?metadata'
: `/${repoFile.id}`
}` }>
<button type="submit">{ t('action.download') }</button> <b>{ repoFile.originalFilename }</b> { repoFile.title }
{ repoFile.description && <p>{ repoFile.description }</p> }
</form>
</p>
)}
</>
}
{accessions && accessions.length > 0 && (
<>
<h2 className="mt-4">{t('dataset.details.accessions')}</h2>
<Property
title={t('dataset.accessions')}
value={(
<ul>{accessions.map((acc) => (
<li key={acc.id}><Link to={`/a/${acc.uuid}`}>{acc.accessionNumber}</Link></li>
))}
</ul>
)}
index={propertyIndex++}
/>
</>
)}
</>
);
};
export default DatasetDetailsPage;
\ No newline at end of file
import React, {useState} from 'react';
import {useTranslation} from 'react-i18next';
// model
import DatasetFilter from "@genesys-pgr/client/model/catalog/DatasetFilter";
interface DatasetFiltersProps {
filter: DatasetFilter;
applyFilter: (filter: Partial<DatasetFilter>) => void;
}
export function DatasetFilters({filter, applyFilter}: DatasetFiltersProps) {
const {t} = useTranslation();
const [text, setText] = useState(filter._text || '');
const handleSubmit = (e) => {
e.preventDefault();
console.log('------------')
applyFilter({
_text: text,
});
};
const onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setText(e.target.value);
};
return (
<form className="form-inline mb-4" onSubmit={handleSubmit}>
<div className="form-group mx-sm-2">
<label className="mr-2">{t('accession.filters.fullText')}</label>
<input name="full-text-search" type="text" className="form-control" value={text}
onChange={onInputChange}/>
</div>
<button className="btn btn-primary" type="submit">{t('action.submit')}</button>
</form>
);
}
import * as React from "react";
import {Link} from "react-router-dom";
import {useTranslation} from "react-i18next";
// model
import {IPageRequest} from "@genesys-pgr/client/model/Page";
import FilteredPage from "@genesys-pgr/client/model/FilteredPage";
import DatasetFilter from "@genesys-pgr/client/model/catalog/DatasetFilter";
import Dataset from "@genesys-pgr/client/model/catalog/Dataset";
import {Config} from "config/config";
// service
import {DatasetService} from "@genesys-pgr/client/service";
// ui
import PageTitle from "ui/common/PageTitle";
import Pagination from "ui/common/Pagination";
import {DatasetFilters} from "dataset/DatasetFilters";
// util
import {parseLocationSearch} from "utilities/filterUtil";
import {useSelector} from "react-redux";
interface IDatasetListPageProps {
location: any;
}
const DatasetListPage = ({location}: IDatasetListPageProps) => {
// util
const {t} = useTranslation();
// redux
const appConfig: Config = useSelector((state: any) => state?.appConfig?.config);
// state
const [datasets, setDatasets] = React.useState<FilteredPage<Dataset, DatasetFilter>>();
const [filter, setFilter] = React.useState<DatasetFilter>(appConfig.filter);
const loadData = React.useCallback((filter: string | DatasetFilter, pageR: IPageRequest): Promise<FilteredPage<Dataset, DatasetFilter>> => {
return DatasetService
.datasetList(filter, pageR)
.then((data) => {
setDatasets(data);
setFilter(data.filter);
return data;
})
.catch((e) => {
console.log('Api call failed: ', e);
return null;