@dev.smartpricing/message-composer-layer 4.2.10 → 4.2.11-ux.0

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.
@@ -1,17 +1,29 @@
1
1
  <script setup lang="ts">
2
- import type { RenderType } from '@dev.smartpricing/message-composer-utils/types'
2
+ import type { RenderType, MessageStatus } from '@dev.smartpricing/message-composer-utils/types'
3
3
  import { useMessageGroupsQuery } from '~/queries/messageGroups'
4
4
 
5
- defineOptions({ name: 'TemplateSelect' })
5
+ defineOptions({ name: 'MessageGroupSelect' })
6
6
 
7
7
  const props = withDefaults(
8
8
  defineProps<{
9
9
  renderType?: RenderType
10
10
  placeholder?: string
11
11
  searchPlaceholder?: string
12
+ /**
13
+ * Map of message-group id -> reason text explaining why the group is not
14
+ * selectable (e.g. already linked to another newsletter by an external
15
+ * system). Presence of a key disables the group; the value is shown verbatim
16
+ * as the tooltip, so it must already be localized by the caller.
17
+ *
18
+ * NOTE: the caller is responsible for excluding the currently-selected group
19
+ * when editing, otherwise the current selection will render as disabled.
20
+ */
21
+ disabledGroupReasons?: Record<string, string>
22
+ /** Overrides the "hide inactive" filter label. Defaults to the built-in translation. */
23
+ hideFilterLabel?: string
12
24
  }>(),
13
25
  {
14
- placeholder: 'Select a template',
26
+ placeholder: 'Select a message group',
15
27
  searchPlaceholder: 'Search...',
16
28
  },
17
29
  )
@@ -22,16 +34,48 @@ const emit = defineEmits<{
22
34
  select: [item: { id: string; name: string }]
23
35
  }>()
24
36
 
37
+ const { t } = useI18n()
38
+
25
39
  const { data: messageGroups, isLoading } = useMessageGroupsQuery(() => ({
26
40
  renderType: props.renderType,
27
41
  }))
28
42
 
43
+ const hideInactive = ref(false)
44
+
45
+ function isGroupActive(messages: Array<{ status: MessageStatus }>): boolean {
46
+ return messages.length > 0 && messages.every((m) => m.status === 'approved')
47
+ }
48
+
29
49
  const items = computed(() => {
30
50
  if (!messageGroups.value) return []
31
- return messageGroups.value.map((group) => ({
32
- label: group.name,
33
- value: group.id,
34
- }))
51
+ return messageGroups.value.reduce<
52
+ Array<{
53
+ label: string
54
+ value: string
55
+ disabled: boolean
56
+ tooltip?: string
57
+ chip: { color: 'success' | 'neutral' }
58
+ }>
59
+ >((acc, group) => {
60
+ const externalReason = props.disabledGroupReasons?.[group.id]
61
+ const externallyUsed = externalReason != null
62
+ const active = isGroupActive(group.messages)
63
+ const disabled = !active || externallyUsed
64
+ if (hideInactive.value && disabled) return acc
65
+ acc.push({
66
+ label: group.name,
67
+ value: group.id,
68
+ disabled,
69
+ // External reason wins over the inactive tooltip when both apply.
70
+ tooltip: externallyUsed
71
+ ? externalReason
72
+ : !active
73
+ ? t('common.messageGroupSelect.inactive_tooltip')
74
+ : undefined,
75
+ chip: { color: disabled ? 'neutral' : 'success' },
76
+ })
77
+ return acc
78
+ }, [])
35
79
  })
36
80
 
