@sfgrp/taxonpages 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/README.markdown +432 -0
  2. package/bin/taxonpages.js +78 -0
  3. package/index.html +22 -0
  4. package/package.json +82 -0
  5. package/postcss.config.cjs +17 -0
  6. package/server.js +142 -0
  7. package/src/App.vue +31 -0
  8. package/src/assets/css/leaflet.css +24 -0
  9. package/src/assets/css/main.css +23 -0
  10. package/src/assets/css/tailwind.css +3 -0
  11. package/src/assets/css/vars.css +58 -0
  12. package/src/assets/css/webkit.css +19 -0
  13. package/src/assets/images/taxonworks_full_logo.svg +22 -0
  14. package/src/assets/images/taxonworks_logo.svg +7 -0
  15. package/src/cli/commands/build.js +60 -0
  16. package/src/cli/commands/dev.js +48 -0
  17. package/src/cli/commands/init.js +65 -0
  18. package/src/cli/commands/preview.js +27 -0
  19. package/src/cli/commands/serve.js +26 -0
  20. package/src/cli/utils/resolveConfig.js +112 -0
  21. package/src/components/AddressMaker.global.vue +67 -0
  22. package/src/components/Animation/AnimationOpacity.global.vue +12 -0
  23. package/src/components/Autocomplete/Autocomplete.global.vue +223 -0
  24. package/src/components/Autocomplete/AutocompleteOtu.global.vue +33 -0
  25. package/src/components/Autocomplete/AutocompleteSpinner.vue +36 -0
  26. package/src/components/Button/ButtonExpand.global.vue +40 -0
  27. package/src/components/Button/VButton.global.vue +39 -0
  28. package/src/components/Card/VCard.global.vue +18 -0
  29. package/src/components/Card/VCardContent.global.vue +5 -0
  30. package/src/components/Card/VCardHeader.global.vue +7 -0
  31. package/src/components/Clipboard/VClipboard.global.vue +50 -0
  32. package/src/components/Dropdown/Dropdown.global.vue +108 -0
  33. package/src/components/Footer/FooterAnalytics.vue +26 -0
  34. package/src/components/Footer/FooterCitation.vue +45 -0
  35. package/src/components/Footer/FooterCopyright.vue +20 -0
  36. package/src/components/Gallery/GalleryCarousel/GalleryCarousel.global.vue +138 -0
  37. package/src/components/Gallery/GalleryImage.global.vue +65 -0
  38. package/src/components/Gallery/GalleryMainImage.vue +63 -0
  39. package/src/components/Gallery/GalleryMosaic/GalleryMosaic.global.vue +75 -0
  40. package/src/components/Gallery/GalleryThumbnail.vue +26 -0
  41. package/src/components/Gallery/GalleryThumbnailList.vue +34 -0
  42. package/src/components/Gallery/useGallery.js +50 -0
  43. package/src/components/Icon/IconArrowDown.global.vue +19 -0
  44. package/src/components/Icon/IconArrowLeft.global.vue +20 -0
  45. package/src/components/Icon/IconArrowRight.global.vue +20 -0
  46. package/src/components/Icon/IconArrowUp.global.vue +16 -0
  47. package/src/components/Icon/IconCalendar.global.vue +25 -0
  48. package/src/components/Icon/IconCheck.global.vue +16 -0
  49. package/src/components/Icon/IconClipboard.global.vue +16 -0
  50. package/src/components/Icon/IconClose.global.vue +20 -0
  51. package/src/components/Icon/IconDocument.global.vue +20 -0
  52. package/src/components/Icon/IconDownload.global.vue +16 -0
  53. package/src/components/Icon/IconFiles.global.vue +23 -0
  54. package/src/components/Icon/IconGithub.global.vue +11 -0
  55. package/src/components/Icon/IconHamburger.global.vue +18 -0
  56. package/src/components/Icon/IconInformation.global.vue +16 -0
  57. package/src/components/Icon/IconJson.global.vue +14 -0
  58. package/src/components/Icon/IconMinusCircle.global.vue +19 -0
  59. package/src/components/Icon/IconPause.global.vue +16 -0
  60. package/src/components/Icon/IconPlay.global.vue +16 -0
  61. package/src/components/Icon/IconPlusCircle.global.vue +19 -0
  62. package/src/components/Icon/IconSearch.global.vue +19 -0
  63. package/src/components/Icon/IconSpeakerWave.global.vue +16 -0
  64. package/src/components/Icon/IconSpeakerX.global.vue +16 -0
  65. package/src/components/Icon/IconTrash.global.vue +16 -0
  66. package/src/components/Icon/IconWarning.global.vue +16 -0
  67. package/src/components/ImageViewer/ControlImageNext.vue +11 -0
  68. package/src/components/ImageViewer/ControlImagePrevious.vue +10 -0
  69. package/src/components/ImageViewer/ImageAttribution.vue +15 -0
  70. package/src/components/ImageViewer/ImageDepictions.vue +21 -0
  71. package/src/components/ImageViewer/ImageSource.vue +15 -0
  72. package/src/components/ImageViewer/ImageToolbar.vue +14 -0
  73. package/src/components/ImageViewer/ImageViewer.global.vue +197 -0
  74. package/src/components/ImageViewer/ImageViewerClose.vue +12 -0
  75. package/src/components/ImageViewer/ImageViewerCounter.vue +16 -0
  76. package/src/components/Input/InputText.global.vue +30 -0
  77. package/src/components/Input/SelectInput.global.vue +31 -0
  78. package/src/components/Layout/LayoutFooter.vue +67 -0
  79. package/src/components/Layout/LayoutHeader.vue +62 -0
  80. package/src/components/Map/VMap.client.vue +365 -0
  81. package/src/components/Map/constants/disableLayerOptions.js +7 -0
  82. package/src/components/Map/constants/index.js +1 -0
  83. package/src/components/Map/icons/AssertedDistribution.js +5 -0
  84. package/src/components/Map/icons/CollectionObject.js +5 -0
  85. package/src/components/Map/icons/FieldOccurrence.js +5 -0
  86. package/src/components/Map/icons/Georeference.js +5 -0
  87. package/src/components/Map/icons/TypeMaterial.js +5 -0
  88. package/src/components/Map/icons/index.js +5 -0
  89. package/src/components/Map/shapes/Absent.js +8 -0
  90. package/src/components/Map/shapes/Aggregate.js +7 -0
  91. package/src/components/Map/shapes/AssertedDistribution.js +7 -0
  92. package/src/components/Map/shapes/CollectionObject.js +5 -0
  93. package/src/components/Map/shapes/FieldOccurrence.js +5 -0
  94. package/src/components/Map/shapes/TypeMaterial.js +5 -0
  95. package/src/components/Map/shapes/index.js +6 -0
  96. package/src/components/Map/utils/addPatternToMap.js +45 -0
  97. package/src/components/Map/utils/geojsonOptions.js +62 -0
  98. package/src/components/Map/utils/makeTileFromConfiguration.js +31 -0
  99. package/src/components/Markdown/MarkdownLayout.global.vue +36 -0
  100. package/src/components/Modal/VModal.global.vue +107 -0
  101. package/src/components/Navbar/NavbarMenu.vue +36 -0
  102. package/src/components/Navbar/NavbarMobile.vue +93 -0
  103. package/src/components/Navbar/NavbarSubmenu.vue +112 -0
  104. package/src/components/Pagination/VPagination.global.vue +139 -0
  105. package/src/components/Pagination/VPaginationInfo.global.vue +36 -0
  106. package/src/components/ProjectStats.global.vue +69 -0
  107. package/src/components/Ssr/ClientOnly.global.vue +14 -0
  108. package/src/components/SwitchTheme.vue +86 -0
  109. package/src/components/Tab/TabItem.global.vue +20 -0
  110. package/src/components/Tab/TabMenu.global.vue +7 -0
  111. package/src/components/Table/VTable.global.vue +7 -0
  112. package/src/components/Table/VTableBody.global.vue +7 -0
  113. package/src/components/Table/VTableBodyCell.global.vue +7 -0
  114. package/src/components/Table/VTableBodyRow.global.vue +5 -0
  115. package/src/components/Table/VTableHeader.global.vue +7 -0
  116. package/src/components/Table/VTableHeaderCell.global.vue +7 -0
  117. package/src/components/Table/VTableHeaderRow.global.vue +5 -0
  118. package/src/components/TrackerReport.global.vue +92 -0
  119. package/src/components/VSkeleton.global.vue +48 -0
  120. package/src/components/VSpinner.global.vue +219 -0
  121. package/src/components/clientComponents.js +28 -0
  122. package/src/components/globalComponents.js +29 -0
  123. package/src/constants/configPaths.cjs +4 -0
  124. package/src/constants/defaultConfig.js +7 -0
  125. package/src/constants/objectTypes.js +8 -0
  126. package/src/entry-client.js +39 -0
  127. package/src/entry-server.js +114 -0
  128. package/src/layout/Application.vue +21 -0
  129. package/src/main.js +20 -0
  130. package/src/modules/DwCFilter/components/DropdownMenu.vue +79 -0
  131. package/src/modules/DwCFilter/components/Facet/FacetDistribution.vue +47 -0
  132. package/src/modules/DwCFilter/components/Facet/FacetInstitutionCode.vue +17 -0
  133. package/src/modules/DwCFilter/components/Facet/FacetOrder.vue +38 -0
  134. package/src/modules/DwCFilter/components/Facet/FacetTypeStatus.vue +35 -0
  135. package/src/modules/DwCFilter/components/FilterBar.vue +123 -0
  136. package/src/modules/DwCFilter/components/OtuModal/OtuModal.vue +177 -0
  137. package/src/modules/DwCFilter/components/OtuModal/RecordItems.vue +89 -0
  138. package/src/modules/DwCFilter/components/OtuModal/TabList.vue +32 -0
  139. package/src/modules/DwCFilter/router/index.js +7 -0
  140. package/src/modules/DwCFilter/utils/flattenParameters.js +20 -0
  141. package/src/modules/DwCFilter/views/index.vue +183 -0
  142. package/src/modules/ImageMatrix/components/ListImages.vue +54 -0
  143. package/src/modules/ImageMatrix/router/index.js +7 -0
  144. package/src/modules/ImageMatrix/services/Keys.js +9 -0
  145. package/src/modules/ImageMatrix/utils/makeImageObject.js +15 -0
  146. package/src/modules/ImageMatrix/views/id.vue +133 -0
  147. package/src/modules/bibliography/components/DropdownMenu.vue +53 -0
  148. package/src/modules/bibliography/components/Facet/FacetFullCitation.vue +0 -0
  149. package/src/modules/bibliography/components/OtuModal.vue +129 -0
  150. package/src/modules/bibliography/components/VSlider.vue +154 -0
  151. package/src/modules/bibliography/components/YearPicker.vue +40 -0
  152. package/src/modules/bibliography/router/index.js +7 -0
  153. package/src/modules/bibliography/utils/getPagination.js +7 -0
  154. package/src/modules/bibliography/views/index.vue +225 -0
  155. package/src/modules/home/router/index.js +8 -0
  156. package/src/modules/home/views/index.vue +11 -0
  157. package/src/modules/httpErrorPages/router/index.js +18 -0
  158. package/src/modules/httpErrorPages/view/404.vue +10 -0
  159. package/src/modules/httpErrorPages/view/500.vue +11 -0
  160. package/src/modules/interactiveKeys/router/index.js +7 -0
  161. package/src/modules/interactiveKeys/views/InteractiveKey.vue +108 -0
  162. package/src/modules/keys/components/MetadataModal.vue +53 -0
  163. package/src/modules/keys/router/index.js +7 -0
  164. package/src/modules/keys/views/keyId.vue +161 -0
  165. package/src/modules/news/adapters/makeNews.js +21 -0
  166. package/src/modules/news/components/NewsCard.vue +35 -0
  167. package/src/modules/news/components/NewsCategories.vue +31 -0
  168. package/src/modules/news/components/PinnedNews.vue +70 -0
  169. package/src/modules/news/components/WidgetNews.global.vue +53 -0
  170. package/src/modules/news/router/index.js +12 -0
  171. package/src/modules/news/services/News.js +11 -0
  172. package/src/modules/news/store/news.js +50 -0
  173. package/src/modules/news/utils/getPagination.js +7 -0
  174. package/src/modules/news/views/id.vue +77 -0
  175. package/src/modules/news/views/index.vue +69 -0
  176. package/src/modules/otus/components/Breadcrumb/Breadcrumb.vue +40 -0
  177. package/src/modules/otus/components/Breadcrumb/BreadcrumbDropdown.vue +57 -0
  178. package/src/modules/otus/components/CommonNames.vue +14 -0
  179. package/src/modules/otus/components/DWCDownload.vue +33 -0
  180. package/src/modules/otus/components/DataMap.vue +57 -0
  181. package/src/modules/otus/components/Export.vue +1 -0
  182. package/src/modules/otus/components/ExternalResources.vue +11 -0
  183. package/src/modules/otus/components/Panel/PanelBiologicalAssociations/PanelBiologicalAssociations.vue +184 -0
  184. package/src/modules/otus/components/Panel/PanelBiologicalAssociations/main.js +6 -0
  185. package/src/modules/otus/components/Panel/PanelBiologicalAssociations/utils/makeBiologicalAssociation.js +30 -0
  186. package/src/modules/otus/components/Panel/PanelContent/PanelContent.vue +58 -0
  187. package/src/modules/otus/components/Panel/PanelContent/PanelContentTopic.vue +42 -0
  188. package/src/modules/otus/components/Panel/PanelContent/main.js +6 -0
  189. package/src/modules/otus/components/Panel/PanelDescendants/DescendantsSynonymList.vue +21 -0
  190. package/src/modules/otus/components/Panel/PanelDescendants/DescendantsTree.vue +122 -0
  191. package/src/modules/otus/components/Panel/PanelDescendants/PanelDescendants.vue +82 -0
  192. package/src/modules/otus/components/Panel/PanelDescendants/main.js +6 -0
  193. package/src/modules/otus/components/Panel/PanelDropdown.vue +63 -0
  194. package/src/modules/otus/components/Panel/PanelGallery/PanelGallery.vue +42 -0
  195. package/src/modules/otus/components/Panel/PanelGallery/main.js +7 -0
  196. package/src/modules/otus/components/Panel/PanelKeys/PanelKeys.vue +103 -0
  197. package/src/modules/otus/components/Panel/PanelKeys/main.js +6 -0
  198. package/src/modules/otus/components/Panel/PanelMap/PanelMap.vue +124 -0
  199. package/src/modules/otus/components/Panel/PanelMap/clusters/Mixed.js +50 -0
  200. package/src/modules/otus/components/Panel/PanelMap/clusters/index.js +2 -0
  201. package/src/modules/otus/components/Panel/PanelMap/clusters/makeClusterIconFor.js +10 -0
  202. package/src/modules/otus/components/Panel/PanelMap/components/CachedMap.vue +118 -0
  203. package/src/modules/otus/components/Panel/PanelMap/components/DwcTable.vue +64 -0
  204. package/src/modules/otus/components/Panel/PanelMap/components/MapPopup.vue +34 -0
  205. package/src/modules/otus/components/Panel/PanelMap/components/Search/ListResults.vue +51 -0
  206. package/src/modules/otus/components/Panel/PanelMap/components/Search/OtuSearch.vue +167 -0
  207. package/src/modules/otus/components/Panel/PanelMap/components/Search/SearchBar.vue +27 -0
  208. package/src/modules/otus/components/Panel/PanelMap/composables/useGeojsonOptions.js +36 -0
  209. package/src/modules/otus/components/Panel/PanelMap/constants/index.js +1 -0
  210. package/src/modules/otus/components/Panel/PanelMap/constants/legend.js +30 -0
  211. package/src/modules/otus/components/Panel/PanelMap/main.js +6 -0
  212. package/src/modules/otus/components/Panel/PanelMap/store/useDistributionStore.js +130 -0
  213. package/src/modules/otus/components/Panel/PanelMap/utils/index.js +4 -0
  214. package/src/modules/otus/components/Panel/PanelMap/utils/isRankGroup.js +5 -0
  215. package/src/modules/otus/components/Panel/PanelMap/utils/makeGeoJSONFeature.js +13 -0
  216. package/src/modules/otus/components/Panel/PanelMap/utils/makeSegmentedCircle.js +37 -0
  217. package/src/modules/otus/components/Panel/PanelMap/utils/removeDuplicateShapes.js +40 -0
  218. package/src/modules/otus/components/Panel/PanelNomenclature/PanelCitationRow.vue +25 -0
  219. package/src/modules/otus/components/Panel/PanelNomenclature/PanelNomenclature.vue +97 -0
  220. package/src/modules/otus/components/Panel/PanelNomenclature/PanelNomenclatureShowMore.vue +22 -0
  221. package/src/modules/otus/components/Panel/PanelNomenclature/main.js +6 -0
  222. package/src/modules/otus/components/Panel/PanelNomenclature/splitList.js +14 -0
  223. package/src/modules/otus/components/Panel/PanelNomenclatureReferences/PanelNomenclatureReferences.vue +72 -0
  224. package/src/modules/otus/components/Panel/PanelNomenclatureReferences/PanelReferenceRow.vue +20 -0
  225. package/src/modules/otus/components/Panel/PanelNomenclatureReferences/main.js +6 -0
  226. package/src/modules/otus/components/Panel/PanelSounds/PanelSounds.vue +42 -0
  227. package/src/modules/otus/components/Panel/PanelSounds/components/AudioPlayer.vue +275 -0
  228. package/src/modules/otus/components/Panel/PanelSounds/components/PanelSoundRow.vue +21 -0
  229. package/src/modules/otus/components/Panel/PanelSounds/components/SoundObservations.vue +73 -0
  230. package/src/modules/otus/components/Panel/PanelSounds/components/TableObservations.vue +31 -0
  231. package/src/modules/otus/components/Panel/PanelSounds/constants/observationTypes.js +15 -0
  232. package/src/modules/otus/components/Panel/PanelSounds/main.js +7 -0
  233. package/src/modules/otus/components/Panel/PanelSounds/utils/index.js +5 -0
  234. package/src/modules/otus/components/Panel/PanelSounds/utils/makeContinuousObservation.js +5 -0
  235. package/src/modules/otus/components/Panel/PanelSounds/utils/makeMediaObservation.js +5 -0
  236. package/src/modules/otus/components/Panel/PanelSounds/utils/makeObservation.js +40 -0
  237. package/src/modules/otus/components/Panel/PanelSounds/utils/makePresenceAbsenceObservation.js +5 -0
  238. package/src/modules/otus/components/Panel/PanelSounds/utils/makeQualitativeObservation.js +5 -0
  239. package/src/modules/otus/components/Panel/PanelSounds/utils/makeSampleObservation.js +29 -0
  240. package/src/modules/otus/components/Panel/PanelSounds/utils/makeWorkingObservation.js +5 -0
  241. package/src/modules/otus/components/Panel/PanelStats/PanelStats.vue +160 -0
  242. package/src/modules/otus/components/Panel/PanelStats/main.js +6 -0
  243. package/src/modules/otus/components/Panel/PanelTypeDesignation/PanelTypeDesignation.vue +37 -0
  244. package/src/modules/otus/components/Panel/PanelTypeDesignation/main.js +8 -0
  245. package/src/modules/otus/components/Panel/PanelTypeSpecimen/PanelTypeSpecimen.vue +52 -0
  246. package/src/modules/otus/components/Panel/PanelTypeSpecimen/main.js +8 -0
  247. package/src/modules/otus/components/TaxaInfo.vue +38 -0
  248. package/src/modules/otus/composables/index.js +2 -0
  249. package/src/modules/otus/composables/useChildrenRoutes.js +32 -0
  250. package/src/modules/otus/composables/useUserLifeCycleHooks.js +24 -0
  251. package/src/modules/otus/constants/index.js +3 -0
  252. package/src/modules/otus/constants/layouts/index.js +1 -0
  253. package/src/modules/otus/constants/layouts/overview.js +23 -0
  254. package/src/modules/otus/constants/layouts.js +43 -0
  255. package/src/modules/otus/constants/rankGroups.js +5 -0
  256. package/src/modules/otus/constants/responseError.js +3 -0
  257. package/src/modules/otus/constants/typeOrder.js +11 -0
  258. package/src/modules/otus/helpers/useOtuPageRequest.js +19 -0
  259. package/src/modules/otus/router/index.js +28 -0
  260. package/src/modules/otus/services/TaxonWorks.js +77 -0
  261. package/src/modules/otus/store/request.js +34 -0
  262. package/src/modules/otus/store/store.js +92 -0
  263. package/src/modules/otus/store/useImageStore.js +57 -0
  264. package/src/modules/otus/utils/index.js +2 -0
  265. package/src/modules/otus/utils/isAvailableForRank.js +6 -0
  266. package/src/modules/otus/utils/stripHtml.js +5 -0
  267. package/src/modules/otus/views/Index.vue +218 -0
  268. package/src/modules/otus/views/PageLayout.vue +78 -0
  269. package/src/modules/setup/views/Index.vue +66 -0
  270. package/src/plugins/markdown/index.js +2 -0
  271. package/src/plugins/markdown/relativeToRouter.js +51 -0
  272. package/src/plugins/markdown/variableReplacement.js +14 -0
  273. package/src/plugins/schemaOrg/composables/index.js +28 -0
  274. package/src/plugins/schemaOrg/index.js +31 -0
  275. package/src/plugins/schemaOrg/loadResolver.js +10 -0
  276. package/src/plugins/schemaOrg/nodes/Taxon.js +82 -0
  277. package/src/plugins/schemaOrg/nodes/index.js +1 -0
  278. package/src/plugins/vite/index.js +2 -0
  279. package/src/plugins/vite/projectStyle.js +29 -0
  280. package/src/plugins/vite/restart.js +30 -0
  281. package/src/router/index.js +46 -0
  282. package/src/ssr/utils/generateConsoleMessage.js +16 -0
  283. package/src/ssr/utils/registerFakeClientComponents.js +20 -0
  284. package/src/ssr/utils/taxonPagesMark.txt +9 -0
  285. package/src/store/index.js +1 -0
  286. package/src/store/useFooterStore.js +13 -0
  287. package/src/utils/color.js +9 -0
  288. package/src/utils/files.js +21 -0
  289. package/src/utils/globalVars.js +7 -0
  290. package/src/utils/index.js +5 -0
  291. package/src/utils/loadConfiguration.js +34 -0
  292. package/src/utils/loadLayouts.js +21 -0
  293. package/src/utils/parseEnvConfig.js +0 -0
  294. package/src/utils/request.js +18 -0
  295. package/src/utils/strings.js +12 -0
  296. package/src/utils/url.js +8 -0
  297. package/tailwind.config.cjs +92 -0
  298. package/templates/config/analytics.yml.example +22 -0
  299. package/templates/config/api.yml +5 -0
  300. package/templates/config/copyright.yml +5 -0
  301. package/templates/config/header.yml +17 -0
  302. package/templates/config/maps.yml +16 -0
  303. package/templates/config/metadata.yml +10 -0
  304. package/templates/config/news.yml.example +15 -0
  305. package/templates/config/project.yml +6 -0
  306. package/templates/config/router.yml.example +4 -0
  307. package/templates/config/style/theme.css +48 -0
  308. package/templates/config/taxa_page.yml.example +22 -0
  309. package/templates/config/tracker.yml.example +8 -0
  310. package/templates/pages/about.md +44 -0
  311. package/templates/pages/home.md +26 -0
  312. package/vite.config.js +92 -0
