diff --git a/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryImpl.java b/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryImpl.java index 733d1da9794950b689b43cd95ae465823f45778c..616a33d7e6083e9f1abc027f590b692a9a17573e 100644 --- a/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryImpl.java +++ b/backend/src/main/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryImpl.java @@ -121,7 +121,7 @@ public class GermplasmRepositoryImpl implements GermplasmRepository { @Override public Iterator<GermplasmMcpdVO> scrollGermplasmMcpdsByIds(Set<String> ids, int fetchSize) { - QueryBuilder query = QueryBuilders.idsQuery().addIds(ids.toArray(new String[0])); + QueryBuilder query = QueryBuilders.termsQuery("germplasmDbId", ids); return new ESScrollIterator<>(client, requestFactory, parser, GermplasmMcpdVO.class, query, fetchSize); } diff --git a/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmController.java b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmController.java index 84da94f897426a8b78c7bc6a3dc2c62b74d4a4c3..ec4ed09ba66253fc5662fbd9a60076c6c0153694 100644 --- a/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmController.java +++ b/backend/src/main/java/fr/inra/urgi/faidare/web/germplasm/GermplasmController.java @@ -76,15 +76,17 @@ public class GermplasmController { @GetMapping("/{germplasmId}") public ModelAndView get(@PathVariable("germplasmId") String germplasmId) { - // GermplasmVO germplasm = germplasmRepository.getById(germplasmId); - - // TODO replace this block by the above commented one - GermplasmVO germplasm = createGermplasm(); + GermplasmVO germplasm = germplasmRepository.getById(germplasmId); if (germplasm == null) { throw new NotFoundException("Germplasm with ID " + germplasmId + " not found"); } + // TODO remove this, which is used to display all the sections on a specific germplasm + if (germplasm.getGermplasmDbId().equals("dXJuOlZJQi9nZXJtcGxhc20vWmVhX1ZJQl9SSUwxOFJJTDJ3YXlfX185Ng==")) { + germplasm = createGermplasm(); + } + return toModelAndView(germplasm); } @@ -132,17 +134,19 @@ public class GermplasmController { } private ModelAndView toModelAndView(GermplasmVO germplasm) { - // List<BrapiGermplasmAttributeValue> attributes = getAttributes(germplasm); - // PedigreeVO pedigree = getPedigree(germplasm); + List<BrapiGermplasmAttributeValue> attributes = getAttributes(germplasm); + PedigreeVO pedigree = getPedigree(germplasm); + + // TODO remove this + if (germplasm.getGermplasmDbId().equals("dXJuOlZJQi9nZXJtcGxhc20vWmVhX1ZJQl9SSUwxOFJJTDJ3YXlfX185Ng==")) { + attributes = Arrays.asList(createAttribute()); + pedigree = createPedigree(); + } + // List<XRefDocumentVO> crossReferences = xRefDocumentRepository.find( // XRefDocumentSearchCriteria.forXRefId(germplasm.getGermplasmDbId()) // ); - // TODO replace this block by the above commented one - List<BrapiGermplasmAttributeValue> attributes = Arrays.asList( - createAttribute() - ); - PedigreeVO pedigree = createPedigree(); List<XRefDocumentVO> crossReferences = Arrays.asList( createXref("foobar"), createXref("bazbing") @@ -224,7 +228,7 @@ public class GermplasmController { private GermplasmVO createGermplasm() { GermplasmVO result = new GermplasmVO(); - + result.setGermplasmDbId("dXJuOlZJQi9nZXJtcGxhc20vWmVhX1ZJQl9SSUwxOFJJTDJ3YXlfX185Ng=="); result.setGermplasmName("BLE BARBU DU ROUSSILLON"); result.setAccessionNumber("1408"); result.setSynonyms(Arrays.asList("BLE DU ROUSSILLON", "FRA051:1699", "ROUSSILLON")); diff --git a/backend/src/main/java/fr/inra/urgi/faidare/web/site/SiteController.java b/backend/src/main/java/fr/inra/urgi/faidare/web/site/SiteController.java index c28705adcb4ebeb98a2bcb3c1afc0dec9ae9e61c..cf17c73ddddca7b2d20e9ac263c93edc3c59beef 100644 --- a/backend/src/main/java/fr/inra/urgi/faidare/web/site/SiteController.java +++ b/backend/src/main/java/fr/inra/urgi/faidare/web/site/SiteController.java @@ -50,6 +50,11 @@ public class SiteController { public ModelAndView get(@PathVariable("siteId") String siteId) { LocationVO site = locationRepository.getById(siteId); + if (site == null) { + throw new NotFoundException("Site with ID " + siteId + " not found"); + } + + // TODO uncomment this and remove the hard-coded xrefs // List<XRefDocumentVO> crossReferences = xRefDocumentRepository.find( // XRefDocumentSearchCriteria.forXRefId(site.getLocationDbId())); List<XRefDocumentVO> crossReferences = Arrays.asList( @@ -57,13 +62,6 @@ public class SiteController { createXref("bazbing") ); - // LocationVO site = createSite(); - - if (site == null) { - throw new NotFoundException("Site with ID " + siteId + " not found"); - } - - return new ModelAndView("site", "model", new SiteModel( @@ -93,24 +91,6 @@ public class SiteController { return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(body); } - private LocationVO createSite() { - LocationVO site = new LocationVO(); - site.setLocationName("France"); - site.setSourceUri("https://urgi.versailles.inrae.fr/gnpis"); - site.setUri("Test URI"); - site.setUrl("https://google.com"); - site.setLatitude(45.65); - site.setLongitude(1.34); - BrapiAdditionalInfo additionalInfo = new BrapiAdditionalInfo(); - additionalInfo.addProperty("Slope", 4.32); - additionalInfo.addProperty("Distance to city", "3 km"); - additionalInfo.addProperty("foo", "bar"); - additionalInfo.addProperty("baz", "zing"); - additionalInfo.addProperty("blob", null); - site.setAdditionalInfo(additionalInfo); - return site; - } - private XRefDocumentVO createXref(String name) { XRefDocumentVO xref = new XRefDocumentVO(); xref.setName(name); diff --git a/backend/src/main/java/fr/inra/urgi/faidare/web/study/StudyController.java b/backend/src/main/java/fr/inra/urgi/faidare/web/study/StudyController.java index 11ea51f7f956ea7793c7b0afc5810a2e901b04c0..626df842e50b8fe1eaab7f6492e70fb064da9b3d 100644 --- a/backend/src/main/java/fr/inra/urgi/faidare/web/study/StudyController.java +++ b/backend/src/main/java/fr/inra/urgi/faidare/web/study/StudyController.java @@ -75,6 +75,10 @@ public class StudyController { public ModelAndView get(@PathVariable("studyId") String studyId) { StudyDetailVO study = studyRepository.getById(studyId); + if (study == null) { + throw new NotFoundException("Study with ID " + studyId + " not found"); + } + // TODO uncomment this // List<XRefDocumentVO> crossReferences = xRefDocumentRepository.find( // XRefDocumentSearchCriteria.forXRefId(study.getStudyDbId())); @@ -83,19 +87,11 @@ public class StudyController { createXref("bazbing") ); - 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); LocationVO location = getLocation(study); - // TODO remove this - location.setLatitude(34.0); - location.setLongitude(14.0); - return new ModelAndView("study", "model", new StudyModel( diff --git a/backend/src/main/java/fr/inra/urgi/faidare/web/thymeleaf/FaidareExpressions.java b/backend/src/main/java/fr/inra/urgi/faidare/web/thymeleaf/FaidareExpressions.java index 9ba16d342d94e9097e720c5b3ad2e370d564fe6d..342c41655def0bdee5eb87df5055dde98c986a79 100644 --- a/backend/src/main/java/fr/inra/urgi/faidare/web/thymeleaf/FaidareExpressions.java +++ b/backend/src/main/java/fr/inra/urgi/faidare/web/thymeleaf/FaidareExpressions.java @@ -2,9 +2,11 @@ package fr.inra.urgi.faidare.web.thymeleaf; import java.nio.charset.StandardCharsets; import java.text.DecimalFormat; +import java.util.Arrays; import java.util.Base64; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Function; @@ -24,7 +26,9 @@ public class FaidareExpressions { private static final Map<String, Function<String, String>> TAXON_ID_URL_FACTORIES_BY_SOURCE_NAME = createTaxonIdUrlFactories(); - private static final ObjectMapper objectMapper = new ObjectMapper(); + + private static final List<NavbarEntry> NAVBAR_ENTRIES = + createNavbarEntries(); private static Map<String, Function<String, String>> createTaxonIdUrlFactories() { Map<String, Function<String, String>> result = new HashMap<>(); @@ -35,6 +39,23 @@ public class FaidareExpressions { return Collections.unmodifiableMap(result); } + private static List<NavbarEntry> createNavbarEntries() { + return Arrays.asList( + NavbarEntry.menu("URGI", Arrays.asList( + NavbarEntry.link("Home", "https://urgi.versailles.inra.fr"), + NavbarEntry.link("News", "https://urgi.versailles.inra.fr/About-us/News"), + NavbarEntry.link("About us", "https://urgi.versailles.inra.fr/About-us") + )), + NavbarEntry.menu("More...", Arrays.asList( + NavbarEntry.link("About", "https://urgi.versailles.inrae.fr/faidare/about"), + NavbarEntry.link("Join us", "https://urgi.versailles.inra.fr/faidare/join"), + NavbarEntry.link("Terms of use", "https://urgi.versailles.inra.fr/faidare/legal"), + NavbarEntry.link("Help", "https://urgi.versailles.inra.fr/faidare/help"), + NavbarEntry.link("News/Perspectives", "https://urgi.versailles.inra.fr/faidare/news") + )) + ); + } + private final Locale locale; public FaidareExpressions(Locale locale) { @@ -59,13 +80,8 @@ public class FaidareExpressions { return urlFactory != null ? urlFactory.apply(taxonSource.getTaxonId()) : null; } - public String toJson(Object value) { - try { - return objectMapper.writeValueAsString(value); - } - catch (JsonProcessingException e) { - throw new IllegalArgumentException(e); - } + public List<NavbarEntry> navbarEntries() { + return NAVBAR_ENTRIES; } private String collPopTitle(CollPopVO collPopVO, Function<String, String> nameTransformer) { diff --git a/backend/src/main/java/fr/inra/urgi/faidare/web/thymeleaf/NavbarEntry.java b/backend/src/main/java/fr/inra/urgi/faidare/web/thymeleaf/NavbarEntry.java new file mode 100644 index 0000000000000000000000000000000000000000..8925aec060762927cf87328c2e40164e5bb7e589 --- /dev/null +++ b/backend/src/main/java/fr/inra/urgi/faidare/web/thymeleaf/NavbarEntry.java @@ -0,0 +1,40 @@ +package fr.inra.urgi.faidare.web.thymeleaf; + +import java.util.Collections; +import java.util.List; + +/** + * A navbar link + * @author JB Nizet + */ +public final class NavbarEntry { + private final String label; + private final String url; + private final List<NavbarEntry> subMenu; + + private NavbarEntry(String label, String url, List<NavbarEntry> subMenu) { + this.label = label; + this.url = url; + this.subMenu = subMenu; + } + + public static NavbarEntry link(String label, String url) { + return new NavbarEntry(label, url, Collections.emptyList()); + } + + public static NavbarEntry menu(String label, List<NavbarEntry> subMenu) { + return new NavbarEntry(label, null, subMenu); + } + + public String getLabel() { + return label; + } + + public String getUrl() { + return url; + } + + public List<NavbarEntry> getSubMenu() { + return subMenu; + } +} diff --git a/backend/src/main/resources/templates/layout/main.html b/backend/src/main/resources/templates/layout/main.html index 8097134fddb189f6c038ba29aceb29f14eee972f..0ceb3ebf650b4ce83e8fc1371d175841769ee0da 100644 --- a/backend/src/main/resources/templates/layout/main.html +++ b/backend/src/main/resources/templates/layout/main.html @@ -14,7 +14,7 @@ <link rel="shortcut icon" - th:href="@{/static/assets/images/favicon.ico}" + th:href="@{/assets/images/favicon.ico}" type="image/x-icon" /> </head> @@ -22,9 +22,63 @@ <body> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container"> - <span class="navbar-brand py-0"> + <a + class="navbar-brand py-0" + href="https://urgi.versailles.inrae.fr/faidare" + > <img th:src="@{/assets/images/logo.png}" style="height: 40px" /> - </span> + </a> + <button + class="navbar-toggler" + type="button" + data-bs-toggle="collapse" + data-bs-target="#navbarContent" + aria-controls="navbarContent" + aria-expanded="false" + aria-label="Toggle navigation" + > + <span class="navbar-toggler-icon"></span> + </button> + <div class="collapse navbar-collapse" id="navbarContent"> + <ul class="navbar-nav me-auto"> + <th:block th:each="topEntry : ${#faidare.navbarEntries}"> + <li class="nav-item" th:if="${#lists.isEmpty(topEntry.subMenu)}"> + <a + class="nav-link" + th:href="${topEntry.url}" + th:text="${topEntry.label}" + ></a> + </li> + <li + class="nav-item dropdown" + th:if="${not #lists.isEmpty(topEntry.subMenu)}" + > + <a + class="nav-link dropdown-toggle" + th:id="${'navbar-dropdown-' + topEntry.label}" + href="#" + role="button" + data-bs-toggle="dropdown" + aria-expanded="false" + th:text="${topEntry.label}" + > + </a> + <ul + class="dropdown-menu bg-light" + th:aria-labelledby="${'navbar-dropdown-' + topEntry.label}" + > + <li th:each="subEntry : ${topEntry.subMenu}" class="bg-light"> + <a + class="dropdown-item" + th:href="${subEntry.url}" + th:text="${subEntry.label}" + ></a> + </li> + </ul> + </li> + </th:block> + </ul> + </div> </div> </nav> <div class="container mt-3"> diff --git a/backend/src/test/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryTest.java b/backend/src/test/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryTest.java index 930cbbe92bf6f58456bacae4109f42ef5ce2c931..7ec9bb8e27fa23dbdb2a84b87e5c116334fae20c 100644 --- a/backend/src/test/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryTest.java +++ b/backend/src/test/java/fr/inra/urgi/faidare/repository/es/GermplasmRepositoryTest.java @@ -52,7 +52,6 @@ class GermplasmRepositoryTest { esSetUp.initialize(ProgenyVO.class, 0L); esSetUp.initialize(PedigreeVO.class, 0L); esSetUp.initialize(GermplasmMcpdVO.class, 0L); - } @Autowired @@ -137,6 +136,22 @@ class GermplasmRepositoryTest { .allMatch(vo -> !vo.getGermplasmDbId().isEmpty()); } + @Test + void shouldScrollGermplasmMcpdsByIds() { + Iterator<GermplasmMcpdVO> list = repository.scrollGermplasmMcpdsByIds(Collections.singleton("13705"), 1000); + assertThat(list).toIterable() + .isNotEmpty() + .allMatch(vo -> !vo.getGermplasmDbId().isEmpty()); + + list = repository.scrollGermplasmMcpdsByIds(Collections.singleton("1370"), 1000); + assertThat(list).toIterable() + .isEmpty(); + + list = repository.scrollGermplasmMcpdsByIds(Collections.singleton("Prunus"), 1000); + assertThat(list).toIterable() + .isEmpty(); + } + @Test void should_Scroll_By_accessionNumber() { GermplasmPOSTSearchCriteria criteria = new GermplasmPOSTSearchCriteria(); diff --git a/web/package.json b/web/package.json index 3efc776bb3c7da2b2537fa6e7aaaebd295d57509..d4dae567299cac36ee27d7aa43752435a21589ae 100644 --- a/web/package.json +++ b/web/package.json @@ -16,7 +16,7 @@ "license": "MIT", "dependencies": { "@types/leaflet": "1.7.5", - "bootstrap": "5.1.0", + "bootstrap": "5.1.1", "leaflet": "1.7.1" }, "devDependencies": { diff --git a/web/src/bootstrap/popovers.ts b/web/src/bootstrap/popovers.ts index b19e5e75dedc37274b3a863bd1f18e448af43bdf..4e6baa5bbdd271604c328bd0167729290c6b0f97 100644 --- a/web/src/bootstrap/popovers.ts +++ b/web/src/bootstrap/popovers.ts @@ -1,4 +1,4 @@ -import { Popover } from 'bootstrap'; +import Popover from 'bootstrap/js/dist/popover'; export function initializePopovers() { const popoverTriggerList: Array<HTMLElement> = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')); diff --git a/web/src/index.ts b/web/src/index.ts index 060cf75d6a996a175e6d4b29c8fa1b067cf0610e..18fd98fd9580fd50269bf100a160d93660172a7e 100644 --- a/web/src/index.ts +++ b/web/src/index.ts @@ -1,5 +1,7 @@ import { initializePopovers } from './bootstrap/popovers'; import { initializeMap } from './map/map'; +import 'bootstrap/js/dist/dropdown'; +import 'bootstrap/js/dist/collapse'; (window as any).faidare = { initializePopovers, diff --git a/web/yarn.lock b/web/yarn.lock index 006da818ecb29a7986970a0c18274d4648db5611..877a23dac04a277365934d2a8f391bfbfa49b98e 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -372,10 +372,10 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -bootstrap@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.1.0.tgz#543ef8f44f4b9af67b0230f19508542fec38ef55" - integrity sha512-bs74WNI9BgBo3cEovmdMHikSKoXnDgA6VQjJ7TyTotU6L7d41ZyCEEelPwkYEzsG/Zjv3ie9IE3EMAje0W9Xew== +bootstrap@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.1.1.tgz#9d6eed81e08feaccedf3adaca51fe4b73a2871df" + integrity sha512-/jUa4sSuDZWlDLQ1gwQQR8uoYSvLJzDd8m5o6bPKh3asLAMYVZKdRCjb1joUd5WXf0WwCNzd2EjwQQhupou0dA== brace-expansion@^1.1.7: version "1.1.11"