37
81
  function handleUpdate(value: string) {
@@ -50,7 +94,23 @@ function handleUpdate(value: string) {
50
94
  searchable
51
95
  :placeholder="placeholder"
52
96
  :search-input="{ placeholder: searchPlaceholder }"
53
- :data-testid="templateSelectTestIds.root"
97
+ :data-testid="messageGroupSelectTestIds.root"
54
98
  @update:model-value="handleUpdate"
55
- />
99
+ >
100
+ <template #item-label="{ item }">
101
+ <UTooltip v-if="item.disabled" :text="item.tooltip">
102
+ <span class="text-muted">{{ item.label }}</span>
103
+ </UTooltip>
104
+ <span v-else>{{ item.label }}</span>
105
+ </template>
106
+
107
+ <template #content-top>
108
+ <div class="flex items-center gap-2 px-2 py-1.5 border-b border-default">
109
+ <USwitch v-model="hideInactive" size="xs" />
110
+ <span class="text-xs text-muted">
111
+ {{ hideFilterLabel ?? t('common.messageGroupSelect.hide_inactive') }}
112
+ </span>
113
+ </div>
114
+ </template>
115
+ </USelectMenu>
56
116
  </template>
@@ -738,6 +738,9 @@ export const previewByIdTestIds = {
738
738
  loading: 'preview-by-id-loading',
739
739
  } as const
740
740
 
741
- export const templateSelectTestIds = {
742
- root: 'template-select-root',
741
+ export const messageGroupSelectTestIds = {
742
+ root: 'message-group-select-root',
743
743
  } as const
744
+
745
+ /** @deprecated Use `messageGroupSelectTestIds` instead */
746
+ export const templateSelectTestIds = messageGroupSelectTestIds
@@ -54,6 +54,11 @@ export default {
54
54
  search: 'Suchen...',
55
55
  success: 'Erfolg',
56
56
  translation_failed: 'Übersetzung fehlgeschlagen',
57
+ messageGroupSelect: {
58
+ inactive_tooltip:
59
+ 'Diese Nachrichtengruppe enthält nicht genehmigte oder fehlende Nachrichten',
60
+ hide_inactive: 'Inaktive ausblenden',
61
+ },
57
62
  view_less: 'Weniger anzeigen',
58
63
  view_more: 'Mehr anzeigen',
59
64
  },
@@ -53,6 +53,10 @@ export default {
53
53
  search: 'Search...',
54
54
  success: 'Success',
55
55
  translation_failed: 'Translation failed',
56
+ messageGroupSelect: {
57
+ inactive_tooltip: 'This message group has unapproved or missing messages',
58
+ hide_inactive: 'Hide inactive',
59
+ },
56
60
  view_less: 'View less',
57
61
  view_more: 'View more',
58
62
  },
@@ -54,6 +54,10 @@ export default {
54
54
  search: 'Buscar...',
55
55
  success: 'Éxito',
56
56
  translation_failed: 'La traducción ha fallado',
57
+ messageGroupSelect: {
58
+ inactive_tooltip: 'Este grupo de mensajes tiene mensajes no aprobados o faltantes',
59
+ hide_inactive: 'Ocultar inactivos',
60
+ },
57
61
  view_less: 'Ver menos',
58
62
  view_more: 'Ver más',
59
63
  },
@@ -54,6 +54,10 @@ export default {
54
54
  search: 'Rechercher...',
55
55
  success: 'Succès',
56
56
  translation_failed: 'Échec de la traduction',
57
+ messageGroupSelect: {
58
+ inactive_tooltip: 'Ce groupe de messages contient des messages non approuvés ou manquants',
59
+ hide_inactive: 'Masquer inactifs',
60
+ },
57
61
  view_less: 'Afficher moins',
58
62
  view_more: 'Afficher plus',
59
63
  },
@@ -53,6 +53,10 @@ export default {
53
53
  search: 'Cerca...',
54
54
  success: 'Successo',
55
55
  translation_failed: 'Traduzione non riuscita',
56
+ messageGroupSelect: {
57
+ inactive_tooltip: 'Questo gruppo di messaggi contiene messaggi non approvati o mancanti',
58
+ hide_inactive: 'Nascondi inattivi',
59
+ },
56
60
  view_less: 'Mostra meno',
57
61
  view_more: 'Mostra di più',
58
62
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev.smartpricing/message-composer-layer",
3
- "version": "4.2.10",
3
+ "version": "4.2.11-ux.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -36,7 +36,7 @@
36
36
  "vue-router": "^5.0.7",
37
37
  "vue3-emoji-picker": "^1.1.8",
38
38
  "zod": "^4.4.3",
39
- "@dev.smartpricing/message-composer-utils": "4.2.10"
39
+ "@dev.smartpricing/message-composer-utils": "4.2.11-ux.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@nuxt/eslint": "^1.15.2",