@tekkare/romulus 0.1.184 → 0.1.185

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
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.16.0"
6
6
  },
7
- "version": "0.1.183",
7
+ "version": "0.1.184",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "2.0.0"
@@ -14,7 +14,11 @@
14
14
  voudrait dire autant de requetes et autant de references sur le meme jeu
15
15
  de documents, et plusieurs messages le meme matin pour le meme produit ;
16
16
  - la cadence appartient au mail. La pastille de l'app encaisse au fil de
17
- l'eau, elle n'a pas de digest.
17
+ l'eau, elle n'a pas de digest ;
18
+ - une alerte de produit ne choisit ni champs ni declencheurs : ils sont deja
19
+ forces a « tout » (cf. `watchesProduct`), le formulaire ne fait que les
20
+ cacher. Choisir « seulement l'apparition » sur une marque suivie partout
21
+ ferait manquer un dereboursement.
18
22
  -->
19
23
  <script setup lang="ts">
20
24
  import { computed, ref, watch } from 'vue'
@@ -103,6 +107,13 @@ const emit = defineEmits<{
103
107
  'select-view': [id: string]
104
108
  /** Saisie du selecteur de marques, a porter jusqu'a l'index. */
105
109
  'search-brands': [value: string]
110
+ /**
111
+ * Le formulaire s'ecarte de sa reference de depart. L'appelant n'a pas
112
+ * acces aux refs internes (titre, marques, declencheurs...) : c'est le
113
+ * seul moyen pour lui de savoir s'il y a quelque chose a perdre avant de
114
+ * fermer.
115
+ */
116
+ 'update:dirty': [value: boolean]
106
117
  }>()
107
118
 