@@ -0,0 +1,20 @@
1
+ export function flattenParameters(obj, prefix = '') {
2
+ const result = {}
3
+
4
+ for (const key in obj) {
5
+ if (!obj.hasOwnProperty(key)) continue
6
+
7
+ const value = obj[key]
8
+ const newKey = prefix ? `${prefix}[${key}]` : key
9
+
10
+ if (Array.isArray(value)) {
11
+ result[`${newKey}[]`] = value
12
+ } else if (typeof value === 'object' && value !== null) {
13
+ Object.assign(result, flattenParameters(value, newKey))
14
+ } else {
15
+ result[newKey] = value
16
+ }
17
+ }
18
+
19
+ return result
20
+ }
@@ -0,0 +1,183 @@
1
+ <template>
2
+ <div class="container mx-auto box-border">
3
+ <div class="px-4 md:px-0 mt-4 mb-6">
4
+ <h1 class="text-4xl font-bold">Search the Darwin Core</h1>
5
+ <h2>
6
+ Filter OTUs by scientific name, author, and distribution (Darwin Core)
7
+ </h2>
8
+ </div>
9
+ <ClientOnly>
10
+ <VSpinner
11
+ v-if="isLoading"
12
+ full-screen
13
+ />
14
+ </ClientOnly>
15
+ <FilterBar
16
+ v-model="parameters"
17
+ @search="() => loadList()"
18
+ @reset="reset"
19
+ />
20
+
21
+ <VCard>
22
+ <VCardContent>
23
+ <div class="flex flex-row justify-between items-center mb-4">
24
+ <div class="flex flex-col md:flex-row gap-3 md:items-center">
25
+ <VPagination
26
+ v-model="pagination.page"
27
+ :total="pagination.total"
28
+ :per="pagination.per"
29
+ @update:modelValue="
30
+ (page) => {
31
+ loadList(page)
32
+ }
33
+ "
34
+ />
35
+ <VPaginationInfo :pagination="pagination" />
36
+ </div>
37
+ <DropdownMenu
38
+ :parameters="{ ...parameters, ...wildcardParam }"
39
+ :request="requestData"
40
+ />
41
+ </div>
42
+
43
+ <VTable>
44
+ <VTableHeader>
45
+ <VTableHeaderRow>
46
+ <VTableHeaderCell class="w-2" />
47
+ <VTableHeaderCell>OTU</VTableHeaderCell>
48
+ </VTableHeaderRow>
49
+ </VTableHeader>
50
+ <VTableBody>
51
+ <VTableBodyRow
52
+ v-for="item in list"
53
+ :key="item.id"
54
+ >
55
+ <VTableBodyCell class="pr-1">
56
+ <OtuModal
57
+ :otu="item"
58
+ :parameters="{ ...parameters, ...wildcardParam }"
59
+ />
60
+ </VTableBodyCell>
61
+ <VTableBodyCell class="break-all">
62
+ <RouterLink
63
+ :to="{ name: 'otus-id', params: { id: item.id } }"
64
+ v-html="item.object_tag"
65
+ />
66
+ </VTableBodyCell>
67
+ </VTableBodyRow>
68
+ </VTableBody>
69
+ </VTable>
70
+ <div class="flex flex-col md:flex-row gap-3 md:items-center mt-4">
71
+ <VPagination
72
+ v-model="pagination.page"
73
+ :total="pagination.total"
74
+ :per="pagination.per"
75
+ @select="
76
+ (page) => {
77
+ loadList(page)
78
+ }
79
+ "
80
+ />
81
+ <VPaginationInfo :pagination="pagination" />
82
+ </div>
83
+ </VCardContent>
84
+ </VCard>
85
+ </div>
86
+ </template>
87
+
88
+ <script setup>
89
+ import { onMounted, ref, computed } from 'vue'
90
+ import { makeAPIRequest } from '@/utils'
91
+ import { useRoute, useRouter } from 'vue-router'
92
+ import { flattenParameters } from '../utils/flattenParameters'
93
+ import FilterBar from '../components/FilterBar.vue'
94
+ import DropdownMenu from '../components/DropdownMenu.vue'
95
+ import OtuModal from '../components/OtuModal/OtuModal.vue'
96
+
97
+ const PER = 50
98
+
99
+ const route = useRoute()
100
+ const router = useRouter()
101
+
102
+ const list = ref([])
103
+ const isLoading = ref(false)
104
+ const pagination = ref({ page: 1, total: 0, per: PER })
105
+ const parameters = ref({})
106
+ const requestData = ref()
107
+ const wildcardParam = computed(() => ({
108
+ wildcard_attribute: Object.keys(parameters.value)
109
+ }))
110
+
111
+ function getPagination(headers) {
112
+ return {
113
+ page: Number(headers['pagination-page']),
114
+ per: Number(headers['pagination-per-page']),
115
+ total: Number(headers['pagination-total'])
116
+ }
117
+ }
118
+
119
+ function setParameters(data = {}) {
120
+ parameters.value = data
121
+ }
122
+
123
+ function setPagination(data = {}) {
124
+ pagination.value = {
125
+ page: Number(data.page) || 1,
126
+ total: 0,
127
+ per: PER
128
+ }
129
+ }
130
+
131
+ function setQuery() {
132
+ router.push({
133
+ query: { ...parameters.value, page: pagination.value.page }
134
+ })
135
+ }
136
+
137
+ function loadList(page = 1) {
138
+ isLoading.value = true
139
+
140
+ makeAPIRequest
141
+ .get('/otus/inventory/alphabetical', {
142
+ params: {
143
+ ...flattenParameters({
144
+ dwc_occurrence_query: {
145
+ ...parameters.value,
146
+ ...wildcardParam.value
147
+ }
148
+ }),
149
+ page,
150
+ per: PER
151
+ }
152
+ })
153
+ .then(({ data, headers, request }) => {
154
+ list.value = data
155
+ pagination.value = getPagination(headers)
156
+
157
+ requestData.value = {
158
+ data,
159
+ url: request.responseURL
160
+ }
161
+
162
+ setQuery()
163
+ })
164
+ .finally(() => {
165
+ isLoading.value = false
166
+ })
167
+ }
168
+
169
+ function reset() {
170
+ setParameters()
171
+ setPagination()
172
+ setQuery()
173
+ list.value = []
174
+ }
175
+
176
+ onMounted(() => {
177
+ const { page, ...params } = route.query
178
+
179
+ setParameters(params)
180
+ setPagination({ page })
181
+ loadList()
182
+ })
183
+ </script>
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <GalleryThumbnailList
3
+ :images="images"
4
+ @select-index="
5
+ (index) => {
6
+ galleryIndex = index
7
+ isImageViewerOpen = true
8
+ }
9
+ "
10
+ />
11
+
12
+ <ImageViewer
13
+ v-if="isImageViewerOpen"
14
+ :index="galleryIndex"
15
+ :images="images"
16
+ :next="galleryIndex < props.images.length - 1"
17
+ :previous="galleryIndex > 0"
18
+ @select-index="galleryIndex = $event"
19
+ @next="nextImage()"
20
+ @previous="previousImage()"
21
+ @close="isImageViewerOpen = false"
22
+ />
23
+ </template>
24
+
25
+ <script setup>
26
+ import { ref, computed, watch } from 'vue'
27
+ import GalleryThumbnailList from '@/components/Gallery/GalleryThumbnailList.vue'
28
+
29
+ const props = defineProps({
30
+ images: {
31
+ type: Array,
32
+ default: () => []
33
+ }
34
+ })
35
+
36
+ const isImageViewerOpen = ref(false)
37
+ const galleryIndex = ref(0)
38
+ const currentImage = computed(() => props.images[galleryIndex.value] || {})
39
+
40
+ const previousImage = () => {
41
+ galleryIndex.value--
42
+ }
43
+ const nextImage = () => {
44
+ galleryIndex.value++
45
+ }
46
+
47
+ watch(
48
+ () => props.images,
49
+ () => {
50
+ galleryIndex.value = 0
51
+ },
52
+ { immediate: true }
53
+ )
54
+ </script>
@@ -0,0 +1,7 @@
1
+ export default [
2
+ {
3
+ name: 'image-matrices-id',
4
+ path: '/image_matrices/:id',
5
+ component: () => import('../views/id.vue')
6
+ }
7
+ ]
@@ -0,0 +1,9 @@
1
+ import { makeAPIRequest } from '@/utils'
2
+
3
+ export class ObservationMatrixImage {
4
+ static find(id, params) {
5
+ return makeAPIRequest.get(`/observation_matrices/${id}/image_matrix`, {
6
+ params
7
+ })
8
+ }
9
+ }
@@ -0,0 +1,15 @@
1
+ function makeOriginalImageUrl(imagePath) {
2
+ const { url, project_token } = __APP_ENV__
3
+
4
+ return `${url}/${imagePath?.substring(8)}?project_token=${project_token}`
5
+ }
6
+
7
+ export function makeImageObject(item) {
8
+ return {
9
+ depiction: {
10
+ label: item.figure_label
11
+ },
12
+ ...item.image,
13
+ original: makeOriginalImageUrl(item.image.original_png)
14
+ }
15
+ }
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <VCard class="container mx-auto">
3
+ <VSpinner
4
+ v-if="isLoading"
5
+ full-screen
6
+ />
7
+ <VCardHeader>
8
+ <div class="flex flex-row justify-between items-center">
9
+ <h1>{{ observationMatrix.name }}</h1>
10
+ <VPagination
11
+ v-if="pagination"
12
+ :total="pagination.total"
13
+ v-model="pagination.page"
14
+ :per="PER"
15
+ @select="(page) => loadMatrix(matrixId, page)"
16
+ />
17
+ </div>
18
+ </VCardHeader>
19
+ <VCardContent>
20
+ <div class="image-matrix overflow-auto">
21
+ <VTable>
22
+ <caption class="sr-only">
23
+ Image matrix
24
+ </caption>
25
+ <VTableHeader>
26
+ <VTableHeaderRow class="bg-base-foreground">
27
+ <VTableBodyCell class="border-b" />
28
+ <VTableHeaderCell
29
+ v-for="{ id, label } in descriptors"
30
+ :key="id"
31
+ class="border-l border-b"
32
+ scope="col"
33
+ >
34
+ {{ label }}
35
+ </VTableHeaderCell>
36
+ </VTableHeaderRow>
37
+ </VTableHeader>
38
+ <VTableBody>
39
+ <VTableBodyRow v-for="item in list">
40
+ <VTableBodyCell class="border-b text-base-content h-20">
41
+ <RouterLink
42
+ :to="{ name: 'otus-id', params: { id: item.id } }"
43
+ v-html="item.label"
44
+ />
45
+ </VTableBodyCell>
46
+ <VTableBodyCell
47
+ v-for="images in item.depictions"
48
+ class="border-l border-b"
49
+ >
50
+ <ListImage :images="images" />
51
+ </VTableBodyCell>
52
+ </VTableBodyRow>
53
+ </VTableBody>
54
+ </VTable>
55
+ </div>
56
+ </VCardContent>
57
+ </VCard>
58
+ </template>
59
+
60
+ <script setup>
61
+ import { ref } from 'vue'
62
+ import { useRoute } from 'vue-router'
63
+ import { makeImageObject } from '../utils/makeImageObject.js'
64
+ import ListImage from '../components/ListImages.vue'
65
+ import { ObservationMatrixImage } from '../services/Keys.js'
66
+
67
+ const PER = 50
68
+
69
+ const list = ref([])
70
+ const isLoading = ref(false)
71
+ const descriptors = ref([])
72
+ const observationMatrix = ref({})
73
+ const route = useRoute()
74
+ const pagination = ref()
75
+
76
+ const matrixId = route.params.id
77
+
78
+ async function loadMatrix(id, page = 1) {
79
+ isLoading.value = true
80
+
81
+ try {
82
+ const { data } = await ObservationMatrixImage.find(id, {
83
+ page,
84
+ per: PER
85
+ })
86
+
87
+ observationMatrix.value = data.observation_matrix
88
+ descriptors.value = data.list_of_descriptors.map((item) => ({
89
+ label: item.name,
90
+ id: item.id
91
+ }))
92
+
93
+ pagination.value = {
94
+ page: data.pagination.pagination_page,
95
+ total: data.pagination.pagination_total,
96
+ per: data.pagination.pagination_per_page
97
+ }
98
+
99
+ list.value = data.depiction_matrix.map((item) => {
100
+ const obj = {
101
+ id: item.object.id,
102
+ type: item.object.type,
103
+ label: item.object.label,
104
+ depictions: []
105
+ }
106
+
107
+ for (let i = 0; i < descriptors.value.length; i++) {
108
+ const depictions = item.depictions[i].map((d) =>
109
+ makeImageObject({
110
+ ...d,
111
+ ...data.image_hash[d.image_id]
112
+ })
113
+ )
114
+
115
+ obj.depictions.push(depictions)
116
+ }
117
+
118
+ return obj
119
+ })
120
+ } catch {
121
+ } finally {
122
+ isLoading.value = false
123
+ }
124
+ }
125
+
126
+ loadMatrix(route.params.id)
127
+ </script>
128
+
129
+ <style scoped>
130
+ .image-matrix {
131
+ max-height: calc(100vh - 12rem);
132
+ }
133
+ </style>
@@ -0,0 +1,53 @@
1
+ <template>
2
+ <Dropdown :items="menuOptions">
3
+ <template #button>
4
+ <IconHamburger class="text-base-soft h-4" />
5
+ </template>
6
+ </Dropdown>
7
+ <VModal
8
+ v-if="isModalVisible"
9
+ @close="isModalVisible = false"
10
+ >
11
+ <template #header>
12
+ <h3>JSON Data</h3>
13
+ </template>
14
+ <div
15
+ v-if="request"
16
+ class="p-5 font-normal"
17
+ >
18
+ <h3 class="pb-2 text-sm">
19
+ URL: <a :href="request.url">{{ request.url }}</a>
20
+ </h3>
21
+ <div class="relative">
22
+ <p
23
+ class="bg-base-background p-2 text-sm font-normal whitespace-pre-wrap"
24
+ v-html="JSON.stringify(request.data, null, 4)"
25
+ />
26
+ <VClipboard
27
+ class="absolute right-2 top-2 opacity-75"
28
+ :text="JSON.stringify(request.data, null, 2)"
29
+ />
30
+ </div>
31
+ </div>
32
+ </VModal>
33
+ </template>
34
+
35
+ <script setup>
36
+ import { ref, computed } from 'vue'
37
+
38
+ const props = defineProps({
39
+ request: {
40
+ type: Object,
41
+ default: () => ({})
42
+ }
43
+ })
44
+
45
+ const isModalVisible = ref(false)
46
+
47
+ const menuOptions = computed(() => [
48
+ {
49
+ label: 'JSON Data',
50
+ action: () => (isModalVisible.value = true)
51
+ }
52
+ ])
53
+ </script>
@@ -0,0 +1,129 @@
1
+ <template>
2
+ <IconPlusCircle
3
+ class="size-6 text-secondary-color cursor-pointer"
4
+ @click="() => (isModalVisible = true)"
5
+ />
6
+ <Teleport to="body">
7
+ <VModal
8
+ v-if="isModalVisible"
9
+ @close="() => (isModalVisible = false)"
10
+ >
11
+ <template #header>
12
+ <div class="text-sm">Bibliography - <span v-html="label" /></div>
13
+ </template>
14
+
15
+ <div class="md:max-h-[64vh] min-h-28 px-4 overflow-y-auto pb-4">
16
+ <ClientOnly>
17
+ <VSpinner v-if="isLoading" />
18
+ </ClientOnly>
19
+
20
+ <div
21
+ v-if="!isLoading && !list.length"
22
+ class="text-xl text-center my-8 w-full"
23
+ >
24
+ No records found.
25
+ </div>
26
+
27
+ <div v-if="list.length">
28
+ <VPagination
29
+ v-if="pagination.total > pagination.per"
30
+ class="py-4"
31
+ v-model="pagination.page"
32
+ :total="pagination.total"
33
+ :per="pagination.per"
34
+ @update:modelValue="
35
+ (page) => {
36
+ loadPage(page)
37
+ }
38
+ "
39
+ />
40
+
41
+ <VTable>
42
+ <VTableHeader>
43
+ <VTableHeaderRow>
44
+ <VTableHeaderCell>OTU</VTableHeaderCell>
45
+ </VTableHeaderRow>
46
+ </VTableHeader>
47
+ <VTableBody>
48
+ <VTableBodyRow
49
+ v-for="otu in list"
50
+ :key="otu.id"
51
+ >
52
+ <VTableBodyCell>
53
+ <RouterLink
54
+ :to="{ name: 'otus-id', params: { id: otu.id } }"
55
+ v-html="otu.object_tag"
56
+ />
57
+ </VTableBodyCell>
58
+ </VTableBodyRow>
59
+ </VTableBody>
60
+ </VTable>
61
+
62
+ <VPagination
63
+ v-if="pagination.total > pagination.per"
64
+ class="pt-4"
65
+ v-model="pagination.page"
66
+ :total="pagination.total"
67
+ :per="pagination.per"
68
+ @update:modelValue="
69
+ (page) => {
70
+ loadPage(page)
71
+ }
72
+ "
73
+ />
74
+ </div>
75
+ </div>
76
+ </VModal>
77
+ </Teleport>
78
+ </template>
79
+
80
+ <script setup>
81
+ import { ref, watch } from 'vue'
82
+ import { makeAPIRequest } from '@/utils'
83
+ import { getPagination } from '../utils/getPagination'
84
+
85
+ const props = defineProps({
86
+ sourceId: {
87
+ type: Number,
88
+ required: true
89
+ },
90
+
91
+ label: {
92
+ type: String,
93
+ required: true
94
+ }
95
+ })
96
+
97
+ const pagination = ref({ page: 1, total: 0, per: 50 })
98
+
99
+ const isLoading = ref(false)
100
+ const isModalVisible = ref(false)
101
+ const list = ref([])
102
+
103
+ function loadPage(page = 1) {
104
+ isLoading.value = true
105
+ makeAPIRequest
106
+ .get('/otus', {
107
+ params: {
108
+ page,
109
+ per: 50,
110
+ 'taxon_name_query[source_query][source_id][]': props.sourceId,
111
+ paginate: true
112
+ }
113
+ })
114
+ .then(({ data, headers }) => {
115
+ list.value = data
116
+ pagination.value = getPagination(headers)
117
+ })
118
+ .catch(() => {})
119
+ .finally(() => {
120
+ isLoading.value = false
121
+ })
122
+ }
123
+
124
+ watch(isModalVisible, (newVal) => {
125
+ if (newVal) {
126
+ loadPage()
127
+ }
128
+ })
129
+ </script>