@tekkare/romulus 0.1.242 → 0.1.244
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.
- package/dist/module.json +1 -1
- package/layer/app/components/AppUpdateToast.vue +157 -0
- package/layer/app/components/OipShell.vue +2 -0
- package/layer/app/components/auth/SplitLayout.vue +261 -0
- package/layer/app/components/layout/alertBrandSync.vue +143 -0
- package/layer/app/components/layout/firstVisitVideo.vue +165 -0
- package/layer/app/components/layout/tool/adminTemplates.vue +261 -0
- package/layer/app/components/layout/tool/alerts.vue +969 -0
- package/layer/app/components/layout/tool/export.vue +590 -0
- package/layer/app/components/layout/tool/views.vue +933 -0
- package/layer/app/components/layout/viewEmptyState.vue +278 -0
- package/layer/app/components/layout/viewPill.vue +550 -0
- package/layer/app/components/panels/OipPanelProjects.vue +94 -0
- package/layer/app/composables/useAdminAccess.ts +86 -0
- package/layer/app/composables/useAlertBrandSync.ts +85 -0
- package/layer/app/composables/useAlertSource.ts +210 -0
- package/layer/app/composables/useAlerts.ts +345 -0
- package/layer/app/composables/useExportSource.ts +236 -0
- package/layer/app/composables/useHubrEmbedded.ts +13 -0
- package/layer/app/composables/usePermalink.ts +108 -0
- package/layer/app/composables/useSavedExports.ts +286 -0
- package/layer/app/composables/useViewCardActions.ts +500 -0
- package/layer/app/composables/useViewEditing.ts +11 -0
- package/layer/app/composables/useViewTemplates.ts +369 -0
- package/layer/app/composables/useViews.ts +574 -0
- package/layer/app/oip-defaults/alerts.ts +34 -0
- package/layer/app/oip-defaults/api.ts +18 -0
- package/layer/app/oip-defaults/export.ts +23 -0
- package/layer/app/oip-defaults/ui.ts +21 -0
- package/layer/app/oip-defaults/views.ts +59 -0
- package/layer/app/utils/alertFieldLabels.ts +191 -0
- package/layer/app/utils/countries.ts +30 -0
- package/layer/app/utils/exportPage.ts +418 -0
- package/layer/app/utils/headerTabs.ts +15 -0
- package/layer/app/utils/hybridRows.ts +22 -0
- package/layer/app/utils/oipScopeStore.ts +112 -0
- package/layer/app/utils/oipScopes.ts +376 -0
- package/layer/app/utils/postLoginRedirect.ts +58 -0
- package/layer/app/utils/valueTable.ts +126 -0
- package/layer/app/utils/viewPages.ts +30 -0
- package/layer/app/utils/viewTemplateCriteria.ts +215 -0
- package/layer/app/utils/viewTemplates.ts +116 -0
- package/layer/nuxt.config.ts +9 -0
- package/layer/server/api/oip/notes.get.ts +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* viewTemplateCriteria - les criteres d'un template, tels qu'ils sont ranges.
|
|
3
|
+
*
|
|
4
|
+
* Un template publie par Tekkare est une vue enregistree, et une vue
|
|
5
|
+
* enregistree stocke des LIBELLES : « Insuffisant », « Oncologie: true »,
|
|
6
|
+
* « 30 derniers jours ». Ces libelles sont ecrits dans la langue de qui a
|
|
7
|
+
* pose les filtres. Range tel quel, un template ecrit en francais ouvre un
|
|
8
|
+
* ecran vide chez un lecteur anglais.
|
|
9
|
+
*
|
|
10
|
+
* On range donc la CLE plutot que le libelle a chaque fois qu'elle existe.
|
|
11
|
+
* Quatre mecanismes du catalogue en dur (`~/utils/viewTemplates`) traduisent
|
|
12
|
+
* leur valeur, et tous les quatre la tirent de l'i18n :
|
|
13
|
+
*
|
|
14
|
+
* | mecanisme | ce qui est traduit | ce qu'on range |
|
|
15
|
+
* |----------------------|-----------------------------|----------------|
|
|
16
|
+
* | periode relative | « 30 derniers jours » | `last30` |
|
|
17
|
+
* | filtre booleen | « Oncologie: true » | `oncology` |
|
|
18
|
+
* | onglet des avis HAS | « Indications » | `indic` |
|
|
19
|
+
* | page Prix | le NOM du filtre | sa cle i18n |
|
|
20
|
+
*
|
|
21
|
+
* Le reste des valeurs est neutre : « Liste en sus », « Commercialisée »,
|
|
22
|
+
* « Brand », les marques, les codes ATC, les laboratoires. Elles viennent des
|
|
23
|
+
* index, sortis de sources francaises, et un lecteur anglais les voit deja
|
|
24
|
+
* telles quelles aujourd'hui. Rien a faire pour elles.
|
|
25
|
+
*
|
|
26
|
+
* Reste une poignee de filtres dont les valeurs existent vraiment en deux
|
|
27
|
+
* orthographes, parce que l'index porte un champ `_fr` et un champ `_en`
|
|
28
|
+
* (cf. `LANGUAGE_BOUND`). Leur paire ne vit ni dans l'i18n ni dans le code :
|
|
29
|
+
* la resoudre demande une requete au cluster. La v1 ne la resout pas, elle
|
|
30
|
+
* range la valeur telle quelle avec la langue d'ecriture, et le dialogue de
|
|
31
|
+
* publication previent. Le jour ou le resolveur arrive, il remplit le cote
|
|
32
|
+
* manquant sans toucher une seule ligne deja enregistree : c'est tout
|
|
33
|
+
* l'interet de ranger une forme, et pas une chaine.
|
|
34
|
+
*/
|
|
35
|
+
import {
|
|
36
|
+
HAS_TABS,
|
|
37
|
+
LANGUAGE_BOUND,
|
|
38
|
+
PERIOD_FILTER,
|
|
39
|
+
PERIOD_SHORTCUTS,
|
|
40
|
+
TRANSLATED_FILTER_NAMES,
|
|
41
|
+
} from "#oip-app/views";
|
|
42
|
+
import { VIEW_PREFS_FILTER } from "../composables/useViews";
|
|
43
|
+
|
|
44
|
+
export { LANGUAGE_BOUND };
|
|
45
|
+
|
|
46
|
+
/** Langue d'ecriture d'un template. */
|
|
47
|
+
export type TemplateLang = "fr" | "en";
|
|
48
|
+
|
|
49
|
+
export interface TemplateCriteriaContext {
|
|
50
|
+
lang: TemplateLang;
|
|
51
|
+
t: (key: string) => string;
|
|
52
|
+
te: (key: string) => boolean;
|
|
53
|
+
/** Prefixe i18n des libelles de filtres de la page, sans le point final. */
|
|
54
|
+
namespace: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Un critere range. `kind` dit comment le relire :
|
|
59
|
+
* - `values` : les valeurs telles quelles, eventuellement dans les deux
|
|
60
|
+
* langues quand la paire est connue ;
|
|
61
|
+
* - `check` / `tab` : une cle i18n, dont on refait le libelle a la lecture ;
|
|
62
|
+
* - `period` : un raccourci de periode, qui reste glissant.
|
|
63
|
+
*/
|
|
64
|
+
export interface StoredCriterion {
|
|
65
|
+
filter: string;
|
|
66
|
+
/** Cle i18n du NOM du filtre, quand c'est lui qui est traduit (page Prix). */
|
|
67
|
+
filterKey?: string;
|
|
68
|
+
kind: "values" | "check" | "tab" | "period";
|
|
69
|
+
/** `kind: "values"` sans paire connue. */
|
|
70
|
+
values?: string[];
|
|
71
|
+
/** `kind: "values"` avec sa paire, quand elle est connue. */
|
|
72
|
+
localized?: Record<TemplateLang, string[]>;
|
|
73
|
+
/** `kind` autre que `values` : la cle a relire. */
|
|
74
|
+
key?: string;
|
|
75
|
+
/** Langue d'ecriture, pour les valeurs qu'on ne sait pas encore traduire. */
|
|
76
|
+
lang?: TemplateLang;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Filtres et libelles propres a l'app (periode, onglets, filtres traduits,
|
|
80
|
+
// filtres lies a la langue) : contrat #oip-app/views.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
/** Les valeurs d'un critere, que la periode les garde en chaine ou non. */
|
|
84
|
+
function valuesOf(item: any): string[] {
|
|
85
|
+
if (Array.isArray(item?.values)) return item.values.map(String);
|
|
86
|
+
return item?.values !== undefined && item?.values !== null ? [String(item.values)] : [];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** La cle dont la traduction vaut `label`, parmi `keys`. */
|
|
90
|
+
function keyOf(
|
|
91
|
+
keys: string[],
|
|
92
|
+
prefix: string,
|
|
93
|
+
label: string,
|
|
94
|
+
ctx: TemplateCriteriaContext,
|
|
95
|
+
): string | null {
|
|
96
|
+
return (
|
|
97
|
+
keys.find((key) => ctx.te(`${prefix}${key}`) && ctx.t(`${prefix}${key}`) === label) ?? null
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Range les criteres d'un ecran, dans la langue de qui les a poses.
|
|
103
|
+
*
|
|
104
|
+
* Ce qui n'est reconnu par aucun des quatre mecanismes part en valeurs
|
|
105
|
+
* telles quelles : c'est le cas de la grande majorite, et c'est le bon
|
|
106
|
+
* defaut — une valeur neutre rangee comme neutre se relit a l'identique.
|
|
107
|
+
*/
|
|
108
|
+
export function encodeCriteria(
|
|
109
|
+
criteria: any[],
|
|
110
|
+
ctx: TemplateCriteriaContext,
|
|
111
|
+
): StoredCriterion[] {
|
|
112
|
+
return (criteria ?? []).map((item) => {
|
|
113
|
+
const filter = String(item?.filter ?? "");
|
|
114
|
+
const values = valuesOf(item);
|
|
115
|
+
|
|
116
|
+
// Les preferences de cartes ne sont pas un filtre : elles voyagent dans
|
|
117
|
+
// les criteres faute d'un autre champ libre, et ne se traduisent pas.
|
|
118
|
+
if (filter === VIEW_PREFS_FILTER) {
|
|
119
|
+
return { filter, kind: "values" as const, values };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Le NOM du filtre est traduit : on range sa cle, pas son libelle.
|
|
123
|
+
const filterKey = TRANSLATED_FILTER_NAMES.find(
|
|
124
|
+
(key) => ctx.te(key) && ctx.t(key) === filter,
|
|
125
|
+
);
|
|
126
|
+
if (filterKey) {
|
|
127
|
+
return { filter, filterKey, kind: "values" as const, values, lang: ctx.lang };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Periode relative : le raccourci reste glissant, les deux dates non.
|
|
131
|
+
if (filter === PERIOD_FILTER && values.length === 1) {
|
|
132
|
+
const key = keyOf(PERIOD_SHORTCUTS, "heart.period.", values[0]!, ctx);
|
|
133
|
+
if (key) return { filter, kind: "period" as const, key };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Filtre booleen : la vue stocke « <libelle du filtre>: true ».
|
|
137
|
+
if (values.length === 1 && values[0]!.endsWith(": true")) {
|
|
138
|
+
const label = values[0]!.slice(0, -": true".length);
|
|
139
|
+
const key = `${ctx.namespace}.${filter}`;
|
|
140
|
+
if (ctx.te(key) && ctx.t(key) === label) {
|
|
141
|
+
return { filter, kind: "check" as const, key };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Onglet des avis HAS.
|
|
146
|
+
if (filter === "Type" && values.length === 1) {
|
|
147
|
+
const key = keyOf(HAS_TABS, "heart.tabs.", values[0]!, ctx);
|
|
148
|
+
if (key) return { filter, kind: "tab" as const, key };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
filter,
|
|
153
|
+
kind: "values" as const,
|
|
154
|
+
values,
|
|
155
|
+
...(LANGUAGE_BOUND.has(filter) && { lang: ctx.lang }),
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Relit des criteres ranges, dans la langue de l'ecran.
|
|
162
|
+
*
|
|
163
|
+
* La periode rend une CHAINE et non un tableau : c'est ce que `rangePicker`
|
|
164
|
+
* attend, et c'est ce qui la garde relative.
|
|
165
|
+
*/
|
|
166
|
+
export function decodeCriteria(
|
|
167
|
+
stored: StoredCriterion[],
|
|
168
|
+
ctx: TemplateCriteriaContext,
|
|
169
|
+
): Array<{ filter: string; values: string[] | string }> {
|
|
170
|
+
return (stored ?? []).map((item) => {
|
|
171
|
+
const filter = item.filterKey && ctx.te(item.filterKey)
|
|
172
|
+
? ctx.t(item.filterKey)
|
|
173
|
+
: item.filter;
|
|
174
|
+
|
|
175
|
+
switch (item.kind) {
|
|
176
|
+
case "period":
|
|
177
|
+
return {
|
|
178
|
+
filter,
|
|
179
|
+
values: item.key && ctx.te(`heart.period.${item.key}`)
|
|
180
|
+
? ctx.t(`heart.period.${item.key}`)
|
|
181
|
+
: (item.values?.[0] ?? ""),
|
|
182
|
+
};
|
|
183
|
+
case "check":
|
|
184
|
+
return {
|
|
185
|
+
filter,
|
|
186
|
+
values: [`${item.key && ctx.te(item.key) ? ctx.t(item.key) : filter}: true`],
|
|
187
|
+
};
|
|
188
|
+
case "tab":
|
|
189
|
+
return {
|
|
190
|
+
filter,
|
|
191
|
+
values: [
|
|
192
|
+
item.key && ctx.te(`heart.tabs.${item.key}`)
|
|
193
|
+
? ctx.t(`heart.tabs.${item.key}`)
|
|
194
|
+
: (item.values?.[0] ?? ""),
|
|
195
|
+
],
|
|
196
|
+
};
|
|
197
|
+
default:
|
|
198
|
+
return { filter, values: item.localized?.[ctx.lang] ?? item.values ?? [] };
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Les filtres qui resteront dans la langue d'ecriture, parmi des criteres
|
|
205
|
+
* ranges. Ce que le dialogue de publication annonce avant d'enregistrer.
|
|
206
|
+
*/
|
|
207
|
+
export function languageBoundFilters(stored: StoredCriterion[]): string[] {
|
|
208
|
+
return [
|
|
209
|
+
...new Set(
|
|
210
|
+
(stored ?? [])
|
|
211
|
+
.filter((item) => item.kind === "values" && !item.localized && LANGUAGE_BOUND.has(item.filter))
|
|
212
|
+
.map((item) => item.filter),
|
|
213
|
+
),
|
|
214
|
+
];
|
|
215
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* viewTemplates - les vues prêtes a l'emploi fournies par Tekkare.
|
|
3
|
+
*
|
|
4
|
+
* Un template est une vue que personne n'a enregistree : un jeu de criteres
|
|
5
|
+
* ecrit ici, applique comme une vue temporaire (sans identifiant, cf.
|
|
6
|
+
* `isTemporaryView`). L'utilisateur le demarre, le retouche, et l'enregistre
|
|
7
|
+
* dans ses vues s'il veut le garder. Rien ne part en base tant qu'il ne le
|
|
8
|
+
* demande pas.
|
|
9
|
+
*
|
|
10
|
+
* Les criteres se construisent avec la langue de l'ecran, jamais en dur :
|
|
11
|
+
* - les filtres tapent `status_fr` ou `status_en` selon la locale, et la vue
|
|
12
|
+
* stocke le libelle affiche (« Insuffisant » / « Insufficient ») ;
|
|
13
|
+
* - un filtre booleen (`CheckFilter`) stocke `"<libelle du filtre>: true"`,
|
|
14
|
+
* donc « Oncologie: true » en francais et « Oncology: true » en anglais ;
|
|
15
|
+
* - sur la page Prix, c'est le NOM du filtre qui est traduit.
|
|
16
|
+
* D'ou le contexte `{ lang, t }` passe a chaque `criteria()`.
|
|
17
|
+
*
|
|
18
|
+
* Les valeurs sont celles des index : elles ont ete relevees par agregation,
|
|
19
|
+
* pas devinees (cf. la page projet du vault). Une valeur inventee ne filtre
|
|
20
|
+
* rien et le template ouvre un ecran vide.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { VIEW_TEMPLATES } from "#oip-app/views";
|
|
24
|
+
|
|
25
|
+
export type ViewTemplateTone = "primary" | "success" | "warning" | "danger" | "info";
|
|
26
|
+
|
|
27
|
+
export interface ViewTemplateContext {
|
|
28
|
+
lang: "fr" | "en";
|
|
29
|
+
t: (key: string) => string;
|
|
30
|
+
/**
|
|
31
|
+
* Une cle i18n existe-t-elle. Les templates en dur n'en ont pas besoin
|
|
32
|
+
* (leurs cles sont ecrites ici, donc sures) ; ceux publies depuis l'app,
|
|
33
|
+
* si : ils relisent une cle rangee en base, qu'un renommage a pu perimer.
|
|
34
|
+
*/
|
|
35
|
+
te: (key: string) => boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Un critere de vue. `values` est un tableau, sauf pour la periode. */
|
|
39
|
+
export interface ViewTemplateCriterion {
|
|
40
|
+
filter: string;
|
|
41
|
+
values: string[] | string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ViewTemplate {
|
|
45
|
+
/** Identifiant stable : il sert de cle de carte, jamais d'id de vue. */
|
|
46
|
+
id: string;
|
|
47
|
+
/** Chemin de la page, sans prefixe de langue ni barre finale. */
|
|
48
|
+
page: string;
|
|
49
|
+
/** Icone Phosphor de la pastille. */
|
|
50
|
+
icon: string;
|
|
51
|
+
tone?: ViewTemplateTone;
|
|
52
|
+
title: Record<"fr" | "en", string>;
|
|
53
|
+
description: Record<"fr" | "en", string>;
|
|
54
|
+
criteria: (ctx: ViewTemplateContext) => ViewTemplateCriterion[];
|
|
55
|
+
/**
|
|
56
|
+
* Le template se demarre par un lien profond plutot qu'en posant les
|
|
57
|
+
* criteres a l'ecran.
|
|
58
|
+
*
|
|
59
|
+
* Les pages du portail « Medicaments France » ne portent pas des filtres
|
|
60
|
+
* mais une selection de produits, et personne ne la resout dans la page :
|
|
61
|
+
* c'est le middleware `03.scope-from-query` qui expanse un code ATC en
|
|
62
|
+
* liste de marques, remplit les listes par source (`medicamBrandList`,
|
|
63
|
+
* `susBrandList`...) et pose la vue temporaire. Un template de panier est
|
|
64
|
+
* donc l'URL qui le declenche, ce qui evite d'y figer une liste de marques
|
|
65
|
+
* qui vieillirait a chaque nouvelle AMM.
|
|
66
|
+
*/
|
|
67
|
+
deepLink?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Publie pour l'espace du lecteur nommement, et non pour tout le monde :
|
|
70
|
+
* la carte le dit (« Créé pour vous »).
|
|
71
|
+
*/
|
|
72
|
+
forYou?: boolean;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Parametre d'URL qui dit de quel template vient le perimetre pose. Le
|
|
77
|
+
* middleware du lien profond le recopie sur la vue temporaire, la pastille de
|
|
78
|
+
* la barre nomme alors le template plutot que de dire « Vue temporaire », et la
|
|
79
|
+
* navigation le garde avec les autres cles de perimetre (cf. useDrugsNav).
|
|
80
|
+
*/
|
|
81
|
+
export const VIEW_TEMPLATE_QUERY_PARAM = "template";
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Critere de vue vers parametre d'URL (template en lien profond) et
|
|
85
|
+
* parametres a nettoyer avant d'en poser de nouveaux : metier de l'app, cf.
|
|
86
|
+
* contrat #oip-app/views.
|
|
87
|
+
*/
|
|
88
|
+
export { VIEW_TEMPLATE_QUERY_KEYS, VIEW_TEMPLATE_QUERY_RESET } from "#oip-app/views";
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Chemin comparable : sans prefixe de langue (`/en/price`), sans barre finale.
|
|
92
|
+
* Les pages declarent `route.path`, qui porte les deux.
|
|
93
|
+
*/
|
|
94
|
+
export function normalizePage(path: string): string {
|
|
95
|
+
return String(path ?? "")
|
|
96
|
+
.replace(/^\/(?:en|fr)(?=\/|$)/, "")
|
|
97
|
+
.replace(/\/$/, "");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Un template du catalogue par identifiant, quelle que soit sa page : la
|
|
102
|
+
* pastille nomme le template dont vient la vue, et la vue suit le lecteur
|
|
103
|
+
* d'une page du portail a l'autre alors que l'identifiant porte la page de
|
|
104
|
+
* depart.
|
|
105
|
+
*/
|
|
106
|
+
export function viewTemplateById(id: string): ViewTemplate | undefined {
|
|
107
|
+
return VIEW_TEMPLATES.find((template) => template.id === id);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Les templates d'une page, dans l'ordre du catalogue. */
|
|
111
|
+
export function viewTemplatesFor(page: string): ViewTemplate[] {
|
|
112
|
+
const wanted = normalizePage(page);
|
|
113
|
+
return VIEW_TEMPLATES.filter(
|
|
114
|
+
(template) => template.page === wanted,
|
|
115
|
+
);
|
|
116
|
+
}
|
package/layer/nuxt.config.ts
CHANGED
|
@@ -8,7 +8,16 @@
|
|
|
8
8
|
// pas dans `modules` : l'app les enregistre deja avec ses options (romulus
|
|
9
9
|
// sans baseStyles, ses locales), et un second enregistrement par le layer
|
|
10
10
|
// les reinstallerait avec les options par defaut.
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
11
13
|
export default defineNuxtConfig({
|
|
14
|
+
// Contrat avec l'app pour ce qui lui est propre (client API, bandeau,
|
|
15
|
+
// tables metier des vues et des alertes). Par defaut, les valeurs neutres
|
|
16
|
+
// du layer ; une app pointe `#oip-app` vers son dossier `app/oip` dans son
|
|
17
|
+
// propre nuxt.config, et sa valeur l'emporte.
|
|
18
|
+
alias: {
|
|
19
|
+
"#oip-app": fileURLToPath(new URL("./app/oip-defaults", import.meta.url)),
|
|
20
|
+
},
|
|
12
21
|
future: {
|
|
13
22
|
compatibilityVersion: 4,
|
|
14
23
|
},
|
|
@@ -146,7 +146,7 @@ export default defineEventHandler(async (event): Promise<ApiNote[]> => {
|
|
|
146
146
|
// tout le portail. Sans sujet de cette app, la note n'est pas la sienne.
|
|
147
147
|
const paths = (row.linked_subjects ?? [])
|
|
148
148
|
.map((link) => link.OipSubject_subject_id)
|
|
149
|
-
.filter((subject) => appUrls.includes(subject?.app?.prod_url))
|
|
149
|
+
.filter((subject) => appUrls.includes(subject?.app?.prod_url ?? ""))
|
|
150
150
|
.map((subject) => (subject!.relative_path ?? "").trim())
|
|
151
151
|
.filter(Boolean);
|
|
152
152
|
const sources = (row.linked_sources ?? [])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekkare/romulus",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.244",
|
|
4
4
|
"description": "Romulus Design System - Nuxt module by Tekkare",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
"types": "./dist/runtime/utils/*.d.ts",
|
|
18
18
|
"import": "./dist/runtime/utils/*.js"
|
|
19
19
|
},
|
|
20
|
-
"./layer": "./layer/nuxt.config.ts"
|
|
20
|
+
"./layer": "./layer/nuxt.config.ts",
|
|
21
|
+
"./layer-utils/*": "./layer/app/utils/*.ts",
|
|
22
|
+
"./layer-composables/*": "./layer/app/composables/*.ts"
|
|
21
23
|
},
|
|
22
24
|
"main": "./dist/module.cjs",
|
|
23
25
|
"module": "./dist/module.mjs",
|