108
119
  const FR = {
@@ -116,7 +127,7 @@ const FR = {
116
127
  brandsHint: 'Cherchez par marque, molécule, classe ATC ou laboratoire. L’alerte couvre tout le hub pour chaque marque retenue.',
117
128
  brandsRequired: 'Choisissez au moins une marque.',
118
129
  brandsTooMany: 'Une alerte suit {max} marques au maximum.',
119
- productFields: 'Tous les champs sont suivis : une alerte de marque ne se restreint pas, elle rapporte tout ce qui bouge.',
130
+ productFields: 'Rien à choisir : une alerte de marque suit tout, tous champs et tous déclencheurs confondus (nouvel élément, changement de valeur, sortie du périmètre).',
120
131
  screenOption: 'Écran actuel (une vue sera créée)',
121
132
  viewSelect: 'Vue à surveiller',
122
133
  viewApplied: 'La vue choisie est appliquée à l’écran : c’est lui qui fournit la requête surveillée.',
@@ -169,7 +180,7 @@ const EN = {
169
180
  brandsHint: 'Search by brand, molecule, ATC class or company. The alert covers the whole hub for each brand kept.',
170
181
  brandsRequired: 'Pick at least one brand.',
171
182
  brandsTooMany: 'An alert watches at most {max} brands.',
172
- productFields: 'Every field is watched: a brand alert does not narrow down, it reports whatever moves.',
183
+ productFields: 'Nothing to choose: a brand alert watches everything, every field and every trigger (new item, value change, left the scope).',
173
184
  screenOption: 'Current screen (a view will be created)',
174
185
  viewSelect: 'View to watch',
175
186
  viewApplied: 'The chosen view is applied to the screen: the screen is what provides the watched query.',
@@ -249,7 +260,19 @@ watch(brandSearch, (value) => emit('search-brands', value))
249
260
  const watchesProduct = computed(() => kind.value === 'product')
250
261
 
251
262
  const title = ref(props.initial?.title ?? props.viewTitle)
252
- const triggers = ref<RmAlertTrigger[]>(props.initial?.triggers ?? ['appeared'])
263
+ /**
264
+ * Une alerte de produit suit tout, declencheurs compris : le choix ne se pose
265
+ * pas plus que celui des champs, et cocher que « nouvel element » laisserait
266
+ * croire qu'un changement de prix sur une marque deja suivie ne compte pas.
267
+ */
268
+ const ALL_TRIGGERS: RmAlertTrigger[] = ['appeared', 'changed', 'disappeared']
269
+ const triggers = ref<RmAlertTrigger[]>(
270
+ props.initial?.triggers ??
271
+ (kind.value === 'product' ? ALL_TRIGGERS : ['appeared']),
272
+ )
273
+ watch(kind, (value) => {
274
+ if (value === 'product') triggers.value = ALL_TRIGGERS
275
+ })
253
276
  const watchedFields = ref<string[]>(
254
277
  (props.initial?.watchedFields ?? []).filter((field) => field !== RM_ALERT_ANY_FIELD),
255
278
  )
@@ -264,6 +287,37 @@ const initialFields = JSON.stringify([...(props.initial?.watchedFields ?? [])].s
264
287
  /** Titre libre des que l'utilisateur y touche : on ne l'ecrase plus. */
265
288
  const titleTouched = ref(props.mode === 'edit')
266
289
 
290
+ /**
291
+ * Etat de depart, capture une seule fois : ce a quoi `dirty` compare le
292
+ * formulaire. Le titre n'y figure pas, il se suit par `titleTouched` (il
293
+ * bouge tout seul tant que l'utilisateur n'y a pas touche, cf. plus bas).
294
+ */
295
+ const baseline = {
296
+ kind: kind.value,
297
+ brands: JSON.stringify([...brands.value].sort()),
298
+ triggers: JSON.stringify([...triggers.value].sort()),
299
+ watchedFields: JSON.stringify([...watchedFields.value].sort()),
300
+ anyField: anyField.value,
301
+ emailOn: emailOn.value,
302
+ cadence: cadence.value,
303
+ selectedViewId: selectedViewId.value,
304
+ }
305
+
306
+ const dirty = computed(
307
+ () =>
308
+ titleTouched.value ||
309
+ kind.value !== baseline.kind ||
310
+ JSON.stringify([...brands.value].sort()) !== baseline.brands ||
311
+ JSON.stringify([...triggers.value].sort()) !== baseline.triggers ||
312
+ JSON.stringify([...watchedFields.value].sort()) !== baseline.watchedFields ||
313
+ anyField.value !== baseline.anyField ||
314
+ emailOn.value !== baseline.emailOn ||
315
+ cadence.value !== baseline.cadence ||
316
+ selectedViewId.value !== baseline.selectedViewId,
317
+ )
318
+
319
+ watch(dirty, (value) => emit('update:dirty', value), { immediate: true })
320
+
267
321
  watch(
268
322
  () => props.viewTitle,
269
323
  (value) => {
@@ -495,7 +549,7 @@ function submit() {
495
549
  {{ watchesProduct ? `${T.brands} : ${brands.join(', ')}` : `${T.view} : ${viewTitle}` }}
496
550
  </p>
497
551
 
498
- <fieldset class="rm-alert-form__group" data-field="triggers">
552
+ <fieldset v-if="!watchesProduct" class="rm-alert-form__group" data-field="triggers">
499
553
  <legend class="rm-alert-form__label">{{ T.triggers }}</legend>
500
554
  <p class="rm-alert-form__hint">{{ T.triggersHint }}</p>
501
555
  <RmCheckbox
@@ -512,7 +566,7 @@ function submit() {
512
566
  />
513
567
  </fieldset>
514
568
 
515
- <p v-if="watchesProduct && watchesChanges" class="rm-alert-form__hint">
569
+ <p v-if="watchesProduct" class="rm-alert-form__hint">
516
570
  {{ T.productFields }}
517
571
  </p>
518
572
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekkare/romulus",
3
- "version": "0.1.184",
3
+ "version": "0.1.185",
4
4
  "description": "Romulus Design System - Nuxt module by Tekkare",
5
5
  "license": "MIT",
6
6
  "type": "module",