@tekkare/romulus 0.1.107 → 0.1.109
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
CHANGED
|
@@ -75,6 +75,22 @@ const FR = {
|
|
|
75
75
|
"La vue a changé sans que la requête de l'alerte suive. Ouvrez la page surveillée pour la réarmer.",
|
|
76
76
|
failing: 'Le dernier passage a été refusé, la référence précédente est conservée.',
|
|
77
77
|
},
|
|
78
|
+
refusal: {
|
|
79
|
+
too_broad: (n: string, max: string) =>
|
|
80
|
+
`Cette vue est trop large pour être surveillée : ${n} documents, alors qu’une alerte en suit ${max} au maximum. Resserrez le périmètre de la vue, sur une marque ou une molécule par exemple.`,
|
|
81
|
+
collapse: (n: string) =>
|
|
82
|
+
`Les résultats se sont effondrés (${n} documents restants) : c’est un incident sur les données, pas une nouvelle. Rien n’a été signalé, l’alerte reprendra au prochain passage sain.`,
|
|
83
|
+
growth: (n: string) =>
|
|
84
|
+
`Les résultats ont brutalement augmenté (${n} documents) : c’est un incident sur les données, pas une nouvelle. Rien n’a été signalé.`,
|
|
85
|
+
id_overlap: (n: string) =>
|
|
86
|
+
`Les documents suivis ne sont plus reconnus (${n} retrouvés) : la source a probablement été réindexée. Rien n’a été signalé pour éviter d’annoncer tout le périmètre comme nouveau.`,
|
|
87
|
+
field_sweep: (n: string) =>
|
|
88
|
+
`Un même champ a changé sur ${n} documents d’un coup : c’est une modification de la source, pas une actualité. Rien n’a été signalé.`,
|
|
89
|
+
shard_failure:
|
|
90
|
+
'La source n’a répondu que partiellement. Rien n’a été signalé : un résultat incomplet se lit comme une disparition générale.',
|
|
91
|
+
es_error:
|
|
92
|
+
'La source n’a pas répondu. Rien n’a été signalé, l’alerte réessaiera au prochain passage.',
|
|
93
|
+
},
|
|
78
94
|
reseeded: 'La vue a changé, l’alerte est repartie d’une nouvelle référence le',
|
|
79
95
|
}
|
|
80
96
|
|
|
@@ -112,19 +128,63 @@ const EN = {
|
|
|
112
128
|
"The view changed and the alert's query did not follow. Open the watched page to re-arm it.",
|
|
113
129
|
failing: 'The last run was refused; the previous baseline is kept.',
|
|
114
130
|
},
|
|
131
|
+
refusal: {
|
|
132
|
+
too_broad: (n: string, max: string) =>
|
|
133
|
+
`This view is too wide to watch: ${n} documents, where an alert tracks at most ${max}. Narrow the view, to one brand or molecule for instance.`,
|
|
134
|
+
collapse: (n: string) =>
|
|
135
|
+
`Results collapsed (${n} documents left): that is a data incident, not news. Nothing was reported; the alert resumes on the next healthy run.`,
|
|
136
|
+
growth: (n: string) =>
|
|
137
|
+
`Results grew abruptly (${n} documents): that is a data incident, not news. Nothing was reported.`,
|
|
138
|
+
id_overlap: (n: string) =>
|
|
139
|
+
`The tracked documents are no longer recognised (${n} found again): the source was probably reindexed. Nothing was reported, to avoid announcing the whole scope as new.`,
|
|
140
|
+
field_sweep: (n: string) =>
|
|
141
|
+
`One field changed on ${n} documents at once: that is a change to the source, not news. Nothing was reported.`,
|
|
142
|
+
shard_failure:
|
|
143
|
+
'The source only answered partially. Nothing was reported: an incomplete result reads like a mass disappearance.',
|
|
144
|
+
es_error: 'The source did not answer. Nothing was reported; the alert will retry.',
|
|
145
|
+
},
|
|
115
146
|
reseeded: 'The view changed, the alert restarted from a new baseline on',
|
|
116
147
|
}
|
|
117
148
|
|
|
118
149
|
const T = computed(() => (props.lang === 'en' ? EN : FR))
|
|
119
150
|
|
|
151
|
+
/** Nombres ecrits comme on les lit : 19 751, pas 19751. */
|
|
152
|
+
const number = (value: number) =>
|
|
153
|
+
new Intl.NumberFormat(props.lang === 'en' ? 'en-GB' : 'fr-FR').format(value)
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Pourquoi le dernier passage a ete refuse, dit en clair.
|
|
157
|
+
*
|
|
158
|
+
* Le moteur garde son message brut (il nomme des shards et des index) ; la
|
|
159
|
+
* carte, elle, part de la CAUSE et ecrit sa propre phrase. Faute de cause
|
|
160
|
+
* connue, le message brut reste, valant mieux que rien.
|
|
161
|
+
*/
|
|
162
|
+
const refusal = computed<string | null>(() => {
|
|
163
|
+
const kind = props.alert.lastErrorKind
|
|
164
|
+
if (!kind) return props.alert.lastError ?? null
|
|
165
|
+
|
|
166
|
+
const sentences = T.value.refusal as Record<string, any>
|
|
167
|
+
const sentence = sentences[kind]
|
|
168
|
+
if (!sentence) return props.alert.lastError ?? null
|
|
169
|
+
if (typeof sentence === 'string') return sentence
|
|
170
|
+
|
|
171
|
+
const count = number(props.alert.lastErrorCount ?? 0)
|
|
172
|
+
return kind === 'too_broad'
|
|
173
|
+
? sentence(count, number(props.alert.maxTracked ?? 10000))
|
|
174
|
+
: sentence(count)
|
|
175
|
+
})
|
|
176
|
+
|
|
120
177
|
/** Les etats qui demandent une explication, pas seulement une pastille. */
|
|
121
178
|
const notice = computed(() => {
|
|
122
179
|
const status = props.alert.status
|
|
123
180
|
if (status === 'active') return null
|
|
181
|
+
// Un refus explique se suffit : redoubler « le dernier passage a ete
|
|
182
|
+
// refuse » avec « cette vue est trop large » dit deux fois la meme chose.
|
|
183
|
+
const text = status === 'failing' && refusal.value ? refusal.value : T.value.notice[status]
|
|
124
184
|
return {
|
|
125
185
|
tone: status === 'stale' || status === 'failing' ? 'warn' : 'info',
|
|
126
|
-
text
|
|
127
|
-
detail:
|
|
186
|
+
text,
|
|
187
|
+
detail: null as string | null,
|
|
128
188
|
}
|
|
129
189
|
})
|
|
130
190
|
|
|
@@ -54,6 +54,11 @@ const props = withDefaults(
|
|
|
54
54
|
mode?: 'create' | 'edit'
|
|
55
55
|
/** Alerte a modifier, en mode `edit`. */
|
|
56
56
|
initial?: Partial<RmAlertDraft>
|
|
57
|
+
/**
|
|
58
|
+
* Le mode d'essai est ouvert cote API : la cadence courte apparait. Hors
|
|
59
|
+
* de la, elle n'existe pas a l'ecran.
|
|
60
|
+
*/
|
|
61
|
+
testCadence?: boolean
|
|
57
62
|
lang?: 'fr' | 'en'
|
|
58
63
|
}>(),
|
|
59
64
|
{
|
|
@@ -64,6 +69,7 @@ const props = withDefaults(
|
|
|
64
69
|
submitting: false,
|
|
65
70
|
mode: 'create',
|
|
66
71
|
initial: undefined,
|
|
72
|
+
testCadence: false,
|
|
67
73
|
lang: 'fr',
|
|
68
74
|
},
|
|
69
75
|
)
|
|
@@ -109,6 +115,7 @@ const FR = {
|
|
|
109
115
|
daily: 'Quotidienne (un envoi par jour au plus)',
|
|
110
116
|
weekly: 'Hebdomadaire (un envoi par semaine au plus)',
|
|
111
117
|
monthly: 'Mensuelle (un envoi par mois au plus)',
|
|
118
|
+
test5: 'Toutes les 5 minutes (mode essai)',
|
|
112
119
|
cadenceHint:
|
|
113
120
|
'Un plafond, pas un rythme : rien ne part quand rien n’a bougé, et la détection suit celle des données.',
|
|
114
121
|
submit: 'Créer l’alerte',
|
|
@@ -150,6 +157,7 @@ const EN = {
|
|
|
150
157
|
daily: 'Daily (at most one a day)',
|
|
151
158
|
weekly: 'Weekly (at most one a week)',
|
|
152
159
|
monthly: 'Monthly (at most one a month)',
|
|
160
|
+
test5: 'Every 5 minutes (test mode)',
|
|
153
161
|
cadenceHint:
|
|
154
162
|
'A cap, not a rhythm: nothing goes out when nothing moved, and detection follows the data.',
|
|
155
163
|
submit: 'Create the alert',
|
|
@@ -246,6 +254,9 @@ const cadenceOptions = computed(() => [
|
|
|
246
254
|
{ value: 'monthly' as const, label: T.value.monthly },
|
|
247
255
|
{ value: 'weekly' as const, label: T.value.weekly },
|
|
248
256
|
{ value: 'daily' as const, label: T.value.daily },
|
|
257
|
+
...(props.testCadence
|
|
258
|
+
? [{ value: 'test5' as const, label: T.value.test5 }]
|
|
259
|
+
: []),
|
|
249
260
|
])
|
|
250
261
|
|
|
251
262
|
const cadenceLabel = computed(
|
|
@@ -6,8 +6,13 @@
|
|
|
6
6
|
* importer un `.vue`. Meme raison que pour `utils/export.ts`.
|
|
7
7
|
*/
|
|
8
8
|
export type RmAlertStatus = 'seeding' | 'active' | 'paused' | 'stale' | 'failing';
|
|
9
|
-
/**
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Plafond d'envoi du mail, jamais une promesse de frequence.
|
|
11
|
+
*
|
|
12
|
+
* `test5` n'est pas un produit : c'est le mode d'essai (cinq minutes), qui
|
|
13
|
+
* n'apparait que si l'API dit l'avoir ouvert.
|
|
14
|
+
*/
|
|
15
|
+
export type RmAlertCadence = 'daily' | 'weekly' | 'monthly' | 'test5';
|
|
11
16
|
/**
|
|
12
17
|
* Surveiller le document entier plutot qu'une liste de champs. Les champs
|
|
13
18
|
* d'ingestion (horodatage, date de collecte) restent exclus cote moteur,
|
|
@@ -37,8 +42,18 @@ export interface RmAlert {
|
|
|
37
42
|
trackedCount?: number;
|
|
38
43
|
/** Evenements pas encore lus. */
|
|
39
44
|
unreadCount?: number;
|
|
40
|
-
/** Message du dernier passage refuse. */
|
|
45
|
+
/** Message brut du dernier passage refuse. Repli, quand la cause est inconnue. */
|
|
41
46
|
lastError?: string | null;
|
|
47
|
+
/**
|
|
48
|
+
* Cause du refus, telle que le moteur la nomme. C'est elle qui choisit la
|
|
49
|
+
* phrase affichee : un message technique en anglais n'a rien a faire sous
|
|
50
|
+
* les yeux d'un utilisateur.
|
|
51
|
+
*/
|
|
52
|
+
lastErrorKind?: string | null;
|
|
53
|
+
/** Chiffre sur lequel le refus porte (documents trouves, retrouves...). */
|
|
54
|
+
lastErrorCount?: number | null;
|
|
55
|
+
/** Plafond de documents qu'une alerte peut suivre. */
|
|
56
|
+
maxTracked?: number | null;
|
|
42
57
|
lastRunAt?: string | null;
|
|
43
58
|
/** Date de la derniere remise a zero de la reference, s'il y en a eu une. */
|
|
44
59
|
reseededAt?: string | null;
|