@tekkare/romulus 0.1.251 → 0.1.253

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 (267) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/utils/projects.d.ts +8 -0
  3. package/dist/runtime/utils/projects.js +8 -5
  4. package/layer/app/app.config.ts +6 -0
  5. package/layer/app/components/OipPubmedSummary.vue +223 -0
  6. package/layer/app/components/OipResourceDrawer.vue +331 -0
  7. package/layer/app/components/OipResourceDrawerLink.vue +40 -0
  8. package/layer/app/components/OipResourceField.vue +41 -0
  9. package/layer/app/components/OipResourceGenericCard.vue +54 -0
  10. package/layer/app/components/OipResourceSource.vue +50 -0
  11. package/layer/app/components/OipResourceTags.vue +65 -0
  12. package/layer/app/components/OipResourceView.vue +107 -0
  13. package/layer/app/components/oip-drugs/fiches/AssociationFiche.vue +775 -0
  14. package/layer/app/components/oip-drugs/fiches/BrandFiche.vue +1111 -0
  15. package/layer/app/components/oip-drugs/fiches/IndicationFiche.vue +182 -0
  16. package/layer/app/components/oip-drugs/fiches/JoFiche.vue +101 -0
  17. package/layer/app/components/oip-drugs/fiches/PndsFiche.vue +279 -0
  18. package/layer/app/components/oip-drugs/heart/JoCard.vue +314 -0
  19. package/layer/app/components/oip-drugs/heart/TextHighlight.vue +326 -0
  20. package/layer/app/components/oip-drugs/heart/ansm/BrandCard.vue +187 -0
  21. package/layer/app/components/oip-drugs/heart/ansm/CisDetail.vue +363 -0
  22. package/layer/app/components/oip-drugs/heart/ansm/CisTable.vue +167 -0
  23. package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyCard.vue +373 -0
  24. package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyFiche.vue +372 -0
  25. package/layer/app/components/oip-drugs/heart/associations/TranscriptionCard.vue +55 -0
  26. package/layer/app/components/oip-drugs/heart/elastic/SourceContainerElastic.vue +103 -0
  27. package/layer/app/components/oip-drugs/heart/france/BrandGroupCard.vue +450 -0
  28. package/layer/app/components/oip-drugs/heart/mitm/Card.vue +199 -0
  29. package/layer/app/components/oip-drugs/heart/mitm/Source.vue +23 -0
  30. package/layer/app/components/oip-drugs/heart/mitm/details/Overview.vue +381 -0
  31. package/layer/app/components/oip-drugs/heart/put/Card.vue +212 -0
  32. package/layer/app/components/oip-drugs/heart/results/AccesCard.vue +696 -0
  33. package/layer/app/components/oip-drugs/heart/results/AlertCard.vue +342 -0
  34. package/layer/app/components/oip-drugs/heart/results/AsmrCursor.vue +229 -0
  35. package/layer/app/components/oip-drugs/heart/results/EvalCard.vue +370 -0
  36. package/layer/app/components/oip-drugs/heart/results/IndicCard.vue +743 -0
  37. package/layer/app/components/oip-drugs/heart/results/MatchExplain.vue +243 -0
  38. package/layer/app/components/oip-drugs/heart/results/PrefRows.vue +105 -0
  39. package/layer/app/components/oip-drugs/heart/results/details/HasHistory.vue +487 -0
  40. package/layer/app/components/oip-drugs/heart/results/details/InternationalCountryCard.vue +461 -0
  41. package/layer/app/components/oip-drugs/heart/results/details/InternationalOverview.vue +200 -0
  42. package/layer/app/components/oip-drugs/heart/results/details/InternationalPriceDrawer.vue +647 -0
  43. package/layer/app/components/oip-drugs/heart/results/details/Monograph.vue +128 -0
  44. package/layer/app/components/oip-drugs/heart/results/details/OpinionDrawer.vue +535 -0
  45. package/layer/app/components/oip-drugs/heart/results/details/PresentationDrawer.vue +738 -0
  46. package/layer/app/components/oip-drugs/heart/results/details/Price.vue +227 -0
  47. package/layer/app/components/oip-drugs/heart/results/details/PriceOverview.vue +1261 -0
  48. package/layer/app/components/oip-drugs/heart/results/details/RecordDrawer.vue +494 -0
  49. package/layer/app/components/oip-drugs/heart/results/details/RecordList.vue +426 -0
  50. package/layer/app/components/oip-drugs/heart/results/les/Card.vue +340 -0
  51. package/layer/app/components/oip-drugs/heart/results/les/Drawer.vue +67 -0
  52. package/layer/app/components/oip-drugs/heart/results/les/IndicationDetail.vue +149 -0
  53. package/layer/app/components/oip-drugs/heart/results/les/Source.vue +20 -0
  54. package/layer/app/components/oip-drugs/heart/results/les/SourceTag.vue +39 -0
  55. package/layer/app/components/oip-drugs/heart/searchPage/DynamicSource.vue +29 -0
  56. package/layer/app/components/oip-drugs/medicam/market/Chart.vue +121 -0
  57. package/layer/app/components/oip-drugs/outpatient/ProductEvolution.vue +236 -0
  58. package/layer/app/components/oip-drugs/resources/Ansm.vue +75 -0
  59. package/layer/app/components/oip-drugs/resources/Association.vue +30 -0
  60. package/layer/app/components/oip-drugs/resources/Brand.vue +65 -0
  61. package/layer/app/components/oip-drugs/resources/Contribution.vue +216 -0
  62. package/layer/app/components/oip-drugs/resources/Hospital.vue +151 -0
  63. package/layer/app/components/oip-drugs/resources/Indication.vue +54 -0
  64. package/layer/app/components/oip-drugs/resources/Jo.vue +57 -0
  65. package/layer/app/components/oip-drugs/resources/Medicam.vue +140 -0
  66. package/layer/app/components/oip-drugs/resources/Mitm.vue +84 -0
  67. package/layer/app/components/oip-drugs/resources/NationalAssembly.vue +93 -0
  68. package/layer/app/components/oip-drugs/resources/Outpatient.vue +97 -0
  69. package/layer/app/components/oip-drugs/resources/Pnds.vue +24 -0
  70. package/layer/app/components/oip-drugs/resources/Price.vue +106 -0
  71. package/layer/app/components/oip-drugs/resources/Put.vue +143 -0
  72. package/layer/app/components/oip-science/appel-a-projet/Cards.vue +162 -0
  73. package/layer/app/components/oip-science/clinical-trials/Cards.vue +382 -0
  74. package/layer/app/components/oip-science/clinical-trials/CardsGlobal.vue +273 -0
  75. package/layer/app/components/oip-science/clinical-trials/LinkedList.vue +366 -0
  76. package/layer/app/components/oip-science/clinical-trials/PairBadge.vue +25 -0
  77. package/layer/app/components/oip-science/clinical-trials/PairBody.vue +182 -0
  78. package/layer/app/components/oip-science/clinical-trials/SitesDrawer.vue +95 -0
  79. package/layer/app/components/oip-science/common/Form.vue +73 -0
  80. package/layer/app/components/oip-science/common/MatchAvgTag.vue +283 -0
  81. package/layer/app/components/oip-science/common/NoData.vue +16 -0
  82. package/layer/app/components/oip-science/common/ScoreBadge.vue +35 -0
  83. package/layer/app/components/oip-science/common/Source.vue +31 -0
  84. package/layer/app/components/oip-science/common/TableTags.vue +279 -0
  85. package/layer/app/components/oip-science/common/Timeline.vue +104 -0
  86. package/layer/app/components/oip-science/common/ToolTips.vue +89 -0
  87. package/layer/app/components/oip-science/cross/publicationPubmed.vue +484 -0
  88. package/layer/app/components/oip-science/crossData/CrossDataLocations.vue +71 -0
  89. package/layer/app/components/oip-science/ctgov/Investigators.vue +148 -0
  90. package/layer/app/components/oip-science/ctgov/Locations.vue +102 -0
  91. package/layer/app/components/oip-science/ctgov/Publications.vue +52 -0
  92. package/layer/app/components/oip-science/ctgov/Sponsors.vue +66 -0
  93. package/layer/app/components/oip-science/ctgov/StudyDescription.vue +1136 -0
  94. package/layer/app/components/oip-science/ctgov-centers/ClinicalTrials.vue +40 -0
  95. package/layer/app/components/oip-science/ctgov-centers/Publications.vue +50 -0
  96. package/layer/app/components/oip-science/ctgov-investigators/ClinicalTrials.vue +43 -0
  97. package/layer/app/components/oip-science/ctgov-investigators/Informations.vue +171 -0
  98. package/layer/app/components/oip-science/ctgov-investigators/Publications.vue +44 -0
  99. package/layer/app/components/oip-science/elastic/DateRangeFilter.vue +209 -0
  100. package/layer/app/components/oip-science/elastic/Filter.vue +719 -0
  101. package/layer/app/components/oip-science/elastic/MatchExplain.vue +152 -0
  102. package/layer/app/components/oip-science/establishments/Cards.vue +183 -0
  103. package/layer/app/components/oip-science/establishments/ClinicalTrials.vue +62 -0
  104. package/layer/app/components/oip-science/establishments/Hcps.vue +227 -0
  105. package/layer/app/components/oip-science/establishments/Informations.vue +263 -0
  106. package/layer/app/components/oip-science/establishments/LinkedList.vue +153 -0
  107. package/layer/app/components/oip-science/establishments/MatchedLabels.vue +194 -0
  108. package/layer/app/components/oip-science/establishments/PublicFinance.vue +62 -0
  109. package/layer/app/components/oip-science/euct/Investigators.vue +125 -0
  110. package/layer/app/components/oip-science/euct/Locations.vue +102 -0
  111. package/layer/app/components/oip-science/euct/Products.vue +101 -0
  112. package/layer/app/components/oip-science/euct/Publications.vue +89 -0
  113. package/layer/app/components/oip-science/euct/Sponsors.vue +86 -0
  114. package/layer/app/components/oip-science/euct/StudyDescription.vue +1075 -0
  115. package/layer/app/components/oip-science/euct-centers/ClinicalTrials.vue +40 -0
  116. package/layer/app/components/oip-science/euct-centers/Publications.vue +55 -0
  117. package/layer/app/components/oip-science/euct-investigators/ClinicalTrials.vue +41 -0
  118. package/layer/app/components/oip-science/euct-investigators/Informations.vue +171 -0
  119. package/layer/app/components/oip-science/euct-investigators/Publications.vue +51 -0
  120. package/layer/app/components/oip-science/hcps/AppelsAProjet.vue +62 -0
  121. package/layer/app/components/oip-science/hcps/Cards.vue +237 -0
  122. package/layer/app/components/oip-science/hcps/ClinicalTrials.vue +78 -0
  123. package/layer/app/components/oip-science/hcps/Informations.vue +296 -0
  124. package/layer/app/components/oip-science/hcps/LinkedList.vue +153 -0
  125. package/layer/app/components/oip-science/hcps/MatchedLabels.vue +207 -0
  126. package/layer/app/components/oip-science/hcps/Pubmed.vue +128 -0
  127. package/layer/app/components/oip-science/local/SliderTabs.vue +99 -0
  128. package/layer/app/components/oip-science/local/SliderTabsFull.vue +135 -0
  129. package/layer/app/components/oip-science/pubmed/Authors.vue +128 -0
  130. package/layer/app/components/oip-science/pubmed/Cards.vue +417 -0
  131. package/layer/app/components/oip-science/pubmed/ClinicalTrials.vue +71 -0
  132. package/layer/app/components/oip-science/resources/Phrc.vue +39 -0
  133. package/layer/app/composables/useOipChapterScroll.ts +43 -0
  134. package/layer/app/composables/useOipResourceHooks.ts +27 -0
  135. package/layer/app/composables/useOipResourceNav.ts +66 -0
  136. package/layer/app/composables/useOipResourceViews.ts +117 -0
  137. package/layer/app/composables/useOipResources.ts +83 -0
  138. package/layer/app/oip-drugs/PORTING.md +120 -0
  139. package/layer/app/oip-drugs/composables/useAssociationDetail.ts +220 -0
  140. package/layer/app/oip-drugs/composables/useAssociationExport.ts +63 -0
  141. package/layer/app/oip-drugs/composables/useAssociationLookup.ts +105 -0
  142. package/layer/app/oip-drugs/composables/useCardPrefOptions.ts +201 -0
  143. package/layer/app/oip-drugs/composables/useCurrency.ts +121 -0
  144. package/layer/app/oip-drugs/composables/useDirectusSources.ts +224 -0
  145. package/layer/app/oip-drugs/composables/useHeartBrandMatches.ts +112 -0
  146. package/layer/app/oip-drugs/composables/useHeartDetailSearches.ts +479 -0
  147. package/layer/app/oip-drugs/composables/useHeartIntlApprovals.ts +661 -0
  148. package/layer/app/oip-drugs/composables/useHeartLesIndication.ts +168 -0
  149. package/layer/app/oip-drugs/composables/useHeartMatchExplain.ts +231 -0
  150. package/layer/app/oip-drugs/composables/useHeartReports.ts +239 -0
  151. package/layer/app/oip-drugs/composables/useHeartSearchFields.ts +233 -0
  152. package/layer/app/oip-drugs/composables/useMergeByKey.ts +23 -0
  153. package/layer/app/oip-drugs/composables/useOipDrugsElastic.ts +621 -0
  154. package/layer/app/oip-drugs/composables/usePageEmpty.ts +58 -0
  155. package/layer/app/oip-drugs/composables/v-useSalesSource.ts +64 -0
  156. package/layer/app/oip-drugs/drugs.css +500 -0
  157. package/layer/app/oip-drugs/esIndices.ts +322 -0
  158. package/layer/app/oip-drugs/kinds.ts +264 -0
  159. package/layer/app/oip-drugs/locales/en.json +1571 -0
  160. package/layer/app/oip-drugs/locales/fr.json +1571 -0
  161. package/layer/app/oip-drugs/monographs/blincyto-has.vue +289 -0
  162. package/layer/app/oip-drugs/monographs/darzalex-has.vue +276 -0
  163. package/layer/app/oip-drugs/monographs/dupixent-has.vue +216 -0
  164. package/layer/app/oip-drugs/monographs/enhertu-has.vue +280 -0
  165. package/layer/app/oip-drugs/monographs/has-sein-2023.vue +1649 -0
  166. package/layer/app/oip-drugs/monographs/ibrance-has.vue +277 -0
  167. package/layer/app/oip-drugs/monographs/imfinzi-has.vue +293 -0
  168. package/layer/app/oip-drugs/monographs/keytruda-has.vue +334 -0
  169. package/layer/app/oip-drugs/monographs/kisqali-has.vue +201 -0
  170. package/layer/app/oip-drugs/monographs/opdivo-has.vue +231 -0
  171. package/layer/app/oip-drugs/monographs/ozempic-has.vue +186 -0
  172. package/layer/app/oip-drugs/monographs/tecentriq-has.vue +312 -0
  173. package/layer/app/oip-drugs/monographs/yescarta-has.vue +272 -0
  174. package/layer/app/oip-drugs/types/elastic.ts +113 -0
  175. package/layer/app/oip-drugs/types/es/agencies.ts +152 -0
  176. package/layer/app/oip-drugs/types/es/directory.ts +54 -0
  177. package/layer/app/oip-drugs/types/es/docByIndex.ts +151 -0
  178. package/layer/app/oip-drugs/types/es/openmedic.ts +67 -0
  179. package/layer/app/oip-drugs/types/es/outpatient.ts +71 -0
  180. package/layer/app/oip-drugs/types/es/portal.ts +130 -0
  181. package/layer/app/oip-drugs/types/es/retail.ts +107 -0
  182. package/layer/app/oip-drugs/types/es/statistics.ts +29 -0
  183. package/layer/app/oip-drugs/types/heart/CurrencyRate.ts +16 -0
  184. package/layer/app/oip-drugs/types/heart/ansm.ts +106 -0
  185. package/layer/app/oip-drugs/types/heart/tag.ts +29 -0
  186. package/layer/app/oip-drugs/utils/associationFields.ts +118 -0
  187. package/layer/app/oip-drugs/utils/contributions.ts +36 -0
  188. package/layer/app/oip-drugs/utils/countryMapping.ts +387 -0
  189. package/layer/app/oip-drugs/utils/esHighlight.ts +21 -0
  190. package/layer/app/oip-drugs/utils/exportSheets.ts +57 -0
  191. package/layer/app/oip-drugs/utils/heartIntlPrice.ts +228 -0
  192. package/layer/app/oip-drugs/utils/heartStyleAndFormat.ts +262 -0
  193. package/layer/app/oip-drugs/utils/heartStyleAnsm.ts +71 -0
  194. package/layer/app/oip-drugs/utils/latestDate.ts +31 -0
  195. package/layer/app/oip-drugs/utils/p-heartCardTags.ts +53 -0
  196. package/layer/app/oip-drugs/utils/priceExport.ts +269 -0
  197. package/layer/app/oip-drugs/utils/q-hasRatings.ts +43 -0
  198. package/layer/app/oip-drugs/utils/s-openCard.ts +20 -0
  199. package/layer/app/oip-drugs/utils/sourceUuids.ts +155 -0
  200. package/layer/app/oip-drugs/utils/styleAndFormat.ts +40 -0
  201. package/layer/app/oip-drugs/utils/v-salesSeries.ts +156 -0
  202. package/layer/app/oip-drugs/utils/v-scopeTags.ts +23 -0
  203. package/layer/app/oip-science/PORTING.md +93 -0
  204. package/layer/app/oip-science/assets/smartSelection.json +428 -0
  205. package/layer/app/oip-science/composables/useAuthorMatching.ts +342 -0
  206. package/layer/app/oip-science/composables/useCTCenter.ts +107 -0
  207. package/layer/app/oip-science/composables/useCTInvestigators.ts +107 -0
  208. package/layer/app/oip-science/composables/useEstablishmentCrossData.ts +139 -0
  209. package/layer/app/oip-science/composables/useEstablishmentMatching.ts +176 -0
  210. package/layer/app/oip-science/composables/useEuct.ts +418 -0
  211. package/layer/app/oip-science/composables/useEuctCenter.ts +107 -0
  212. package/layer/app/oip-science/composables/useEuctInvestigators.ts +107 -0
  213. package/layer/app/oip-science/composables/useGlobalClinicalTrials.ts +624 -0
  214. package/layer/app/oip-science/composables/useLinkedTrials.ts +83 -0
  215. package/layer/app/oip-science/composables/useOipElastic.ts +658 -0
  216. package/layer/app/oip-science/composables/useOipSearchExplain.ts +166 -0
  217. package/layer/app/oip-science/composables/usePubmed.ts +487 -0
  218. package/layer/app/oip-science/composables/useSearchFields.ts +153 -0
  219. package/layer/app/oip-science/indexConfig.json +794 -0
  220. package/layer/app/oip-science/locales/en.json +483 -0
  221. package/layer/app/oip-science/locales/fr.json +483 -0
  222. package/layer/app/oip-science/science.css +1182 -0
  223. package/layer/app/oip-science/utils/a-openCard.ts +23 -0
  224. package/layer/app/oip-science/utils/b-openCard.ts +35 -0
  225. package/layer/app/oip-science/utils/c-filterContext.ts +81 -0
  226. package/layer/app/oip-science/utils/f-types.ts +241 -0
  227. package/layer/app/oip-science/utils/frDiseaseTerms.ts +269 -0
  228. package/layer/app/oip-science/utils/matchMethod.ts +53 -0
  229. package/layer/app/oip-science/utils/sliderTabs.ts +13 -0
  230. package/layer/app/oip-science/utils/sources.ts +15 -0
  231. package/layer/app/oip-science/utils/styleAndFormat.ts +608 -0
  232. package/layer/app/oip-science/utils/toPresets.ts +7 -0
  233. package/layer/app/oip-science/utils/valueTable.ts +126 -0
  234. package/layer/app/plugins/oip-science-i18n.ts +17 -0
  235. package/layer/app/utils/oipFicheRoutes.ts +118 -0
  236. package/layer/app/utils/oipResources.ts +440 -0
  237. package/layer/nuxt.config.ts +22 -2
  238. package/layer/public/reports/blincyto-has.html +292 -0
  239. package/layer/public/reports/blincyto-has.pdf +0 -0
  240. package/layer/public/reports/darzalex-has.html +279 -0
  241. package/layer/public/reports/darzalex-has.pdf +0 -0
  242. package/layer/public/reports/dupixent-has.html +217 -0
  243. package/layer/public/reports/dupixent-has.pdf +0 -0
  244. package/layer/public/reports/enhertu-has.html +283 -0
  245. package/layer/public/reports/enhertu-has.pdf +0 -0
  246. package/layer/public/reports/has-sein-2023.html +1639 -0
  247. package/layer/public/reports/ibrance-has.html +280 -0
  248. package/layer/public/reports/ibrance-has.pdf +0 -0
  249. package/layer/public/reports/imfinzi-has.html +297 -0
  250. package/layer/public/reports/imfinzi-has.pdf +0 -0
  251. package/layer/public/reports/keytruda-has.html +337 -0
  252. package/layer/public/reports/keytruda-has.pdf +0 -0
  253. package/layer/public/reports/kisqali-has.html +202 -0
  254. package/layer/public/reports/kisqali-has.pdf +0 -0
  255. package/layer/public/reports/opdivo-has.html +232 -0
  256. package/layer/public/reports/opdivo-has.pdf +0 -0
  257. package/layer/public/reports/ozempic-has.html +188 -0
  258. package/layer/public/reports/ozempic-has.pdf +0 -0
  259. package/layer/public/reports/tecentriq-has.html +315 -0
  260. package/layer/public/reports/tecentriq-has.pdf +0 -0
  261. package/layer/public/reports/yescarta-has.html +275 -0
  262. package/layer/public/reports/yescarta-has.pdf +0 -0
  263. package/layer/server/api/oip/es.post.ts +99 -0
  264. package/layer/server/api/oip/pdf.get.ts +70 -0
  265. package/layer/server/api/oip/reports.get.ts +98 -0
  266. package/layer/server/api/oip/resource-types.get.ts +22 -0
  267. package/package.json +1 -1
