Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Maintenance - Mise à jour mensuelle Lundi 6 Février entre 7h00 et 9h00
Open sidebar
urgi-is
FAIDARE
Commits
d62ab996
Commit
d62ab996
authored
Aug 25, 2021
by
Jean-Baptiste Nizet
Committed by
Exbrayat Cédric
Sep 01, 2021
Browse files
feat: study card
parent
faea8b5c
Changes
3
Hide whitespace changes
Inline
Side-by-side
backend/src/main/java/fr/inra/urgi/faidare/web/study/StudyController.java
0 → 100644
View file @
d62ab996
package
fr.inra.urgi.faidare.web.study
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
com.google.common.collect.Lists
;
import
fr.inra.urgi.faidare.api.NotFoundException
;
import
fr.inra.urgi.faidare.config.FaidareProperties
;
import
fr.inra.urgi.faidare.domain.criteria.GermplasmPOSTSearchCriteria
;
import
fr.inra.urgi.faidare.domain.data.TrialVO
;
import
fr.inra.urgi.faidare.domain.data.germplasm.GermplasmVO
;
import
fr.inra.urgi.faidare.domain.data.study.StudyDetailVO
;
import
fr.inra.urgi.faidare.domain.data.variable.ObservationVariableVO
;
import
fr.inra.urgi.faidare.domain.xref.XRefDocumentVO
;
import
fr.inra.urgi.faidare.repository.es.GermplasmRepository
;
import
fr.inra.urgi.faidare.repository.es.StudyRepository
;
import
fr.inra.urgi.faidare.repository.es.TrialRepository
;
import
fr.inra.urgi.faidare.repository.es.XRefDocumentRepository
;
import
fr.inra.urgi.faidare.repository.file.CropOntologyRepository
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.servlet.ModelAndView
;
/**
* Controller used to display a study card based on its ID.
* @author JB Nizet
*/
@Controller
(
"webStudyController"
)
@RequestMapping
(
"/studies"
)
public
class
StudyController
{
private
final
StudyRepository
studyRepository
;
private
final
FaidareProperties
faidareProperties
;
private
final
XRefDocumentRepository
xRefDocumentRepository
;
private
final
GermplasmRepository
germplasmRepository
;
private
final
CropOntologyRepository
cropOntologyRepository
;
private
final
TrialRepository
trialRepository
;
public
StudyController
(
StudyRepository
studyRepository
,
FaidareProperties
faidareProperties
,
XRefDocumentRepository
xRefDocumentRepository
,
GermplasmRepository
germplasmRepository
,
CropOntologyRepository
cropOntologyRepository
,
TrialRepository
trialRepository
)
{
this
.
studyRepository
=
studyRepository
;
this
.
faidareProperties
=
faidareProperties
;
this
.
xRefDocumentRepository
=
xRefDocumentRepository
;
this
.
germplasmRepository
=
germplasmRepository
;
this
.
cropOntologyRepository
=
cropOntologyRepository
;
this
.
trialRepository
=
trialRepository
;
}
@GetMapping
(
"/{studyId}"
)
public
ModelAndView
site
(
@PathVariable
(
"studyId"
)
String
studyId
)
{
StudyDetailVO
study
=
studyRepository
.
getById
(
studyId
);
// List<XRefDocumentVO> crossReferences = xRefDocumentRepository.find(
// XRefDocumentSearchCriteria.forXRefId(site.getLocationDbId()));
List
<
XRefDocumentVO
>
crossReferences
=
Arrays
.
asList
(
createXref
(
"foobar"
),
createXref
(
"bazbing"
)
);
// LocationVO site = createSite();
if
(
study
==
null
)
{
throw
new
NotFoundException
(
"Study with ID "
+
studyId
+
" not found"
);
}
List
<
GermplasmVO
>
germplasms
=
getGermplasms
(
study
);
List
<
ObservationVariableVO
>
variables
=
getVariables
(
study
);
List
<
TrialVO
>
trials
=
getTrials
(
study
);
return
new
ModelAndView
(
"study"
,
"model"
,
new
StudyModel
(
study
,
faidareProperties
.
getByUri
(
study
.
getSourceUri
()),
germplasms
,
variables
,
trials
,
crossReferences
)
);
}
private
List
<
GermplasmVO
>
getGermplasms
(
StudyDetailVO
study
)
{
if
(
study
.
getGermplasmDbIds
()
==
null
||
study
.
getGermplasmDbIds
().
isEmpty
())
{
return
Collections
.
emptyList
();
}
else
{
GermplasmPOSTSearchCriteria
germplasmCriteria
=
new
GermplasmPOSTSearchCriteria
();
germplasmCriteria
.
setGermplasmDbIds
(
Lists
.
newArrayList
(
study
.
getGermplasmDbIds
()));
return
germplasmRepository
.
find
(
germplasmCriteria
)
.
stream
()
.
sorted
(
Comparator
.
comparing
(
GermplasmVO:
:
getGermplasmName
))
.
collect
(
Collectors
.
toList
());
}
}
private
List
<
ObservationVariableVO
>
getVariables
(
StudyDetailVO
study
)
{
Set
<
String
>
variableIds
=
studyRepository
.
getVariableIds
(
study
.
getStudyDbId
());
return
cropOntologyRepository
.
getVariableByIds
(
variableIds
)
.
stream
()
.
sorted
(
Comparator
.
comparing
(
ObservationVariableVO:
:
getObservationVariableDbId
))
.
collect
(
Collectors
.
toList
());
}
private
List
<
TrialVO
>
getTrials
(
StudyDetailVO
study
)
{
if
(
study
.
getTrialDbIds
()
==
null
||
study
.
getTrialDbIds
().
isEmpty
())
{
return
Collections
.
emptyList
();
}
return
study
.
getTrialDbIds
()
.
stream
()
.
sorted
(
Comparator
.
naturalOrder
())
.
map
(
trialRepository:
:
getById
)
.
filter
(
Objects:
:
nonNull
)
.
collect
(
Collectors
.
toList
());
}
private
XRefDocumentVO
createXref
(
String
name
)
{
XRefDocumentVO
xref
=
new
XRefDocumentVO
();
xref
.
setName
(
name
);
xref
.
setDescription
(
"A very large description for the xref "
+
name
+
" which has way more than 120 characters bla bla bla bla bla bla bla bla bla bla bla bla"
);
xref
.
setDatabaseName
(
"db_"
+
name
);
xref
.
setUrl
(
"https://google.com"
);
xref
.
setEntryType
(
"type "
+
name
);
return
xref
;
}
}
backend/src/main/java/fr/inra/urgi/faidare/web/study/StudyModel.java
0 → 100644
View file @
d62ab996
package
fr.inra.urgi.faidare.web.study
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
fr.inra.urgi.faidare.domain.data.LocationVO
;
import
fr.inra.urgi.faidare.domain.data.TrialVO
;
import
fr.inra.urgi.faidare.domain.data.germplasm.GermplasmVO
;
import
fr.inra.urgi.faidare.domain.data.study.StudyDetailVO
;
import
fr.inra.urgi.faidare.domain.data.variable.ObservationVariableVO
;
import
fr.inra.urgi.faidare.domain.datadiscovery.data.DataSource
;
import
fr.inra.urgi.faidare.domain.xref.XRefDocumentVO
;
/**
* The model used by the study page
* @author JB Nizet
*/
public
final
class
StudyModel
{
private
final
StudyDetailVO
study
;
private
final
DataSource
source
;
private
final
List
<
GermplasmVO
>
germplasms
;
private
final
List
<
ObservationVariableVO
>
variables
;
private
final
List
<
TrialVO
>
trials
;
private
final
List
<
XRefDocumentVO
>
crossReferences
;
private
final
List
<
Map
.
Entry
<
String
,
Object
>>
additionalInfoProperties
;
public
StudyModel
(
StudyDetailVO
study
,
DataSource
source
,
List
<
GermplasmVO
>
germplasms
,
List
<
ObservationVariableVO
>
variables
,
List
<
TrialVO
>
trials
,
List
<
XRefDocumentVO
>
crossReferences
)
{
this
.
study
=
study
;
this
.
source
=
source
;
this
.
germplasms
=
germplasms
;
this
.
variables
=
variables
;
this
.
trials
=
trials
;
this
.
crossReferences
=
crossReferences
;
Map
<
String
,
Object
>
additionalInfo
=
study
.
getAdditionalInfo
()
==
null
?
Collections
.
emptyMap
()
:
study
.
getAdditionalInfo
().
getProperties
();
this
.
additionalInfoProperties
=
additionalInfo
.
entrySet
()
.
stream
()
.
filter
(
entry
->
entry
.
getValue
()
!=
null
&&
!
entry
.
getValue
().
toString
().
isEmpty
())
.
sorted
(
Map
.
Entry
.
comparingByKey
())
.
collect
(
Collectors
.
toList
());
}
public
StudyDetailVO
getStudy
()
{
return
study
;
}
public
DataSource
getSource
()
{
return
source
;
}
public
List
<
XRefDocumentVO
>
getCrossReferences
()
{
return
crossReferences
;
}
public
List
<
GermplasmVO
>
getGermplasms
()
{
return
germplasms
;
}
public
List
<
ObservationVariableVO
>
getVariables
()
{
return
variables
;
}
public
List
<
TrialVO
>
getTrials
()
{
return
trials
;
}
public
List
<
Map
.
Entry
<
String
,
Object
>>
getAdditionalInfoProperties
()
{
return
additionalInfoProperties
;
}
}
backend/src/main/resources/templates/study.html
0 → 100644
View file @
d62ab996
<!DOCTYPE html>
<html
xmlns:th=
"http://www.thymeleaf.org"
th:replace=
"~{layout/main :: layout(title=~{::title}, content=~{::main})}"
>
<head>
<title>
Study
<th:block
th:text=
"${model.study.studyType}"
/>
:
<th:block
th:text=
"${model.study.studyName}"
/></title>
<meta
http-equiv=
"Content-Type"
content=
"text/html; charset=UTF-8"
/>
</head>
<body>
<main>
<h1>
Study
<th:block
th:text=
"${model.study.studyType}"
/>
:
<th:block
th:text=
"${model.study.studyName}"
/></h1>
<h2>
Identification
</h2>
<div
th:replace=
"fragments/row::text-row(label='Name', text=${model.study.studyName})"
></div>
<div
th:replace=
"fragments/row::text-row(label='Identifier', text=${model.study.studyDbId})"
></div>
<th:block
th:if=
"${model.source != null}"
>
<div
th:replace=
"fragments/row::row(label='Source', content=~{::#source}, text='')"
>
<a
id=
"source"
target=
"_blank"
th:href=
"${model.source.url}"
>
<img
style=
"max-height: 60px;"
th:src=
"${model.source.image}"
th:alt=
"${model.source.name} + ' logo'"
/>
</a>
</div>
</th:block>
<th:block
th:if=
"${model.study.url != null && model.source != null}"
>
<div
th:replace=
"fragments/row::row(label='Data link', content=~{::#url}, text='')"
>
<a
id=
"url"
target=
"_blank"
th:href=
"${model.study.url}"
>
Link to this study on
<th:block
th:text=
"${model.source.name}"
/>
</a>
</div>
</th:block>
<div
th:replace=
"fragments/row::text-row(label='Project name', text=${model.study.programName})"
></div>
<div
th:replace=
"fragments/row::text-row(label='Description', text=${model.study.studyDescription})"
></div>
<th:block
th:if=
"${model.study.active != null}"
>
<div
th:replace=
"fragments/row::text-row(label='Active', text=${model.study.active ? 'Yes' : 'No'})"
></div>
</th:block>
<th:block
th:unless=
"${#lists.isEmpty(model.study.seasons)}"
>
<div
th:replace=
"fragments/row::text-row(label='Seasons', text=${#strings.listJoin(model.study.seasons, ',')})"
></div>
</th:block>
<th:block
th:if=
"${model.study.startDate != null && model.study.endDate != null}"
>
<div
th:replace=
"fragments/row::text-row(label='Date', text=${'From ' + #dates.format(model.study.startDate, 'yyyy-MM-dd') + ' to ' + #dates.format(model.study.endDate, 'yyyy-MM-dd') })"
></div>
</th:block>
<th:block
th:if=
"${model.study.startDate != null && model.study.endDate == null}"
>
<div
th:replace=
"fragments/row::text-row(label='Date', text=${'Started on ' + #dates.format(model.study.startDate, 'yyyy-MM-dd')})"
></div>
</th:block>
<th:block
th:if=
"${model.study.locationDbId}"
>
<div
th:replace=
"fragments/row::row(label='Location name', content=~{::#location})"
>
<a
id=
"location"
th:href=
"@{/sites/{siteId}(siteId=${model.study.locationDbId})}"
th:text=
"${model.study.locationName}"
></a>
</div>
</th:block>
<th:block
th:unless=
"${#lists.isEmpty(model.study.dataLinks)}"
>
<div
th:replace=
"fragments/row::row(label='Data files', content=~{::#data-files})"
>
<ul
id=
"data-files"
class=
"list-unstyled"
>
<li
th:each=
"dataLink : ${model.study.dataLinks}"
>
<a
target=
"_blank"
th:href=
"${dataLink.url}"
th:text=
"${dataLink.name}"
></a>
</li>
</ul>
</div>
</th:block>
<th:block
th:unles=
"${#lists.isEmpty(model.germplasms)}"
>
<h2>
Genotype
</h2>
<div
class=
"table-responsive scroll-table table-card-body"
>
<div
class=
"card"
>
<table
class=
"table table-sm table-striped"
>
<thead>
<tr>
<th
scope=
"col"
>
Accession number
</th>
<th
scope=
"col"
>
Name
</th>
<th
scope=
"col"
>
Taxon
</th>
</tr>
</thead>
<tbody>
<tr
th:each=
"row : ${model.germplasms}"
>
<td>
<a
th:href=
"@{/germplasms/{germplasmId}(germplasmId=${row.germplasmDbId})}"
th:text=
"${row.accessionNumber}"
></a>
</td>
<td
th:text=
"${row.germplasmName}"
></td>
<td
th:text=
"${(row.genus == null ? '' : row.genus) + ' ' + (row.species == null ? '' : row.species)+ ' ' + (row.subtaxa == null ? '' : row.subtaxa) }"
></td>
</tr>
</tbody>
</table>
</div>
</div>
</th:block>
<th:block
th:unless=
"${#lists.isEmpty(model.variables)}"
>
<h2>
Variables
</h2>
<div
class=
"table-responsive scroll-table table-card-body"
>
<div
class=
"card"
>
<table
class=
"table table-sm table-striped"
>
<thead>
<tr>
<th
scope=
"col"
>
Variable ID
</th>
<th
scope=
"col"
>
Variable short name
</th>
<th
scope=
"col"
>
Variable long name
</th>
<th
scope=
"col"
>
Ontology name
</th>
<th
scope=
"col"
>
Trait description
</th>
</tr>
</thead>
<tbody>
<tr
th:each=
"row : ${model.variables}"
>
<td>
<a
th:unless=
"${#strings.isEmpty(row.documentationURL)}"
th:href=
"${row.documentationURL}"
th:text=
"${row.observationVariableDbId}"
target=
"_blank"
></a>
<span
th:if=
"${#strings.isEmpty(row.documentationURL)}"
th:text=
"${row.observationVariableDbId}"
></span>
</td>
<td
th:text=
"${row.name}"
></td>
<td
th:text=
"${#lists.isEmpty(row.synonyms) ? '' : row.synonyms[0]}"
></td>
<td
th:text=
"${row.ontologyName}"
></td>
<td
th:text=
"${row.trait.description}"
></td>
</tr>
</tbody>
</table>
</div>
</div>
</th:block>
<th:block
th:unless=
"${#lists.isEmpty(model.trials)}"
>
<h2>
Data Set
</h2>
<div
class=
"table-responsive scroll-big-table table-card-body"
>
<div
class=
"card"
>
<table
class=
"table table-sm table-striped"
>
<thead>
<tr>
<th
scope=
"col"
>
Name
</th>
<th
scope=
"col"
>
Type
</th>
<th
scope=
"col"
>
Linked studies identifier
</th>
</tr>
</thead>
<tbody>
<tr
th:each=
"row : ${model.trials}"
>
<td>
<a
th:unless=
"${#strings.isEmpty(row.documentationURL)}"
th:href=
"${row.documentationURL}"
th:text=
"${row.trialName}"
target=
"_blank"
></a>
<span
th:if=
"${#strings.isEmpty(row.documentationURL)}"
th:text=
"${row.trialName}"
></span>
</td>
<td
th:text=
"${row.trialType}"
></td>
<td
style=
"width: 60%"
>
<th:block
th:each=
"trialStudy, iterStat : ${row.studies}"
th:if=
"${trialStudy.studyDbId != model.study.studyDbId}"
>
<a
th:href=
"@{/studies/{studyId}(studyId=${trialStudy.studyDbId})}"
th:text=
"${trialStudy.studyName.trim()}"
>
</a><th:block
th:if=
"${iterStat.last}"
>
;
</th:block>
</th:block>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</th:block>
<th:block
th:unless=
"${#lists.isEmpty(model.study.contacts)}"
>
<h2>
Contact
</h2>
<div
class=
"table-responsive scroll-table table-card-body"
>
<div
class=
"card"
>
<table
class=
"table table-sm table-striped"
>
<thead>
<tr>
<th
scope=
"col"
>
Role
</th>
<th
scope=
"col"
>
Name
</th>
<th
scope=
"col"
>
Email
</th>
<th
scope=
"col"
>
Institution
</th>
</tr>
</thead>
<tbody>
<tr
th:each=
"row : ${model.study.contacts}"
>
<td
th:text=
"${row.type}"
></td>
<td
th:text=
"${row.name}"
></td>
<td
th:text=
"${row.email}"
></td>
<td
th:text=
"${row.institutionName}"
></td>
</tr>
</tbody>
</table>
</div>
</div>
</th:block>
<th:block
th:unless=
"${#lists.isEmpty(model.additionalInfoProperties)}"
>
<h2>
Additional information
</h2>
<div
class=
"table-responsive scroll-table table-card-body"
>
<div
class=
"card"
>
<table
class=
"table table-sm table-striped"
>
<tbody>
<tr
th:each=
"row : ${model.additionalInfoProperties}"
>
<td
style=
"width: 50%;"
th:text=
"${row.key}"
></td>
<td
th:text=
"${row.value}"
></td>
</tr>
</tbody>
</table>
</div>
</div>
</th:block>
<div
th:replace=
"fragments/xrefs::xrefs(crossReferences=${model.crossReferences})"
></div>
</main>
</body>
</html>
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment