@tekkare/romulus 0.1.104 → 0.1.105
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
|
@@ -18,12 +18,29 @@
|
|
|
18
18
|
-->
|
|
19
19
|
<script setup lang="ts">
|
|
20
20
|
import { computed, ref, watch } from 'vue'
|
|
21
|
-
import type {
|
|
21
|
+
import type {
|
|
22
|
+
RmAlertCadence,
|
|
23
|
+
RmAlertDraft,
|
|
24
|
+
RmAlertField,
|
|
25
|
+
RmAlertTrigger,
|
|
26
|
+
RmAlertViewOption,
|
|
27
|
+
} from '../utils/alerts'
|
|
28
|
+
import { RM_ALERT_ANY_FIELD } from '../utils/alerts'
|
|
22
29
|
|
|
23
30
|
const props = withDefaults(
|
|
24
31
|
defineProps<{
|
|
25
32
|
/** Nom de la vue surveillee, affiche et repris comme titre par defaut. */
|
|
26
33
|
viewTitle: string
|
|
34
|
+
/**
|
|
35
|
+
* Vues enregistrees de la page. Avec plusieurs, le formulaire propose un
|
|
36
|
+
* selecteur : une alerte peut se poser sans avoir la vue a l'ecran.
|
|
37
|
+
*/
|
|
38
|
+
views?: RmAlertViewOption[]
|
|
39
|
+
/**
|
|
40
|
+
* L'ecran porte des filtres qui pourraient devenir une vue. Ajoute
|
|
41
|
+
* l'entree « ecran actuel » au selecteur.
|
|
42
|
+
*/
|
|
43
|
+
canSaveScreen?: boolean
|
|
27
44
|
/** Champs surveillables de la page. Vide : seule l'apparition compte. */
|
|
28
45
|
fields?: RmAlertField[]
|
|
29
46
|
/** Nombre d'elements que la vue tient a l'ecran, s'il est connu. */
|
|
@@ -31,15 +48,32 @@ const props = withDefaults(
|
|
|
31
48
|
submitting?: boolean
|
|
32
49
|
lang?: 'fr' | 'en'
|
|
33
50
|
}>(),
|
|
34
|
-
{
|
|
51
|
+
{
|
|
52
|
+
views: () => [],
|
|
53
|
+
canSaveScreen: false,
|
|
54
|
+
fields: () => [],
|
|
55
|
+
scopeCount: null,
|
|
56
|
+
submitting: false,
|
|
57
|
+
lang: 'fr',
|
|
58
|
+
},
|
|
35
59
|
)
|
|
36
60
|
|
|
37
61
|
const emit = defineEmits<{
|
|
38
62
|
submit: [draft: RmAlertDraft]
|
|
39
63
|
cancel: []
|
|
64
|
+
/**
|
|
65
|
+
* Une autre vue vient d'etre choisie. L'appelant doit l'appliquer a la
|
|
66
|
+
* page : c'est elle qui construit la requete Elasticsearch, donc l'ecran et
|
|
67
|
+
* la vue surveillee doivent dire la meme chose au moment de la capture.
|
|
68
|
+
*/
|
|
69
|
+
'select-view': [id: string]
|
|
40
70
|
}>()
|
|
41
71
|
|
|
42
72
|
const FR = {
|
|
73
|
+
screenOption: 'Écran actuel (une vue sera créée)',
|
|
74
|
+
viewSelect: 'Vue à surveiller',
|
|
75
|
+
viewApplied: 'La vue choisie est appliquée à l’écran : c’est lui qui fournit la requête surveillée.',
|
|
76
|
+
screenNote: 'Vos filtres actuels seront enregistrés comme une vue portant le nom de l’alerte.',
|
|
43
77
|
name: 'Nom de l’alerte',
|
|
44
78
|
view: 'Vue surveillée',
|
|
45
79
|
viewHint: 'L’alerte se déclenche sur le périmètre de cette vue, tel qu’il est à l’écran.',
|
|
@@ -55,17 +89,18 @@ const FR = {
|
|
|
55
89
|
fieldsHint: 'Un seul message par élément, quel que soit le nombre de champs cochés.',
|
|
56
90
|
fieldsRequired: 'Cochez au moins un champ pour surveiller les changements.',
|
|
57
91
|
noFields: 'Cette page ne propose aucun champ surveillable pour le moment.',
|
|
92
|
+
anyField: 'N’importe quel changement',
|
|
93
|
+
anyFieldHint:
|
|
94
|
+
'Tout le document est comparé. Plus large, mais plus bavard : une correction de libellé compte autant qu’un mouvement de prix.',
|
|
58
95
|
channels: 'Canaux',
|
|
59
96
|
inApp: 'Dans l’app (pastille sur la tuile Alertes)',
|
|
60
97
|
email: 'Email',
|
|
61
98
|
cadence: 'Fréquence d’envoi du mail',
|
|
62
99
|
daily: 'Quotidienne (un envoi par jour au plus)',
|
|
63
100
|
weekly: 'Hebdomadaire (un envoi par semaine au plus)',
|
|
101
|
+
monthly: 'Mensuelle (un envoi par mois au plus)',
|
|
64
102
|
cadenceHint:
|
|
65
103
|
'Un plafond, pas un rythme : rien ne part quand rien n’a bougé, et la détection suit celle des données.',
|
|
66
|
-
visibility: 'Partage',
|
|
67
|
-
private: 'Pour moi seul',
|
|
68
|
-
workspace: 'Visible par mon espace de travail',
|
|
69
104
|
submit: 'Créer l’alerte',
|
|
70
105
|
cancel: 'Annuler',
|
|
71
106
|
baseline:
|
|
@@ -74,6 +109,10 @@ const FR = {
|
|
|
74
109
|
}
|
|
75
110
|
|
|
76
111
|
const EN = {
|
|
112
|
+
screenOption: 'Current screen (a view will be created)',
|
|
113
|
+
viewSelect: 'View to watch',
|
|
114
|
+
viewApplied: 'The chosen view is applied to the screen: the screen is what provides the watched query.',
|
|
115
|
+
screenNote: 'Your current filters will be saved as a view named after the alert.',
|
|
77
116
|
name: 'Alert name',
|
|
78
117
|
view: 'Watched view',
|
|
79
118
|
viewHint: 'The alert fires on this view’s scope, as it stands on screen.',
|
|
@@ -89,17 +128,18 @@ const EN = {
|
|
|
89
128
|
fieldsHint: 'One message per item, however many fields are ticked.',
|
|
90
129
|
fieldsRequired: 'Tick at least one field to watch for changes.',
|
|
91
130
|
noFields: 'This page offers no watchable field yet.',
|
|
131
|
+
anyField: 'Any change',
|
|
132
|
+
anyFieldHint:
|
|
133
|
+
'The whole document is compared. Wider, but noisier: a label fix counts as much as a price move.',
|
|
92
134
|
channels: 'Channels',
|
|
93
135
|
inApp: 'In app (badge on the Alerts tile)',
|
|
94
136
|
email: 'Email',
|
|
95
137
|
cadence: 'Mail frequency',
|
|
96
138
|
daily: 'Daily (at most one a day)',
|
|
97
139
|
weekly: 'Weekly (at most one a week)',
|
|
140
|
+
monthly: 'Monthly (at most one a month)',
|
|
98
141
|
cadenceHint:
|
|
99
142
|
'A cap, not a rhythm: nothing goes out when nothing moved, and detection follows the data.',
|
|
100
|
-
visibility: 'Sharing',
|
|
101
|
-
private: 'Just me',
|
|
102
|
-
workspace: 'Visible to my workspace',
|
|
103
143
|
submit: 'Create the alert',
|
|
104
144
|
cancel: 'Cancel',
|
|
105
145
|
baseline:
|
|
@@ -109,20 +149,47 @@ const EN = {
|
|
|
109
149
|
|
|
110
150
|
const T = computed(() => (props.lang === 'en' ? EN : FR))
|
|
111
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Vue retenue. `null` designe l'ecran actuel, qui deviendra une vue au moment
|
|
154
|
+
* de la creation.
|
|
155
|
+
*/
|
|
156
|
+
const selectedViewId = ref<string | null>(props.views[0]?.id ?? null)
|
|
157
|
+
|
|
158
|
+
/** Entrees du selecteur, l'ecran actuel en tete quand il a des filtres. */
|
|
159
|
+
const viewOptions = computed(() => [
|
|
160
|
+
...(props.canSaveScreen ? [{ id: null as string | null, title: T.value.screenOption }] : []),
|
|
161
|
+
...props.views.map((view) => ({ id: view.id as string | null, title: view.title })),
|
|
162
|
+
])
|
|
163
|
+
|
|
164
|
+
const selectedView = computed(
|
|
165
|
+
() => viewOptions.value.find((option) => option.id === selectedViewId.value) ?? viewOptions.value[0],
|
|
166
|
+
)
|
|
167
|
+
|
|
112
168
|
const title = ref(props.viewTitle)
|
|
113
169
|
const triggers = ref<RmAlertTrigger[]>(['appeared'])
|
|
114
170
|
const watchedFields = ref<string[]>([])
|
|
171
|
+
/** Surveiller le document entier plutot qu'une liste de champs. */
|
|
172
|
+
const anyField = ref(false)
|
|
115
173
|
const emailOn = ref(false)
|
|
116
|
-
const cadence = ref<
|
|
117
|
-
|
|
174
|
+
const cadence = ref<RmAlertCadence>('weekly')
|
|
175
|
+
|
|
176
|
+
/** Titre libre des que l'utilisateur y touche : on ne l'ecrase plus. */
|
|
177
|
+
const titleTouched = ref(false)
|
|
118
178
|
|
|
119
179
|
watch(
|
|
120
180
|
() => props.viewTitle,
|
|
121
181
|
(value) => {
|
|
122
|
-
title.value = value
|
|
182
|
+
if (!titleTouched.value) title.value = value
|
|
123
183
|
},
|
|
124
184
|
)
|
|
125
185
|
|
|
186
|
+
watch(selectedViewId, (id) => {
|
|
187
|
+
const view = props.views.find((entry) => entry.id === id)
|
|
188
|
+
if (view && !titleTouched.value) title.value = view.title
|
|
189
|
+
// Une vue choisie doit etre posee a l'ecran avant la capture.
|
|
190
|
+
if (id) emit('select-view', id)
|
|
191
|
+
})
|
|
192
|
+
|
|
126
193
|
/**
|
|
127
194
|
* Deux bascules plutot qu'une generique : dans le template, un `ref` est
|
|
128
195
|
* deballe, donc lui passer la reference elle-meme ne marche pas.
|
|
@@ -146,7 +213,22 @@ const watchesChanges = computed(() => triggers.value.includes('changed'))
|
|
|
146
213
|
* moteur comparerait un hachage vide et ne trouverait jamais rien.
|
|
147
214
|
*/
|
|
148
215
|
const missingFields = computed(
|
|
149
|
-
() =>
|
|
216
|
+
() =>
|
|
217
|
+
watchesChanges.value &&
|
|
218
|
+
!anyField.value &&
|
|
219
|
+
watchedFields.value.length === 0 &&
|
|
220
|
+
props.fields.length > 0,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
/** Options de cadence, dans l'ordre du plus espace au plus frequent. */
|
|
224
|
+
const cadenceOptions = computed(() => [
|
|
225
|
+
{ value: 'monthly' as const, label: T.value.monthly },
|
|
226
|
+
{ value: 'weekly' as const, label: T.value.weekly },
|
|
227
|
+
{ value: 'daily' as const, label: T.value.daily },
|
|
228
|
+
])
|
|
229
|
+
|
|
230
|
+
const cadenceLabel = computed(
|
|
231
|
+
() => cadenceOptions.value.find((option) => option.value === cadence.value)?.label ?? '',
|
|
150
232
|
)
|
|
151
233
|
|
|
152
234
|
const valid = computed(
|
|
@@ -157,35 +239,65 @@ function submit() {
|
|
|
157
239
|
if (!valid.value) return
|
|
158
240
|
emit('submit', {
|
|
159
241
|
title: title.value.trim(),
|
|
242
|
+
viewId: selectedViewId.value,
|
|
160
243
|
triggers: triggers.value,
|
|
161
244
|
// Les champs ne servent qu'au declencheur « changement » : les garder
|
|
162
245
|
// sans lui ferait porter a l'alerte une promesse qu'elle ne tient pas.
|
|
163
|
-
watchedFields: watchesChanges.value
|
|
246
|
+
watchedFields: watchesChanges.value
|
|
247
|
+
? anyField.value
|
|
248
|
+
? [RM_ALERT_ANY_FIELD]
|
|
249
|
+
: watchedFields.value
|
|
250
|
+
: [],
|
|
164
251
|
channels: emailOn.value ? ['in_app', 'email'] : ['in_app'],
|
|
165
252
|
cadence: cadence.value,
|
|
166
|
-
|
|
253
|
+
// Le partage viendra plus tard : le schema le porte deja, l'ecran non.
|
|
254
|
+
visibility: 'private',
|
|
167
255
|
})
|
|
168
256
|
}
|
|
169
257
|
</script>
|
|
170
258
|
|
|
171
259
|
<template>
|
|
172
260
|
<form class="rm-alert-form" @submit.prevent="submit">
|
|
173
|
-
<RmInput
|
|
261
|
+
<RmInput
|
|
262
|
+
:model-value="title"
|
|
263
|
+
:label="T.name"
|
|
264
|
+
required
|
|
265
|
+
@update:model-value="
|
|
266
|
+
titleTouched = true;
|
|
267
|
+
title = $event;
|
|
268
|
+
"
|
|
269
|
+
/>
|
|
174
270
|
|
|
175
271
|
<div class="rm-alert-form__view">
|
|
176
272
|
<p class="rm-alert-form__label">{{ T.view }}</p>
|
|
177
|
-
<p class="rm-alert-
|
|
273
|
+
<p class="rm-alert-form__hint">
|
|
274
|
+
{{ viewOptions.length > 1 ? T.viewApplied : T.viewHint }}
|
|
275
|
+
</p>
|
|
276
|
+
|
|
277
|
+
<RmDropdownSelect
|
|
278
|
+
v-if="viewOptions.length > 1"
|
|
279
|
+
label=""
|
|
280
|
+
:options="viewOptions.map((option) => option.title)"
|
|
281
|
+
:model-value="selectedView?.title ?? ''"
|
|
282
|
+
@update:model-value="
|
|
283
|
+
selectedViewId =
|
|
284
|
+
viewOptions.find((option) => option.title === $event)?.id ?? null
|
|
285
|
+
"
|
|
286
|
+
/>
|
|
287
|
+
<p v-else class="rm-alert-form__view-name">
|
|
178
288
|
<RmIcon name="BookmarkSimple" :size="14" />
|
|
179
|
-
{{ viewTitle }}
|
|
180
|
-
<span v-if="scopeCount" class="rm-alert-form__count">
|
|
181
|
-
{{ scopeCount }} {{ T.scope }}
|
|
182
|
-
</span>
|
|
289
|
+
{{ selectedView?.title ?? viewTitle }}
|
|
183
290
|
</p>
|
|
184
|
-
|
|
291
|
+
|
|
292
|
+
<p v-if="scopeCount && selectedViewId" class="rm-alert-form__count">
|
|
293
|
+
{{ scopeCount }} {{ T.scope }}
|
|
294
|
+
</p>
|
|
295
|
+
<p v-if="!selectedViewId" class="rm-alert-form__hint">{{ T.screenNote }}</p>
|
|
185
296
|
</div>
|
|
186
297
|
|
|
187
298
|
<fieldset class="rm-alert-form__group">
|
|
188
299
|
<legend class="rm-alert-form__label">{{ T.triggers }}</legend>
|
|
300
|
+
<p class="rm-alert-form__hint">{{ T.triggersHint }}</p>
|
|
189
301
|
<RmCheckbox
|
|
190
302
|
v-for="entry in [
|
|
191
303
|
{ key: 'appeared', label: T.appeared, hint: T.appearedHint },
|
|
@@ -198,20 +310,21 @@ function submit() {
|
|
|
198
310
|
:tooltip="entry.hint"
|
|
199
311
|
@update:model-value="toggleTrigger(entry.key as RmAlertTrigger)"
|
|
200
312
|
/>
|
|
201
|
-
<p class="rm-alert-form__hint">{{ T.triggersHint }}</p>
|
|
202
313
|
</fieldset>
|
|
203
314
|
|
|
204
315
|
<fieldset v-if="watchesChanges" class="rm-alert-form__group">
|
|
205
316
|
<legend class="rm-alert-form__label">{{ T.fields }}</legend>
|
|
317
|
+
<p class="rm-alert-form__hint">{{ anyField ? T.anyFieldHint : T.fieldsHint }}</p>
|
|
206
318
|
<template v-if="fields.length">
|
|
319
|
+
<RmCheckbox v-model="anyField" :label="T.anyField" />
|
|
207
320
|
<RmCheckbox
|
|
208
321
|
v-for="field in fields"
|
|
209
322
|
:key="field.value"
|
|
210
|
-
:model-value="watchedFields.includes(field.value)"
|
|
323
|
+
:model-value="anyField || watchedFields.includes(field.value)"
|
|
211
324
|
:label="field.label"
|
|
325
|
+
:disabled="anyField"
|
|
212
326
|
@update:model-value="toggleField(field.value)"
|
|
213
327
|
/>
|
|
214
|
-
<p class="rm-alert-form__hint">{{ T.fieldsHint }}</p>
|
|
215
328
|
<p v-if="missingFields" class="rm-alert-form__error">{{ T.fieldsRequired }}</p>
|
|
216
329
|
</template>
|
|
217
330
|
<p v-else class="rm-alert-form__hint">{{ T.noFields }}</p>
|
|
@@ -223,21 +336,20 @@ function submit() {
|
|
|
223
336
|
<RmCheckbox v-model="emailOn" :label="T.email" />
|
|
224
337
|
|
|
225
338
|
<div v-if="emailOn" class="rm-alert-form__nested">
|
|
339
|
+
<p class="rm-alert-form__label">{{ T.cadence }}</p>
|
|
340
|
+
<p class="rm-alert-form__hint">{{ T.cadenceHint }}</p>
|
|
226
341
|
<RmDropdownSelect
|
|
227
|
-
|
|
228
|
-
:options="
|
|
229
|
-
:model-value="
|
|
230
|
-
@update:model-value="
|
|
342
|
+
label=""
|
|
343
|
+
:options="cadenceOptions.map((option) => option.label)"
|
|
344
|
+
:model-value="cadenceLabel"
|
|
345
|
+
@update:model-value="
|
|
346
|
+
cadence =
|
|
347
|
+
cadenceOptions.find((option) => option.label === $event)?.value ?? 'weekly'
|
|
348
|
+
"
|
|
231
349
|
/>
|
|
232
|
-
<p class="rm-alert-form__hint">{{ T.cadenceHint }}</p>
|
|
233
350
|
</div>
|
|
234
351
|
</fieldset>
|
|
235
352
|
|
|
236
|
-
<fieldset class="rm-alert-form__group">
|
|
237
|
-
<legend class="rm-alert-form__label">{{ T.visibility }}</legend>
|
|
238
|
-
<RmCheckbox v-model="shared" :label="T.workspace" />
|
|
239
|
-
</fieldset>
|
|
240
|
-
|
|
241
353
|
<p class="rm-alert-form__baseline">
|
|
242
354
|
<RmIcon name="Info" :size="14" />
|
|
243
355
|
{{ T.baseline }}
|
|
@@ -258,5 +370,5 @@ function submit() {
|
|
|
258
370
|
</template>
|
|
259
371
|
|
|
260
372
|
<style scoped>
|
|
261
|
-
.rm-alert-form{display:flex;flex-direction:column;gap:18px}.rm-alert-form__label{color:var(--rm-text,#111827);font-size:13px;font-weight:600;margin:0 0
|
|
373
|
+
.rm-alert-form{display:flex;flex-direction:column;gap:18px}.rm-alert-form__label{color:var(--rm-text,#111827);font-size:13px;font-weight:600;margin:0 0 2px;padding:0}.rm-alert-form__group{border:0;display:flex;flex-direction:column;gap:8px;margin:0;padding:0}.rm-alert-form__view-name{align-items:center;color:var(--rm-text,#111827);display:flex;flex-wrap:wrap;font-size:14px;gap:6px;margin:0}.rm-alert-form__count{color:var(--rm-text-soft,#9ca3af);font-size:11.5px}.rm-alert-form__hint{color:var(--rm-text-soft,#9ca3af);font-size:12px;line-height:1.45;margin:0 0 4px}.rm-alert-form__error{color:var(--rm-danger,#b91c1c);font-size:12px;margin:0}.rm-alert-form__nested{display:flex;flex-direction:column;gap:6px;padding-left:26px}.rm-alert-form__baseline{align-items:flex-start;background:var(--rm-surface-muted,#f9fafb);border-radius:8px;color:var(--rm-text-soft,#4b5563);display:flex;font-size:12.5px;gap:8px;line-height:1.45;margin:0;padding:10px 12px}.rm-alert-form__actions{display:flex;gap:8px;justify-content:flex-end}
|
|
262
374
|
</style>
|
|
@@ -101,5 +101,5 @@ const modalStyle = computed(() => {
|
|
|
101
101
|
</template>
|
|
102
102
|
|
|
103
103
|
<style scoped>
|
|
104
|
-
.rm-modal-overlay{align-items:center;backdrop-filter:blur(2px);background:rgba(0,0,0,.4);display:flex;inset:0;justify-content:center;position:fixed;z-index:100}.rm-modal{background:var(--bg-surface);border-radius:12px;box-shadow:0 20px 60px rgba(0,0,0,.15);display:flex;flex-direction:column;max-height:90vh;max-width:95vw}.rm-modal__header{align-items:flex-start;display:flex;gap:var(--space-16);justify-content:space-between;padding:var(--space-20) var(--space-24) 0}.rm-modal__header-content{flex:1;min-width:0}.rm-modal__close{align-items:center;background:none;border:none;border-radius:var(--r-radius-md);color:var(--text-muted);cursor:pointer;display:flex;flex-shrink:0;height:32px;justify-content:center;transition:all var(--r-transition-fast);width:32px}.rm-modal__close:hover{background:var(--bg-surface-3);color:var(--text-primary)}.rm-modal__tabs{padding:0}.rm-modal__body{flex:1;overflow-y:auto;padding:var(--space-24)}.rm-modal__footer{border-top:1px solid var(--border-soft);padding:var(--space-16) var(--space-24)}.rm-modal-enter-active,.rm-modal-leave-active{transition:opacity .2s ease}.rm-modal-enter-active .rm-modal,.rm-modal-leave-active .rm-modal{transition:transform .2s ease}.rm-modal-enter-from,.rm-modal-leave-to{opacity:0}.rm-modal-enter-from .rm-modal,.rm-modal-leave-to .rm-modal{transform:scale(.95)}.rm-modal-leave-active,.rm-modal-leave-to{pointer-events:none}
|
|
104
|
+
.rm-modal-overlay{align-items:center;backdrop-filter:blur(2px);background:rgba(0,0,0,.4);display:flex;font-family:var(--r-font-family);inset:0;justify-content:center;position:fixed;z-index:100}.rm-modal{background:var(--bg-surface);border-radius:12px;box-shadow:0 20px 60px rgba(0,0,0,.15);display:flex;flex-direction:column;max-height:90vh;max-width:95vw}.rm-modal__header{align-items:flex-start;display:flex;gap:var(--space-16);justify-content:space-between;padding:var(--space-20) var(--space-24) 0}.rm-modal__header-content{flex:1;min-width:0}.rm-modal__close{align-items:center;background:none;border:none;border-radius:var(--r-radius-md);color:var(--text-muted);cursor:pointer;display:flex;flex-shrink:0;height:32px;justify-content:center;transition:all var(--r-transition-fast);width:32px}.rm-modal__close:hover{background:var(--bg-surface-3);color:var(--text-primary)}.rm-modal__tabs{padding:0}.rm-modal__body{flex:1;overflow-y:auto;padding:var(--space-24)}.rm-modal__footer{border-top:1px solid var(--border-soft);padding:var(--space-16) var(--space-24)}.rm-modal-enter-active,.rm-modal-leave-active{transition:opacity .2s ease}.rm-modal-enter-active .rm-modal,.rm-modal-leave-active .rm-modal{transition:transform .2s ease}.rm-modal-enter-from,.rm-modal-leave-to{opacity:0}.rm-modal-enter-from .rm-modal,.rm-modal-leave-to .rm-modal{transform:scale(.95)}.rm-modal-leave-active,.rm-modal-leave-to{pointer-events:none}
|
|
105
105
|
</style>
|
|
@@ -6,6 +6,14 @@
|
|
|
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
|
+
/** Plafond d'envoi du mail, jamais une promesse de frequence. */
|
|
10
|
+
export type RmAlertCadence = 'daily' | 'weekly' | 'monthly';
|
|
11
|
+
/**
|
|
12
|
+
* Surveiller le document entier plutot qu'une liste de champs. Les champs
|
|
13
|
+
* d'ingestion (horodatage, date de collecte) restent exclus cote moteur,
|
|
14
|
+
* sinon chaque reindexation ferait bouger chaque document.
|
|
15
|
+
*/
|
|
16
|
+
export declare const RM_ALERT_ANY_FIELD = "*";
|
|
9
17
|
/** Ce qu'une alerte sait detecter. Les trois sortent du meme passage de diff. */
|
|
10
18
|
export type RmAlertTrigger = 'appeared' | 'changed' | 'disappeared';
|
|
11
19
|
export interface RmAlertMenuItem {
|
|
@@ -66,12 +74,22 @@ export interface RmAlertField {
|
|
|
66
74
|
value: string;
|
|
67
75
|
label: string;
|
|
68
76
|
}
|
|
77
|
+
/** Une vue proposee dans le selecteur du formulaire. */
|
|
78
|
+
export interface RmAlertViewOption {
|
|
79
|
+
id: string;
|
|
80
|
+
title: string;
|
|
81
|
+
}
|
|
69
82
|
/** Ce que le formulaire de creation rend a l'appelant. */
|
|
70
83
|
export interface RmAlertDraft {
|
|
71
84
|
title: string;
|
|
85
|
+
/**
|
|
86
|
+
* Vue a surveiller. `null` : l'ecran actuel, que l'appelant enregistrera
|
|
87
|
+
* comme vue avant de creer l'alerte.
|
|
88
|
+
*/
|
|
89
|
+
viewId: string | null;
|
|
72
90
|
triggers: RmAlertTrigger[];
|
|
73
91
|
watchedFields: string[];
|
|
74
92
|
channels: string[];
|
|
75
|
-
cadence:
|
|
93
|
+
cadence: RmAlertCadence;
|
|
76
94
|
visibility: 'private' | 'workspace';
|
|
77
95
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const RM_ALERT_ANY_FIELD = "*";
|