@@ -0,0 +1,167 @@
1
+ <template>
2
+ <!-- Pas de largeur ici : la carte qui monte ce tableau la decide (elle le
3
+ met a fleur de ses bords). Une largeur en style inline ne se laissait
4
+ pas reprendre. -->
5
+ <div class="oip-drugs oip_list gap-8">
6
+ <p v-if="showCount" class="oip_filter_label sku-count">
7
+ {{ cisHits.length }}
8
+ {{ cisHits.length > 1 ? t('oipDrugs.heart.ansm.brandCard.specialties') : t('oipDrugs.heart.ansm.brandCard.specialty') }}
9
+ </p>
10
+ <RmTable :columns="table.columns" :rows="table.rows">
11
+ <template v-for="key in table.typeKeys.link" :key="key" #[key]="{ value }">
12
+ <a :href="rowHref(value?.[1])" class="link nowrap" @click="openRow($event, value?.[1])">
13
+ <OipDrugsHeartTextHighlight :text="value?.[0]" :queries="storeSearchBar" />
14
+ </a>
15
+ </template>
16
+ <template v-for="key in table.typeKeys.text" :key="key" #[key]="{ value }">
17
+ <p class="nowrap">{{ value }}</p>
18
+ </template>
19
+ <template v-for="key in table.typeKeys.tag" :key="key" #[key]="{ value }">
20
+ <RmTag :variant="heartGetStatusColor(value)">{{ value }}</RmTag>
21
+ </template>
22
+ </RmTable>
23
+ </div>
24
+ </template>
25
+
26
+ <script lang="ts" setup>
27
+ import type { OneAnsmResult } from "../../../../oip-drugs/types/heart/ansm";
28
+ import { heartGetStatusColor, heartStripBrandPrefix } from "../../../../oip-drugs/utils/heartStyleAnsm";
29
+ import { heartFormatDate } from "../../../../oip-drugs/utils/heartStyleAndFormat";
30
+ import { drugsBrandPath } from "../../../../oip-drugs/kinds";
31
+ import { valueTable } from "../../../../utils/valueTable";
32
+
33
+ const { t, locale } = useI18n();
34
+ const nav = useOipResourceNav();
35
+
36
+ const props = withDefaults(
37
+ defineProps<{
38
+ brandName: string;
39
+ cisHits: Array<{ _id: string; _source: OneAnsmResult }>;
40
+ storeSearchBar?: string[];
41
+ showCount?: boolean;
42
+ /**
43
+ * Colonnes facultatives affichees (ex-cardPrefs, cle « ansm ») : tout est
44
+ * masque par defaut, comme dans fr_drugs_app.
45
+ */
46
+ prefs?: Record<string, boolean>;
47
+ }>(),
48
+ { storeSearchBar: () => [], showCount: true, prefs: () => ({}) }
49
+ );
50
+
51
+ // Clic sur un CIS -> fiche marque, onglet ANSM, avec ce CIS preselectionne.
52
+ function rowPath(cisId: string) {
53
+ const path = drugsBrandPath(props.brandName);
54
+ return path ? `${path}?tab=ansm&cis=${encodeURIComponent(cisId ?? "")}` : "";
55
+ }
56
+ function rowHref(cisId: string) {
57
+ const path = rowPath(cisId);
58
+ return path ? nav.appHref("fr_drugs_app", path) : undefined;
59
+ }
60
+ function openRow(event: MouseEvent, cisId: string) {
61
+ if (event.metaKey || event.ctrlKey || event.shiftKey) return;
62
+ event.preventDefault();
63
+ const path = rowPath(cisId);
64
+ if (path) nav.openApp("fr_drugs_app", path);
65
+ }
66
+
67
+ /**
68
+ * Colonnes facultatives du tableau, dans l'ordre ou elles s'ajoutent.
69
+ *
70
+ * Elles vivent sur la specialite (CIS) et non sur la marque : les montrer
71
+ * toutes tiendrait sur huit colonnes, dont la moitie ne sert qu'a une
72
+ * question. La pastille « Personnaliser » de la barre de filtres les ouvre une
73
+ * par une, cf. useCardPrefOptions.
74
+ */
75
+ const OPTIONAL_COLUMNS: {
76
+ key: string;
77
+ head: () => string;
78
+ read: (source: OneAnsmResult) => string;
79
+ }[] = [
80
+ {
81
+ key: "form",
82
+ head: () => (locale.value === "en" ? "Pharmaceutical form" : "Forme pharmaceutique"),
83
+ read: (source) => source.pharmaceutical_form || "-",
84
+ },
85
+ {
86
+ key: "route",
87
+ head: () => (locale.value === "en" ? "Route" : "Voie d'administration"),
88
+ read: (source) => source.administration_mode || "-",
89
+ },
90
+ {
91
+ key: "procedure",
92
+ head: () => (locale.value === "en" ? "Procedure" : "Procédure"),
93
+ read: (source) => source.procedure_type || "-",
94
+ },
95
+ {
96
+ key: "generic",
97
+ head: () => (locale.value === "en" ? "Generic group" : "Groupe générique"),
98
+ read: (source) => source.generic_group_label || "-",
99
+ },
100
+ ];
101
+
102
+ const extraColumns = computed(() => {
103
+ const on = props.prefs;
104
+ return OPTIONAL_COLUMNS.filter((column) => on[column.key]);
105
+ });
106
+
107
+ const heads = computed(() => [
108
+ t("oipDrugs.heart.ansm.brandCard.denomination"),
109
+ t("oipDrugs.heart.ansm.brandCard.authorizationDate"),
110
+ t("oipDrugs.heart.ansm.brandCard.status"),
111
+ t("oipDrugs.heart.ansm.brandCard.commercialization"),
112
+ ...extraColumns.value.map((column) => column.head()),
113
+ ]);
114
+
115
+ // Les quatre colonnes de base gardent leurs gabarits ; les facultatives sont
116
+ // du texte, donc elles passent toutes par le meme.
117
+ const columnTypes = computed(() => [
118
+ "link",
119
+ "text",
120
+ "tag",
121
+ "tag",
122
+ ...extraColumns.value.map(() => "text"),
123
+ ]);
124
+
125
+ // Le tableau etait ecrit pour `arg-table` : des libelles de tete et des lignes
126
+ // `{ values: [...] }`. La conversion en colonnes de RmTable est mecanique,
127
+ // cf. `valueTable`. Les colonnes ne se trient pas ici : la carte affiche les
128
+ // specialites dans l'ordre ou la marque les porte.
129
+ const table = computed(() => {
130
+ const converted = valueTable(heads.value, tableContents.value, columnTypes.value, {
131
+ align: columnTypes.value.map(() => "left" as const),
132
+ });
133
+ return {
134
+ ...converted,
135
+ columns: converted.columns.map((column) => ({ ...column, sortable: false })),
136
+ };
137
+ });
138
+
139
+ const tableContents = computed(() =>
140
+ props.cisHits.map((h) => ({
141
+ values: [
142
+ [heartStripBrandPrefix(h._source.cis_label, props.brandName), h._id],
143
+ heartFormatDate((h._source as any).authorization_date),
144
+ h._source.amm_status,
145
+ h._source.commercialization_status,
146
+ ...extraColumns.value.map((column) => column.read(h._source)),
147
+ ],
148
+ }))
149
+ );
150
+ </script>
151
+
152
+ <style scoped>
153
+ .link {
154
+ color: var(--primary);
155
+ font-weight: 600;
156
+ text-decoration: none;
157
+ }
158
+ .link:hover {
159
+ text-decoration: underline;
160
+ }
161
+ .nowrap {
162
+ white-space: nowrap;
163
+ }
164
+ .sku-count {
165
+ padding: 16px 24px 0;
166
+ }
167
+ </style>
@@ -0,0 +1,373 @@
1
+ <!--
2
+ Carte d'un compte rendu de commission de l'Assemblee nationale.
3
+
4
+ Meme dessin que les cartes de l'annuaire (RmResultCard) : de quelle reunion
5
+ il s'agit (ordre du jour, date, legislature, session), qui y est cite (les
6
+ associations, chacune ouvrant sa fiche) et ce qui s'y est decide (les
7
+ amendements adoptes et rejetes). Le texte, lui, ne voyage pas avec la carte,
8
+ il fait jusqu'a 200 000 caracteres : la lecture s'ouvre dans la visionneuse
9
+ de la page, sur la copie HTML de Tekkare.
10
+
11
+ La meme carte sert a la liste et a la fiche d'une association ; la fiche
12
+ retire son propre nom de la liste des citees. Portage de
13
+ heart/associations/nationalAssemblyCard de fr_drugs_app ; montee seule par
14
+ le tiroir des projets, elle porte la classe `oip-drugs`.
15
+ -->
16
+ <template>
17
+ <RmResultCard class="oip-drugs" :lang="dateLang" :link="report[NATIONAL_ASSEMBLY_FIELDS.htmlUrl]">
18
+ <template #title>
19
+ <OipDrugsHeartTextHighlight :text="title" :queries="storeSearchBar" />
20
+ </template>
21
+ <template #subtitle>
22
+ <RmDate
23
+ v-if="report[NATIONAL_ASSEMBLY_FIELDS.sessionDate]"
24
+ :date="report[NATIONAL_ASSEMBLY_FIELDS.sessionDate]"
25
+ :lang="dateLang"
26
+ /><template v-if="report[NATIONAL_ASSEMBLY_FIELDS.sessionDate] && subtitle"> · </template>{{ subtitle }}
27
+ </template>
28
+
29
+ <template #actions>
30
+ <!-- Emplacement libre pour un appelant (la fiche projet y pose son
31
+ bouton « Commenter ») avant le bouton projet : vide partout ailleurs. -->
32
+ <slot name="hubr-actions" />
33
+ <component
34
+ :is="projectButton"
35
+ v-if="projectButton"
36
+ :resource-id="reportId || report[NATIONAL_ASSEMBLY_FIELDS.documentId]"
37
+ type="FrNationalAssemblySession"
38
+ :label="title"
39
+ compact
40
+ />
41
+ </template>
42
+
43
+ <template #meta>
44
+ <RmTag v-if="amendmentsTotal > 0" variant="gray">
45
+ {{ t("oipDrugs.heart.associations.nationalAssembly.card.amendments") }} :
46
+ {{ report[NATIONAL_ASSEMBLY_FIELDS.amendmentsAdopted] ?? 0 }}
47
+ {{ t("oipDrugs.heart.associations.nationalAssembly.card.adopted") }},
48
+ {{ report[NATIONAL_ASSEMBLY_FIELDS.amendmentsRejected] ?? 0 }}
49
+ {{ t("oipDrugs.heart.associations.nationalAssembly.card.rejected") }}
50
+ </RmTag>
51
+ <RmTag v-if="report[NATIONAL_ASSEMBLY_FIELDS.pharmaRelevance]" variant="violet">
52
+ {{ t("oipDrugs.heart.associations.nationalAssembly.fiche.relevance") }} :
53
+ {{ report[NATIONAL_ASSEMBLY_FIELDS.pharmaRelevance] }}
54
+ </RmTag>
55
+ <RmTag v-if="report[NATIONAL_ASSEMBLY_FIELDS.isPlfss]" variant="amber">
56
+ {{ t("oipDrugs.heart.associations.nationalAssembly.card.plfss") }}
57
+ </RmTag>
58
+ <RmTag v-for="tag in pharmaTags" :key="tag" variant="gray">{{ tag }}</RmTag>
59
+ </template>
60
+
61
+ <!-- Les associations citees, en tete de carte : chacune ouvre sa fiche. -->
62
+ <div v-if="associations.length > 0" class="oip_list gap-4">
63
+ <p class="oip_label">{{ t("oipDrugs.heart.associations.nationalAssembly.card.associations") }}</p>
64
+ <div class="oip_row gap-8 wrap">
65
+ <a
66
+ v-for="name in associations"
67
+ :key="name"
68
+ :href="nav.appHref('fr_drugs_app', drugsAssociationPath(name))"
69
+ class="na_association"
70
+ @click="openAssociation($event, name)"
71
+ >
72
+ <RmIcon name="UsersThree" :size="16" />
73
+ {{ name }}
74
+ </a>
75
+ </div>
76
+ </div>
77
+
78
+ <!-- Le resume de la fiche : pourquoi le compte rendu compte pour la
79
+ pharma. Le detail ligne a ligne s'ouvre dans le tiroir. -->
80
+ <p v-if="relevanceReason" class="na_summary">{{ relevanceReason }}</p>
81
+
82
+ <!-- Les passages du compte rendu ou le moteur a trouve les termes cherches,
83
+ surlignes comme dans le Playbook. Un clic ouvre la lecture, deja
84
+ positionnee sur les termes. -->
85
+ <div v-if="passages.length > 0" class="oip_list gap-4">
86
+ <p class="oip_label">{{ t("oipDrugs.heart.associations.nationalAssembly.card.passages") }}</p>
87
+ <button
88
+ v-for="(passage, pi) in passages"
89
+ :key="pi"
90
+ type="button"
91
+ class="na_passage"
92
+ :title="t('oipDrugs.heart.associations.nationalAssembly.card.readPassage')"
93
+ @click.stop.prevent="emit('read', report, hitTerms, passage.plain)"
94
+ >
95
+ <template v-if="passage.cutBefore">…</template><template v-for="(seg, si) in passage.segments" :key="si"><mark v-if="seg.hit">{{ seg.text }}</mark><template v-else>{{ seg.text }}</template></template><template v-if="passage.cutAfter">…</template>
96
+ </button>
97
+ </div>
98
+
99
+ <div class="oip_row gap-8 wrap">
100
+ <RmButton
101
+ v-if="report[NATIONAL_ASSEMBLY_FIELDS.tekkareUrl]"
102
+ variant="secondary"
103
+ prefix-icon="FileText"
104
+ @click="emit('read', report, hitTerms)"
105
+ >
106
+ {{ t("oipDrugs.heart.associations.nationalAssembly.card.read") }}
107
+ </RmButton>
108
+ <RmButton
109
+ v-if="hasFiche"
110
+ variant="secondary"
111
+ prefix-icon="Notebook"
112
+ @click="ficheOpen = true"
113
+ >
114
+ {{ t("oipDrugs.heart.associations.nationalAssembly.card.synthesis") }}
115
+ </RmButton>
116
+ <RmButton
117
+ v-if="report[NATIONAL_ASSEMBLY_FIELDS.htmlUrl]"
118
+ variant="tertiary"
119
+ ghost
120
+ prefix-icon="ArrowSquareOut"
121
+ @click="openLink(report[NATIONAL_ASSEMBLY_FIELDS.htmlUrl])"
122
+ >
123
+ {{ t("oipDrugs.heart.associations.nationalAssembly.card.seeOnAn") }}
124
+ </RmButton>
125
+ </div>
126
+
127
+ <!-- La synthese ligne a ligne (A1, A2...), teleportee hors de la carte. -->
128
+ <RmDrawer
129
+ v-if="hasFiche"
130
+ v-model="ficheOpen"
131
+ size="xl"
132
+ :label="t('oipDrugs.heart.associations.nationalAssembly.fiche.title')"
133
+ >
134
+ <template #header>
135
+ <div class="oip-drugs oip_list gap-4">
136
+ <p class="na_drawer_title">{{ t("oipDrugs.heart.associations.nationalAssembly.fiche.title") }}</p>
137
+ <p class="oip_label">{{ title }}</p>
138
+ </div>
139
+ </template>
140
+ <!-- Teleporte dans <body> : le tiroir reprend la classe `oip-drugs`. -->
141
+ <div class="oip-drugs">
142
+ <OipDrugsHeartAssociationsNationalAssemblyFiche
143
+ :fiche="report[NATIONAL_ASSEMBLY_FIELDS.fiche]"
144
+ :warnings="report[NATIONAL_ASSEMBLY_FIELDS.warnings] ?? []"
145
+ :readable="!!report[NATIONAL_ASSEMBLY_FIELDS.tekkareUrl]"
146
+ @read="readLine"
147
+ />
148
+ </div>
149
+ </RmDrawer>
150
+ </RmResultCard>
151
+ </template>
152
+
153
+ <script lang="ts" setup>
154
+ import { NATIONAL_ASSEMBLY_FIELDS } from "../../../../oip-drugs/utils/associationFields";
155
+ import { highlightSegments } from "../../../../oip-drugs/utils/esHighlight";
156
+ import { drugsAssociationPath } from "../../../../oip-drugs/kinds";
157
+
158
+ const props = withDefaults(
159
+ defineProps<{
160
+ /** Le `_source` d'un compte rendu, sans son texte. */
161
+ report: any;
162
+ /**
163
+ * L'`_id` ES du compte rendu, ce que le projet range. Il vaut
164
+ * `document_id` dans tout l'index, d'ou le repli quand l'appelant ne le
165
+ * passe pas.
166
+ */
167
+ reportId?: string;
168
+ /** Termes de la barre de recherche, pour le surlignage du titre. */
169
+ storeSearchBar?: string[];
170
+ /** Extraits surlignes du hit (balises de controle, cf. highlightSegments). */
171
+ highlight?: Record<string, string[]>;
172
+ /** L'association dont on lit la fiche : elle ne se cite pas elle-meme. */
173
+ currentAssociation?: string;
174
+ }>(),
175
+ { storeSearchBar: () => [], highlight: undefined, currentAssociation: "", reportId: "" },
176
+ );
177
+
178
+ /**
179
+ * `terms` : les mots que le moteur a surlignes dans ce compte rendu. La
180
+ * visionneuse cherche mot pour mot, sans l'analyse francaise : la saisie
181
+ * « cancer du sein » n'y trouverait pas « cancers » ni « sein » seuls.
182
+ * `anchor` : le passage clique, ou la lecture s'ouvre.
183
+ */
184
+ const emit = defineEmits<{ read: [report: any, terms?: string[], anchor?: string] }>();
185
+
186
+ const { t, locale } = useI18n();
187
+ const nav = useOipResourceNav();
188
+ const { projectButton } = useOipResourceHooks();
189
+
190
+ /** Le Ctrl/Cmd-clic garde le lien : il ouvre un onglet. */
191
+ function openAssociation(event: MouseEvent, name: string) {
192
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
193
+ event.preventDefault();
194
+ nav.openApp("fr_drugs_app", drugsAssociationPath(name));
195
+ }
196
+ const dateLang = computed(() => (locale.value === "en" ? "en" : "fr"));
197
+
198
+ /** L'ordre du jour tient le titre ; a defaut, un titre generique. */
199
+ const title = computed(
200
+ () =>
201
+ props.report[NATIONAL_ASSEMBLY_FIELDS.agenda] ||
202
+ t("oipDrugs.heart.associations.nationalAssembly.card.untitled"),
203
+ );
204
+
205
+ const subtitle = computed(() =>
206
+ [
207
+ props.report[NATIONAL_ASSEMBLY_FIELDS.legislature]
208
+ ? t("oipDrugs.heart.associations.nationalAssembly.card.legislature", {
209
+ n: props.report[NATIONAL_ASSEMBLY_FIELDS.legislature],
210
+ })
211
+ : null,
212
+ // La session arrive deja nommee (« session ordinaire de 2024-2025»).
213
+ props.report[NATIONAL_ASSEMBLY_FIELDS.parliamentarySession] || null,
214
+ props.report[NATIONAL_ASSEMBLY_FIELDS.documentNumber]
215
+ ? t("oipDrugs.heart.associations.nationalAssembly.card.number", {
216
+ n: props.report[NATIONAL_ASSEMBLY_FIELDS.documentNumber],
217
+ })
218
+ : null,
219
+ ]
220
+ .filter(Boolean)
221
+ .join(" · "),
222
+ );
223
+
224
+ const amendmentsTotal = computed(
225
+ () =>
226
+ Number(props.report[NATIONAL_ASSEMBLY_FIELDS.amendmentsAdopted] ?? 0) +
227
+ Number(props.report[NATIONAL_ASSEMBLY_FIELDS.amendmentsRejected] ?? 0),
228
+ );
229
+
230
+ /**
231
+ * Les associations citees : celles du texte (`association_label_regroup`) et
232
+ * celles de la fiche (`tags_associations`), memes libelles de l'annuaire. Une
233
+ * association presente des deux cotes n'apparait qu'une fois (casse ignoree).
234
+ */
235
+ const associations = computed<string[]>(() => {
236
+ const asList = (raw: unknown): string[] =>
237
+ Array.isArray(raw) ? raw : typeof raw === "string" && raw ? [raw] : [];
238
+ const mine = props.currentAssociation.toLowerCase();
239
+ const byKey = new Map<string, string>();
240
+ for (const name of [
241
+ ...asList(props.report[NATIONAL_ASSEMBLY_FIELDS.associations]),
242
+ ...asList(props.report[NATIONAL_ASSEMBLY_FIELDS.ficheAssociations]),
243
+ ]) {
244
+ const key = name?.trim().toLowerCase();
245
+ if (key && key !== mine && !byKey.has(key)) byKey.set(key, name.trim());
246
+ }
247
+ return [...byKey.values()].sort((a, b) => a.localeCompare(b, "fr"));
248
+ });
249
+
250
+ /**
251
+ * Passages du texte, decoupes en segments surlignes ou non. Le moteur coupe
252
+ * le plus souvent sur une phrase : les points de suspension ne marquent que
253
+ * les coupes en pleine phrase.
254
+ */
255
+ const passages = computed(() =>
256
+ (props.highlight?.[NATIONAL_ASSEMBLY_FIELDS.text] ?? []).map((fragment) => {
257
+ const text = fragment.trim();
258
+ const plain = text.replace(/[\u0001\u0002]/g, "");
259
+ return {
260
+ plain,
261
+ segments: highlightSegments(text),
262
+ cutBefore: !/^[A-ZÀ-Ý«"(]/.test(plain),
263
+ cutAfter: !/[.!?…»")]$/.test(plain),
264
+ };
265
+ }),
266
+ );
267
+
268
+ /** Les mots surlignes, une fois chacun (casse ignoree), pour la visionneuse. */
269
+ const hitTerms = computed(() => {
270
+ const seen = new Map<string, string>();
271
+ for (const passage of passages.value) {
272
+ for (const seg of passage.segments) {
273
+ const term = seg.text.trim();
274
+ if (seg.hit && term && !seen.has(term.toLowerCase())) seen.set(term.toLowerCase(), term);
275
+ }
276
+ }
277
+ return [...seen.values()];
278
+ });
279
+
280
+ const ficheOpen = ref(false);
281
+
282
+ /** Une ligne de la synthese ouvre son passage : le tiroir laisse la place a la lecture. */
283
+ function readLine(anchor: string) {
284
+ ficheOpen.value = false;
285
+ emit("read", props.report, [anchor], anchor);
286
+ }
287
+
288
+ const hasFiche = computed(
289
+ () => !!(props.report[NATIONAL_ASSEMBLY_FIELDS.hasLlm] && props.report[NATIONAL_ASSEMBLY_FIELDS.fiche]),
290
+ );
291
+
292
+ const pharmaTags = computed<string[]>(() => props.report[NATIONAL_ASSEMBLY_FIELDS.pharmaTags] ?? []);
293
+
294
+
295
+ const relevanceReason = computed<string>(
296
+ () => props.report[NATIONAL_ASSEMBLY_FIELDS.fiche]?.pertinence_pharma?.raison ?? "",
297
+ );
298
+
299
+ function openLink(url: string) {
300
+ if (url) window.open(url, "_blank");
301
+ }
302
+ </script>
303
+
304
+ <style scoped>
305
+ /* Les associations citees : des pastilles cliquables teintees de la couleur
306
+ principale, l'information que la carte doit d'abord montrer. */
307
+ .na_association {
308
+ display: inline-flex;
309
+ align-items: center;
310
+ gap: 6px;
311
+ padding: 4px 12px;
312
+ border: 1px solid color-mix(in srgb, var(--primary) 35%, transparent);
313
+ border-radius: 999px;
314
+ background: color-mix(in srgb, var(--primary) 10%, transparent);
315
+ color: var(--primary);
316
+ font-size: 13px;
317
+ font-weight: 600;
318
+ text-decoration: none;
319
+ }
320
+
321
+ .na_association:hover {
322
+ background: color-mix(in srgb, var(--primary) 18%, transparent);
323
+ border-color: var(--primary);
324
+ }
325
+
326
+ .na_association:focus-visible {
327
+ outline: 2px solid var(--primary);
328
+ outline-offset: 2px;
329
+ }
330
+
331
+ .na_summary {
332
+ margin: 0;
333
+ padding: 8px 0;
334
+ color: var(--text-primary);
335
+ font-size: 13px;
336
+ line-height: 1.55;
337
+ }
338
+
339
+ .na_drawer_title {
340
+ margin: 0;
341
+ color: var(--text-primary);
342
+ font-size: 16px;
343
+ font-weight: 600;
344
+ }
345
+
346
+ /* Un passage cite : bande grise, filet a gauche, comme un extrait du Playbook. */
347
+ .na_passage {
348
+ display: block;
349
+ width: 100%;
350
+ padding: 8px 12px;
351
+ border: none;
352
+ border-left: 3px solid var(--border-default);
353
+ border-radius: 0 6px 6px 0;
354
+ background: var(--lightest);
355
+ color: var(--text-primary);
356
+ font-family: inherit;
357
+ font-size: 13px;
358
+ line-height: 1.55;
359
+ text-align: left;
360
+ cursor: pointer;
361
+ }
362
+
363
+ .na_passage:hover {
364
+ border-left-color: var(--primary);
365
+ }
366
+
367
+ .na_passage mark {
368
+ background: color-mix(in srgb, var(--color-primary) 18%, transparent);
369
+ color: inherit;
370
+ border-radius: 3px;
371
+ padding: 0 2px;
372
+ }
373
+ </style>