@open-mercato/core 0.6.7-develop.6785.1.1dd7cfac55 → 0.6.7-develop.6795.1.8a3f27921c
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/.turbo/turbo-build.log +1 -1
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/modules/auth/backend/settings/page.js +14 -9
- package/dist/modules/auth/backend/settings/page.js.map +2 -2
- package/dist/modules/customers/cli.js +17 -7
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +229 -216
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/search.js +50 -29
- package/dist/modules/customers/search.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/[id]/route.js +22 -9
- package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/route.js +13 -4
- package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
- package/dist/modules/data_sync/api/options.js +7 -2
- package/dist/modules/data_sync/api/options.js.map +2 -2
- package/dist/modules/data_sync/api/run.js +7 -2
- package/dist/modules/data_sync/api/run.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js +7 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/route.js +8 -3
- package/dist/modules/data_sync/api/runs/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/runs.js +7 -2
- package/dist/modules/data_sync/api/runs.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/[id]/route.js +19 -6
- package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/route.js +13 -4
- package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
- package/dist/modules/data_sync/api/validate.js +9 -4
- package/dist/modules/data_sync/api/validate.js.map +2 -2
- package/dist/modules/design_system/acl.js +9 -0
- package/dist/modules/design_system/acl.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.js +11 -0
- package/dist/modules/design_system/backend/design-system/page.js.map +7 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js +15 -0
- package/dist/modules/design_system/backend/design-system/page.meta.js.map +7 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js +52 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +7 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js +63 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js.map +7 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js +163 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js.map +7 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js +9 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/banners.js +186 -0
- package/dist/modules/design_system/gallery/entries/banners.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/buttons.js +361 -0
- package/dist/modules/design_system/gallery/entries/buttons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/charts.js +457 -0
- package/dist/modules/design_system/gallery/entries/charts.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/dates.js +306 -0
- package/dist/modules/design_system/gallery/entries/dates.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/detail.js +358 -0
- package/dist/modules/design_system/gallery/entries/detail.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/display.js +785 -0
- package/dist/modules/design_system/gallery/entries/display.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/feedback.js +658 -0
- package/dist/modules/design_system/gallery/entries/feedback.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/filters.js +505 -0
- package/dist/modules/design_system/gallery/entries/filters.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/foundations.js +453 -0
- package/dist/modules/design_system/gallery/entries/foundations.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/icons.js +140 -0
- package/dist/modules/design_system/gallery/entries/icons.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/inputs.js +1217 -0
- package/dist/modules/design_system/gallery/entries/inputs.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/messages.js +334 -0
- package/dist/modules/design_system/gallery/entries/messages.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/navigation.js +475 -0
- package/dist/modules/design_system/gallery/entries/navigation.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/notifications.js +257 -0
- package/dist/modules/design_system/gallery/entries/notifications.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/overlays.js +576 -0
- package/dist/modules/design_system/gallery/entries/overlays.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js +378 -0
- package/dist/modules/design_system/gallery/entries/scaffolding.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/schedule.js +297 -0
- package/dist/modules/design_system/gallery/entries/schedule.js.map +7 -0
- package/dist/modules/design_system/gallery/registry.js +139 -0
- package/dist/modules/design_system/gallery/registry.js.map +7 -0
- package/dist/modules/design_system/gallery/types.js +1 -0
- package/dist/modules/design_system/gallery/types.js.map +7 -0
- package/dist/modules/design_system/index.js +9 -0
- package/dist/modules/design_system/index.js.map +7 -0
- package/dist/modules/design_system/setup.js +14 -0
- package/dist/modules/design_system/setup.js.map +7 -0
- package/dist/modules/inbox_ops/search.js +15 -4
- package/dist/modules/inbox_ops/search.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +11 -5
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/health/route.js +6 -3
- package/dist/modules/integrations/api/[id]/health/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/route.js +6 -3
- package/dist/modules/integrations/api/[id]/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/state/route.js +6 -3
- package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/version/route.js +6 -3
- package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
- package/dist/modules/integrations/api/logs/route.js +6 -3
- package/dist/modules/integrations/api/logs/route.js.map +2 -2
- package/dist/modules/integrations/api/route.js +6 -3
- package/dist/modules/integrations/api/route.js.map +2 -2
- package/dist/modules/integrations/api/umes-read.js +2 -2
- package/dist/modules/integrations/api/umes-read.js.map +2 -2
- package/dist/modules/integrations/lib/organization-scope.js +2 -9
- package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
- package/dist/modules/messages/search.js +10 -5
- package/dist/modules/messages/search.js.map +2 -2
- package/dist/modules/query_index/data/entities.js +2 -1
- package/dist/modules/query_index/data/entities.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +32 -50
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js +17 -0
- package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js.map +7 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/package.json +16 -16
- package/src/modules/auth/backend/settings/page.tsx +17 -8
- package/src/modules/customers/cli.ts +17 -7
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +24 -13
- package/src/modules/customers/i18n/de.json +17 -0
- package/src/modules/customers/i18n/en.json +17 -0
- package/src/modules/customers/i18n/es.json +17 -0
- package/src/modules/customers/i18n/pl.json +17 -0
- package/src/modules/customers/search.ts +59 -27
- package/src/modules/data_sync/AGENTS.md +1 -0
- package/src/modules/data_sync/api/mappings/[id]/route.ts +22 -9
- package/src/modules/data_sync/api/mappings/route.ts +13 -4
- package/src/modules/data_sync/api/options.ts +7 -2
- package/src/modules/data_sync/api/run.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +8 -3
- package/src/modules/data_sync/api/runs/[id]/retry.ts +7 -2
- package/src/modules/data_sync/api/runs/[id]/route.ts +8 -3
- package/src/modules/data_sync/api/runs.ts +7 -2
- package/src/modules/data_sync/api/schedules/[id]/route.ts +19 -6
- package/src/modules/data_sync/api/schedules/route.ts +13 -4
- package/src/modules/data_sync/api/validate.ts +9 -4
- package/src/modules/design_system/AGENTS.md +34 -0
- package/src/modules/design_system/acl.ts +5 -0
- package/src/modules/design_system/backend/design-system/page.meta.ts +11 -0
- package/src/modules/design_system/backend/design-system/page.tsx +14 -0
- package/src/modules/design_system/gallery/components/CodeSnippet.tsx +55 -0
- package/src/modules/design_system/gallery/components/EntryCard.tsx +95 -0
- package/src/modules/design_system/gallery/components/GalleryShell.tsx +206 -0
- package/src/modules/design_system/gallery/components/VariantPreview.tsx +15 -0
- package/src/modules/design_system/gallery/entries/banners.tsx +226 -0
- package/src/modules/design_system/gallery/entries/buttons.tsx +422 -0
- package/src/modules/design_system/gallery/entries/charts.tsx +518 -0
- package/src/modules/design_system/gallery/entries/dates.tsx +325 -0
- package/src/modules/design_system/gallery/entries/detail.tsx +403 -0
- package/src/modules/design_system/gallery/entries/display.tsx +893 -0
- package/src/modules/design_system/gallery/entries/feedback.tsx +746 -0
- package/src/modules/design_system/gallery/entries/filters.tsx +570 -0
- package/src/modules/design_system/gallery/entries/foundations.tsx +529 -0
- package/src/modules/design_system/gallery/entries/icons.tsx +168 -0
- package/src/modules/design_system/gallery/entries/inputs.tsx +1516 -0
- package/src/modules/design_system/gallery/entries/messages.tsx +339 -0
- package/src/modules/design_system/gallery/entries/navigation.tsx +573 -0
- package/src/modules/design_system/gallery/entries/notifications.tsx +285 -0
- package/src/modules/design_system/gallery/entries/overlays.tsx +677 -0
- package/src/modules/design_system/gallery/entries/scaffolding.tsx +430 -0
- package/src/modules/design_system/gallery/entries/schedule.tsx +307 -0
- package/src/modules/design_system/gallery/registry.ts +152 -0
- package/src/modules/design_system/gallery/types.ts +32 -0
- package/src/modules/design_system/i18n/.hardcoded-allowlist.json +71 -0
- package/src/modules/design_system/i18n/de.json +46 -0
- package/src/modules/design_system/i18n/en.json +46 -0
- package/src/modules/design_system/i18n/es.json +46 -0
- package/src/modules/design_system/i18n/pl.json +46 -0
- package/src/modules/design_system/index.ts +7 -0
- package/src/modules/design_system/setup.ts +12 -0
- package/src/modules/inbox_ops/i18n/de.json +3 -0
- package/src/modules/inbox_ops/i18n/en.json +3 -0
- package/src/modules/inbox_ops/i18n/es.json +3 -0
- package/src/modules/inbox_ops/i18n/pl.json +3 -0
- package/src/modules/inbox_ops/search.ts +20 -4
- package/src/modules/integrations/api/[id]/credentials/route.ts +11 -5
- package/src/modules/integrations/api/[id]/health/route.ts +6 -3
- package/src/modules/integrations/api/[id]/route.ts +6 -3
- package/src/modules/integrations/api/[id]/state/route.ts +6 -3
- package/src/modules/integrations/api/[id]/version/route.ts +6 -3
- package/src/modules/integrations/api/logs/route.ts +6 -3
- package/src/modules/integrations/api/route.ts +6 -3
- package/src/modules/integrations/api/umes-read.ts +2 -2
- package/src/modules/integrations/lib/organization-scope.ts +5 -25
- package/src/modules/messages/i18n/de.json +2 -0
- package/src/modules/messages/i18n/en.json +2 -0
- package/src/modules/messages/i18n/es.json +2 -0
- package/src/modules/messages/i18n/pl.json +2 -0
- package/src/modules/messages/search.ts +11 -5
- package/src/modules/query_index/data/entities.ts +7 -0
- package/src/modules/query_index/lib/engine.ts +40 -63
- package/src/modules/query_index/migrations/.snapshot-open-mercato.json +12 -0
- package/src/modules/query_index/migrations/Migration20260731105052_query_index.ts +35 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"design_system.entries.button.description": "Disparador de acción principal con toda la escala de variantes y tamaños del DS.",
|
|
3
|
+
"design_system.entries.buttonGroup.description": "Grupo unido de botones de acción relacionados que comparten un borde.",
|
|
4
|
+
"design_system.entries.fancyButton.description": "Botón con degradado, de estilo promocional, para acciones destacadas.",
|
|
5
|
+
"design_system.entries.iconButton.description": "Botón cuadrado solo con icono; siempre requiere un aria-label.",
|
|
6
|
+
"design_system.entries.linkButton.description": "Enlace de texto con estilo de control del DS.",
|
|
7
|
+
"design_system.entries.socialButton.description": "Botón de autenticación con colores de marca para inicio de sesión social.",
|
|
8
|
+
"design_system.families.banners": "Avisos y llamadas",
|
|
9
|
+
"design_system.families.buttons": "Botones",
|
|
10
|
+
"design_system.families.charts": "Gráficos",
|
|
11
|
+
"design_system.families.dates": "Fechas y hora",
|
|
12
|
+
"design_system.families.detail": "Secciones de detalle",
|
|
13
|
+
"design_system.families.display": "Visualización de datos",
|
|
14
|
+
"design_system.families.feedback": "Retroalimentación",
|
|
15
|
+
"design_system.families.filters": "Filtros",
|
|
16
|
+
"design_system.families.foundations": "Fundamentos",
|
|
17
|
+
"design_system.families.icons": "Iconos",
|
|
18
|
+
"design_system.families.inputs": "Campos de formulario",
|
|
19
|
+
"design_system.families.messages": "Mensajes",
|
|
20
|
+
"design_system.families.navigation": "Navegación",
|
|
21
|
+
"design_system.families.notifications": "Notificaciones",
|
|
22
|
+
"design_system.families.overlays": "Superposiciones",
|
|
23
|
+
"design_system.families.scaffolding": "Estructura de página",
|
|
24
|
+
"design_system.families.schedule": "Agenda",
|
|
25
|
+
"design_system.gallery.copied": "Fragmento copiado al portapapeles",
|
|
26
|
+
"design_system.gallery.copy": "Copiar código",
|
|
27
|
+
"design_system.gallery.copyFailed": "No se pudo copiar el fragmento",
|
|
28
|
+
"design_system.gallery.familiesGroup": "Familias",
|
|
29
|
+
"design_system.gallery.familyContents": "Componentes de esta familia",
|
|
30
|
+
"design_system.gallery.iconCopied": "Copiado: {snippet}",
|
|
31
|
+
"design_system.gallery.iconCopyJsx": "Copiar JSX (lucide-react)",
|
|
32
|
+
"design_system.gallery.iconCopyMeta": "Copiar nombre para page.meta icon",
|
|
33
|
+
"design_system.gallery.iconCountAll": "{total} iconos",
|
|
34
|
+
"design_system.gallery.iconCountFiltered": "{visible} de {total} iconos",
|
|
35
|
+
"design_system.gallery.iconSearchPlaceholder": "Filtrar iconos…",
|
|
36
|
+
"design_system.gallery.loadFailed": "No se pudo cargar esta familia",
|
|
37
|
+
"design_system.gallery.noResults": "Ningún componente coincide con la búsqueda",
|
|
38
|
+
"design_system.gallery.openInFigma": "Abrir en Figma",
|
|
39
|
+
"design_system.gallery.retry": "Reintentar",
|
|
40
|
+
"design_system.gallery.searchPlaceholder": "Buscar componentes…",
|
|
41
|
+
"design_system.gallery.usageDo": "Haz",
|
|
42
|
+
"design_system.gallery.usageDont": "Evita",
|
|
43
|
+
"design_system.gallery.viewDocs": "Ver documentación",
|
|
44
|
+
"design_system.nav.group": "Desarrollador",
|
|
45
|
+
"design_system.nav.title": "Sistema de diseño"
|
|
46
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"design_system.entries.button.description": "Podstawowy przycisk akcji z pełną skalą wariantów i rozmiarów DS.",
|
|
3
|
+
"design_system.entries.buttonGroup.description": "Połączona grupa powiązanych przycisków akcji ze wspólnym obramowaniem.",
|
|
4
|
+
"design_system.entries.fancyButton.description": "Gradientowy przycisk o marketingowym charakterze dla wyróżnionych akcji.",
|
|
5
|
+
"design_system.entries.iconButton.description": "Kwadratowy przycisk z samą ikoną; zawsze wymaga aria-label.",
|
|
6
|
+
"design_system.entries.linkButton.description": "Tekstowy odnośnik w stylu kontrolki DS.",
|
|
7
|
+
"design_system.entries.socialButton.description": "Przycisk logowania w kolorach marki dla logowania społecznościowego.",
|
|
8
|
+
"design_system.families.banners": "Banery i wskazówki",
|
|
9
|
+
"design_system.families.buttons": "Przyciski",
|
|
10
|
+
"design_system.families.charts": "Wykresy",
|
|
11
|
+
"design_system.families.dates": "Daty i czas",
|
|
12
|
+
"design_system.families.detail": "Sekcje szczegółów",
|
|
13
|
+
"design_system.families.display": "Prezentacja danych",
|
|
14
|
+
"design_system.families.feedback": "Informacje zwrotne",
|
|
15
|
+
"design_system.families.filters": "Filtry",
|
|
16
|
+
"design_system.families.foundations": "Fundamenty",
|
|
17
|
+
"design_system.families.icons": "Ikony",
|
|
18
|
+
"design_system.families.inputs": "Pola formularzy",
|
|
19
|
+
"design_system.families.messages": "Wiadomości",
|
|
20
|
+
"design_system.families.navigation": "Nawigacja",
|
|
21
|
+
"design_system.families.notifications": "Powiadomienia",
|
|
22
|
+
"design_system.families.overlays": "Nakładki",
|
|
23
|
+
"design_system.families.scaffolding": "Szkielet strony",
|
|
24
|
+
"design_system.families.schedule": "Harmonogram",
|
|
25
|
+
"design_system.gallery.copied": "Fragment skopiowany do schowka",
|
|
26
|
+
"design_system.gallery.copy": "Kopiuj kod",
|
|
27
|
+
"design_system.gallery.copyFailed": "Nie udało się skopiować fragmentu",
|
|
28
|
+
"design_system.gallery.familiesGroup": "Rodziny",
|
|
29
|
+
"design_system.gallery.familyContents": "Komponenty w tej rodzinie",
|
|
30
|
+
"design_system.gallery.iconCopied": "Skopiowano: {snippet}",
|
|
31
|
+
"design_system.gallery.iconCopyJsx": "Kopiuj JSX (lucide-react)",
|
|
32
|
+
"design_system.gallery.iconCopyMeta": "Kopiuj nazwę do page.meta icon",
|
|
33
|
+
"design_system.gallery.iconCountAll": "Ikony: {total}",
|
|
34
|
+
"design_system.gallery.iconCountFiltered": "{visible} z {total} ikon",
|
|
35
|
+
"design_system.gallery.iconSearchPlaceholder": "Filtruj ikony…",
|
|
36
|
+
"design_system.gallery.loadFailed": "Nie udało się załadować tej rodziny",
|
|
37
|
+
"design_system.gallery.noResults": "Żaden komponent nie pasuje do wyszukiwania",
|
|
38
|
+
"design_system.gallery.openInFigma": "Otwórz w Figmie",
|
|
39
|
+
"design_system.gallery.retry": "Spróbuj ponownie",
|
|
40
|
+
"design_system.gallery.searchPlaceholder": "Szukaj komponentów…",
|
|
41
|
+
"design_system.gallery.usageDo": "Rób",
|
|
42
|
+
"design_system.gallery.usageDont": "Unikaj",
|
|
43
|
+
"design_system.gallery.viewDocs": "Zobacz dokumentację",
|
|
44
|
+
"design_system.nav.group": "Deweloper",
|
|
45
|
+
"design_system.nav.title": "Design system"
|
|
46
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
2
|
+
|
|
3
|
+
export const setup: ModuleSetupConfig = {
|
|
4
|
+
defaultRoleFeatures: {
|
|
5
|
+
// View-only module: the gallery reads no tenant data, so the grant is safe
|
|
6
|
+
// to hand out broadly. Superadmin is covered by wildcard grants.
|
|
7
|
+
admin: ['design_system.view'],
|
|
8
|
+
employee: ['design_system.view'],
|
|
9
|
+
},
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default setup
|
|
@@ -162,6 +162,9 @@
|
|
|
162
162
|
"inbox_ops.reply.send": "Antwort senden",
|
|
163
163
|
"inbox_ops.reply.sending": "Wird gesendet...",
|
|
164
164
|
"inbox_ops.reply.sent_success": "Antwort erfolgreich gesendet",
|
|
165
|
+
"inbox_ops.search.fallback.title": "Posteingang-Vorschlag",
|
|
166
|
+
"inbox_ops.search.subtitle.template": "Konfidenz: {{confidence}} · Status: {{status}}",
|
|
167
|
+
"inbox_ops.search.subtitle.templateWithCategory": "Konfidenz: {{confidence}} · Status: {{status}} · Kategorie: {{category}}",
|
|
165
168
|
"inbox_ops.sender_unknown": "Unbekannt",
|
|
166
169
|
"inbox_ops.settings.active": "Aktiv",
|
|
167
170
|
"inbox_ops.settings.copied": "Kopiert",
|
|
@@ -162,6 +162,9 @@
|
|
|
162
162
|
"inbox_ops.reply.send": "Send Reply",
|
|
163
163
|
"inbox_ops.reply.sending": "Sending...",
|
|
164
164
|
"inbox_ops.reply.sent_success": "Reply sent successfully",
|
|
165
|
+
"inbox_ops.search.fallback.title": "Inbox Proposal",
|
|
166
|
+
"inbox_ops.search.subtitle.template": "Confidence: {{confidence}} · Status: {{status}}",
|
|
167
|
+
"inbox_ops.search.subtitle.templateWithCategory": "Confidence: {{confidence}} · Status: {{status}} · Category: {{category}}",
|
|
165
168
|
"inbox_ops.sender_unknown": "Unknown",
|
|
166
169
|
"inbox_ops.settings.active": "Active",
|
|
167
170
|
"inbox_ops.settings.copied": "Copied",
|
|
@@ -162,6 +162,9 @@
|
|
|
162
162
|
"inbox_ops.reply.send": "Enviar respuesta",
|
|
163
163
|
"inbox_ops.reply.sending": "Enviando...",
|
|
164
164
|
"inbox_ops.reply.sent_success": "Respuesta enviada correctamente",
|
|
165
|
+
"inbox_ops.search.fallback.title": "Propuesta de bandeja",
|
|
166
|
+
"inbox_ops.search.subtitle.template": "Confianza: {{confidence}} · Estado: {{status}}",
|
|
167
|
+
"inbox_ops.search.subtitle.templateWithCategory": "Confianza: {{confidence}} · Estado: {{status}} · Categoría: {{category}}",
|
|
165
168
|
"inbox_ops.sender_unknown": "Desconocido",
|
|
166
169
|
"inbox_ops.settings.active": "Activo",
|
|
167
170
|
"inbox_ops.settings.copied": "Copiado",
|
|
@@ -162,6 +162,9 @@
|
|
|
162
162
|
"inbox_ops.reply.send": "Wy\u015blij odpowied\u017a",
|
|
163
163
|
"inbox_ops.reply.sending": "Wysy\u0142anie...",
|
|
164
164
|
"inbox_ops.reply.sent_success": "Odpowied\u017a wys\u0142ana pomy\u015blnie",
|
|
165
|
+
"inbox_ops.search.fallback.title": "Propozycja skrzynki",
|
|
166
|
+
"inbox_ops.search.subtitle.template": "Pewność: {{confidence}} · Status: {{status}}",
|
|
167
|
+
"inbox_ops.search.subtitle.templateWithCategory": "Pewność: {{confidence}} · Status: {{status}} · Kategoria: {{category}}",
|
|
165
168
|
"inbox_ops.sender_unknown": "Nieznany",
|
|
166
169
|
"inbox_ops.settings.active": "Aktywny",
|
|
167
170
|
"inbox_ops.settings.copied": "Skopiowano",
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
SearchResultPresenter,
|
|
5
5
|
SearchIndexSource,
|
|
6
6
|
} from '@open-mercato/shared/modules/search'
|
|
7
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
7
8
|
|
|
8
9
|
type SearchContext = SearchBuildContext & {
|
|
9
10
|
tenantId: string
|
|
@@ -30,6 +31,14 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
30
31
|
const record = ctx.record
|
|
31
32
|
if (!record.summary) return null
|
|
32
33
|
|
|
34
|
+
const { t } = await resolveTranslations()
|
|
35
|
+
const confidence = String(record.confidence ?? '')
|
|
36
|
+
const status = String(record.status ?? '')
|
|
37
|
+
const category = record.category ? String(record.category) : ''
|
|
38
|
+
const subtitle = category
|
|
39
|
+
? t('inbox_ops.search.subtitle.templateWithCategory', 'Confidence: {{confidence}} · Status: {{status}} · Category: {{category}}', { confidence, status, category })
|
|
40
|
+
: t('inbox_ops.search.subtitle.template', 'Confidence: {{confidence}} · Status: {{status}}', { confidence, status })
|
|
41
|
+
|
|
33
42
|
return {
|
|
34
43
|
text: String(record.summary || ''),
|
|
35
44
|
fields: {
|
|
@@ -39,8 +48,8 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
39
48
|
detected_language: record.detected_language,
|
|
40
49
|
},
|
|
41
50
|
presenter: {
|
|
42
|
-
title: String(record.summary || 'Inbox Proposal').slice(0, 80),
|
|
43
|
-
subtitle
|
|
51
|
+
title: String(record.summary || t('inbox_ops.search.fallback.title', 'Inbox Proposal')).slice(0, 80),
|
|
52
|
+
subtitle,
|
|
44
53
|
icon: 'inbox',
|
|
45
54
|
},
|
|
46
55
|
checksumSource: {
|
|
@@ -53,9 +62,16 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
53
62
|
}
|
|
54
63
|
},
|
|
55
64
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
65
|
+
const { t } = await resolveTranslations()
|
|
66
|
+
const confidence = String(ctx.record.confidence ?? '')
|
|
67
|
+
const status = String(ctx.record.status ?? '')
|
|
68
|
+
const category = ctx.record.category ? String(ctx.record.category) : ''
|
|
69
|
+
const subtitle = category
|
|
70
|
+
? t('inbox_ops.search.subtitle.templateWithCategory', 'Confidence: {{confidence}} · Status: {{status}} · Category: {{category}}', { confidence, status, category })
|
|
71
|
+
: t('inbox_ops.search.subtitle.template', 'Confidence: {{confidence}} · Status: {{status}}', { confidence, status })
|
|
56
72
|
return {
|
|
57
|
-
title: String(ctx.record.summary || 'Inbox Proposal').slice(0, 80),
|
|
58
|
-
subtitle
|
|
73
|
+
title: String(ctx.record.summary || t('inbox_ops.search.fallback.title', 'Inbox Proposal')).slice(0, 80),
|
|
74
|
+
subtitle,
|
|
59
75
|
icon: 'inbox',
|
|
60
76
|
}
|
|
61
77
|
},
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
runIntegrationMutationGuardAfterSuccess,
|
|
22
22
|
runIntegrationMutationGuards,
|
|
23
23
|
} from '../../guards'
|
|
24
|
-
import {
|
|
24
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
25
25
|
|
|
26
26
|
const idParamsSchema = z.object({ id: z.string().min(1) })
|
|
27
27
|
|
|
@@ -45,10 +45,13 @@ function resolveParams(ctx: { params?: Promise<{ id?: string }> | { id?: string
|
|
|
45
45
|
|
|
46
46
|
export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
47
47
|
const auth = await getAuthFromRequest(req)
|
|
48
|
-
|
|
49
|
-
if (!auth?.tenantId || !organizationId) {
|
|
48
|
+
if (!auth?.tenantId) {
|
|
50
49
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
51
50
|
}
|
|
51
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
52
|
+
if (!organizationId) {
|
|
53
|
+
return organizationScopeRequiredResponse()
|
|
54
|
+
}
|
|
52
55
|
|
|
53
56
|
const rawParams = await resolveParams(ctx)
|
|
54
57
|
const parsedParams = idParamsSchema.safeParse(rawParams)
|
|
@@ -91,10 +94,13 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
|
|
|
91
94
|
|
|
92
95
|
export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
93
96
|
const auth = await getAuthFromRequest(req)
|
|
94
|
-
|
|
95
|
-
if (!auth?.tenantId || !organizationId) {
|
|
97
|
+
if (!auth?.tenantId) {
|
|
96
98
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
97
99
|
}
|
|
100
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
101
|
+
if (!organizationId) {
|
|
102
|
+
return organizationScopeRequiredResponse()
|
|
103
|
+
}
|
|
98
104
|
|
|
99
105
|
const rawParams = await resolveParams(ctx)
|
|
100
106
|
const parsedParams = idParamsSchema.safeParse(rawParams)
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
runIntegrationMutationGuardAfterSuccess,
|
|
10
10
|
runIntegrationMutationGuards,
|
|
11
11
|
} from '../../guards'
|
|
12
|
-
import {
|
|
12
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
13
13
|
|
|
14
14
|
const idParamsSchema = z.object({ id: z.string().min(1) })
|
|
15
15
|
|
|
@@ -24,10 +24,13 @@ export const openApi = {
|
|
|
24
24
|
|
|
25
25
|
export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
26
26
|
const auth = await getAuthFromRequest(req)
|
|
27
|
-
|
|
28
|
-
if (!auth?.tenantId || !organizationId) {
|
|
27
|
+
if (!auth?.tenantId) {
|
|
29
28
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
30
29
|
}
|
|
30
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
31
|
+
if (!organizationId) {
|
|
32
|
+
return organizationScopeRequiredResponse()
|
|
33
|
+
}
|
|
31
34
|
|
|
32
35
|
const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
|
|
33
36
|
? await (ctx.params as Promise<{ id?: string }>)
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
integrationApiRoutePaths,
|
|
13
13
|
runIntegrationsReadBeforeInterceptors,
|
|
14
14
|
} from '../umes-read'
|
|
15
|
-
import {
|
|
15
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
16
16
|
|
|
17
17
|
const idParamsSchema = z.object({ id: z.string().min(1) })
|
|
18
18
|
|
|
@@ -27,10 +27,13 @@ export const openApi = {
|
|
|
27
27
|
|
|
28
28
|
export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
29
29
|
const auth = await getAuthFromRequest(req)
|
|
30
|
-
|
|
31
|
-
if (!auth?.tenantId || !organizationId) {
|
|
30
|
+
if (!auth?.tenantId) {
|
|
32
31
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
33
32
|
}
|
|
33
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
34
|
+
if (!organizationId) {
|
|
35
|
+
return organizationScopeRequiredResponse()
|
|
36
|
+
}
|
|
34
37
|
|
|
35
38
|
const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
|
|
36
39
|
? await (ctx.params as Promise<{ id?: string }>)
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
runIntegrationMutationGuardAfterSuccess,
|
|
14
14
|
runIntegrationMutationGuards,
|
|
15
15
|
} from '../../guards'
|
|
16
|
-
import {
|
|
16
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
17
17
|
|
|
18
18
|
const idParamsSchema = z.object({ id: z.string().min(1) })
|
|
19
19
|
|
|
@@ -28,10 +28,13 @@ export const openApi = {
|
|
|
28
28
|
|
|
29
29
|
export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
30
30
|
const auth = await getAuthFromRequest(req)
|
|
31
|
-
|
|
32
|
-
if (!auth?.tenantId || !organizationId) {
|
|
31
|
+
if (!auth?.tenantId) {
|
|
33
32
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
34
33
|
}
|
|
34
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
35
|
+
if (!organizationId) {
|
|
36
|
+
return organizationScopeRequiredResponse()
|
|
37
|
+
}
|
|
35
38
|
|
|
36
39
|
const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
|
|
37
40
|
? await (ctx.params as Promise<{ id?: string }>)
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
runIntegrationMutationGuardAfterSuccess,
|
|
15
15
|
runIntegrationMutationGuards,
|
|
16
16
|
} from '../../guards'
|
|
17
|
-
import {
|
|
17
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
18
18
|
|
|
19
19
|
const idParamsSchema = z.object({ id: z.string().min(1) })
|
|
20
20
|
|
|
@@ -29,10 +29,13 @@ export const openApi = {
|
|
|
29
29
|
|
|
30
30
|
export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
|
|
31
31
|
const auth = await getAuthFromRequest(req)
|
|
32
|
-
|
|
33
|
-
if (!auth?.tenantId || !organizationId) {
|
|
32
|
+
if (!auth?.tenantId) {
|
|
34
33
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
35
34
|
}
|
|
35
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
36
|
+
if (!organizationId) {
|
|
37
|
+
return organizationScopeRequiredResponse()
|
|
38
|
+
}
|
|
36
39
|
|
|
37
40
|
const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
|
|
38
41
|
? await (ctx.params as Promise<{ id?: string }>)
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
integrationApiRoutePaths,
|
|
9
9
|
runIntegrationsReadBeforeInterceptors,
|
|
10
10
|
} from '../umes-read'
|
|
11
|
-
import {
|
|
11
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
12
12
|
|
|
13
13
|
export const metadata = {
|
|
14
14
|
GET: { requireAuth: true, requireFeatures: ['integrations.manage'] },
|
|
@@ -21,10 +21,13 @@ export const openApi = {
|
|
|
21
21
|
|
|
22
22
|
export async function GET(req: Request) {
|
|
23
23
|
const auth = await getAuthFromRequest(req)
|
|
24
|
-
|
|
25
|
-
if (!auth?.tenantId || !organizationId) {
|
|
24
|
+
if (!auth?.tenantId) {
|
|
26
25
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
27
26
|
}
|
|
27
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
28
|
+
if (!organizationId) {
|
|
29
|
+
return organizationScopeRequiredResponse()
|
|
30
|
+
}
|
|
28
31
|
|
|
29
32
|
const container = await createRequestContainer()
|
|
30
33
|
const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
integrationApiRoutePaths,
|
|
15
15
|
runIntegrationsReadBeforeInterceptors,
|
|
16
16
|
} from './umes-read'
|
|
17
|
-
import {
|
|
17
|
+
import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
18
18
|
|
|
19
19
|
export const metadata = {
|
|
20
20
|
GET: { requireAuth: true, requireFeatures: ['integrations.view'] },
|
|
@@ -47,10 +47,13 @@ function matchesSearchQuery(
|
|
|
47
47
|
|
|
48
48
|
export async function GET(req: Request) {
|
|
49
49
|
const auth = await getAuthFromRequest(req)
|
|
50
|
-
|
|
51
|
-
if (!auth?.tenantId || !organizationId) {
|
|
50
|
+
if (!auth?.tenantId) {
|
|
52
51
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
53
52
|
}
|
|
53
|
+
const organizationId = resolveActiveOrganizationId(auth)
|
|
54
|
+
if (!organizationId) {
|
|
55
|
+
return organizationScopeRequiredResponse()
|
|
56
|
+
}
|
|
54
57
|
|
|
55
58
|
const url = new URL(req.url)
|
|
56
59
|
const parsedQuery = listIntegrationsQuerySchema.safeParse(Object.fromEntries(url.searchParams.entries()))
|
|
@@ -4,7 +4,7 @@ import type { AwilixContainer } from 'awilix'
|
|
|
4
4
|
import { runApiInterceptorsAfter, runApiInterceptorsBefore, type RunInterceptorsBeforeResult } from '@open-mercato/shared/lib/crud/interceptor-runner'
|
|
5
5
|
import { applyResponseEnrichers, applyResponseEnricherToRecord } from '@open-mercato/shared/lib/crud/enricher-runner'
|
|
6
6
|
import type { ApiInterceptorMethod, InterceptorRequest } from '@open-mercato/shared/lib/crud/api-interceptor'
|
|
7
|
-
import {
|
|
7
|
+
import { resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
8
8
|
|
|
9
9
|
export const integrationApiRoutePaths = {
|
|
10
10
|
list: 'integrations',
|
|
@@ -67,7 +67,7 @@ function mergeAdditiveBody(
|
|
|
67
67
|
|
|
68
68
|
function getEnricherContext(input: ReadRouteContext) {
|
|
69
69
|
return {
|
|
70
|
-
organizationId:
|
|
70
|
+
organizationId: resolveActiveOrganizationId(input.auth) as string,
|
|
71
71
|
tenantId: input.auth.tenantId as string,
|
|
72
72
|
userId: input.auth.sub ?? '',
|
|
73
73
|
em: input.container.resolve('em') as EntityManager,
|
|
@@ -1,27 +1,7 @@
|
|
|
1
|
-
type OrganizationScopedAuth = {
|
|
2
|
-
orgId?: string | null
|
|
3
|
-
actorOrgId?: unknown
|
|
4
|
-
} | null | undefined
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* meaningful "all organizations" view of this module. When an operator selects that
|
|
12
|
-
* option the super-admin cookie override clears `auth.orgId` and preserves the actor's
|
|
13
|
-
* own organization in `actorOrgId`; fall back to it so the module keeps showing the
|
|
14
|
-
* operator's own configuration instead of failing.
|
|
15
|
-
*
|
|
16
|
-
* Answering 401 for that case is not merely wrong but self-perpetuating: `apiFetch`
|
|
17
|
-
* reads 401 as an expired session and redirects through `/api/auth/session/refresh`,
|
|
18
|
-
* which succeeds and returns to the same page, reloading forever.
|
|
2
|
+
* @deprecated Moved to `@open-mercato/shared/lib/auth/organizationScope` as
|
|
3
|
+
* `resolveActiveOrganizationId`, because `data_sync` needs the same resolution and
|
|
4
|
+
* `integrations` is not the right owner for it. This alias stays for third-party
|
|
5
|
+
* modules that already import from here.
|
|
19
6
|
*/
|
|
20
|
-
export
|
|
21
|
-
if (!auth) return null
|
|
22
|
-
const selected = auth.orgId
|
|
23
|
-
if (typeof selected === 'string' && selected.trim().length > 0) return selected
|
|
24
|
-
const actorOrgId = auth.actorOrgId
|
|
25
|
-
if (typeof actorOrgId === 'string' && actorOrgId.trim().length > 0) return actorOrgId
|
|
26
|
-
return null
|
|
27
|
-
}
|
|
7
|
+
export { resolveActiveOrganizationId as resolveIntegrationsOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
|
|
@@ -213,6 +213,8 @@
|
|
|
213
213
|
"messages.replyBody": "Antwort",
|
|
214
214
|
"messages.saveDraft": "Entwurf speichern",
|
|
215
215
|
"messages.savingDraft": "Entwurf wird gespeichert...",
|
|
216
|
+
"messages.search.badge.message": "Nachricht",
|
|
217
|
+
"messages.search.fallback.title": "Nachricht",
|
|
216
218
|
"messages.searchPlaceholder": "Nachrichten suchen",
|
|
217
219
|
"messages.send": "Senden",
|
|
218
220
|
"messages.sendViaEmail": "Auch per E-Mail senden",
|
|
@@ -213,6 +213,8 @@
|
|
|
213
213
|
"messages.replyBody": "Reply",
|
|
214
214
|
"messages.saveDraft": "Save draft",
|
|
215
215
|
"messages.savingDraft": "Saving draft...",
|
|
216
|
+
"messages.search.badge.message": "Message",
|
|
217
|
+
"messages.search.fallback.title": "Message",
|
|
216
218
|
"messages.searchPlaceholder": "Search messages",
|
|
217
219
|
"messages.send": "Send",
|
|
218
220
|
"messages.sendViaEmail": "Also send via email",
|
|
@@ -213,6 +213,8 @@
|
|
|
213
213
|
"messages.replyBody": "Respuesta",
|
|
214
214
|
"messages.saveDraft": "Guardar borrador",
|
|
215
215
|
"messages.savingDraft": "Guardando borrador...",
|
|
216
|
+
"messages.search.badge.message": "Mensaje",
|
|
217
|
+
"messages.search.fallback.title": "Mensaje",
|
|
216
218
|
"messages.searchPlaceholder": "Buscar mensajes",
|
|
217
219
|
"messages.send": "Enviar",
|
|
218
220
|
"messages.sendViaEmail": "Enviar también por correo",
|
|
@@ -213,6 +213,8 @@
|
|
|
213
213
|
"messages.replyBody": "Odpowiedź",
|
|
214
214
|
"messages.saveDraft": "Zapisz szkic",
|
|
215
215
|
"messages.savingDraft": "Zapisywanie szkicu...",
|
|
216
|
+
"messages.search.badge.message": "Wiadomość",
|
|
217
|
+
"messages.search.fallback.title": "Wiadomość",
|
|
216
218
|
"messages.searchPlaceholder": "Szukaj wiadomości",
|
|
217
219
|
"messages.send": "Wyślij",
|
|
218
220
|
"messages.sendViaEmail": "Wyślij także e-mailem",
|
|
@@ -4,6 +4,8 @@ import type {
|
|
|
4
4
|
SearchIndexSource,
|
|
5
5
|
SearchResultPresenter,
|
|
6
6
|
} from '@open-mercato/shared/modules/search'
|
|
7
|
+
import type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'
|
|
8
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
7
9
|
|
|
8
10
|
function appendLine(lines: string[], label: string, value: unknown) {
|
|
9
11
|
if (value === null || value === undefined) return
|
|
@@ -31,8 +33,8 @@ function snippet(value: unknown, max = 140): string | undefined {
|
|
|
31
33
|
return `${trimmed.slice(0, max - 3)}...`
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
function buildMessagePresenter(record: Record<string, unknown>): SearchResultPresenter {
|
|
35
|
-
const title = pickString(record.subject) ?? 'Message'
|
|
36
|
+
function buildMessagePresenter(translate: TranslateFn, record: Record<string, unknown>): SearchResultPresenter {
|
|
37
|
+
const title = pickString(record.subject) ?? translate('messages.search.fallback.title', 'Message')
|
|
36
38
|
const body = snippet(record.body)
|
|
37
39
|
const externalName = pickString(record.external_name, record.externalName)
|
|
38
40
|
const subtitle = [externalName, body].filter(Boolean).join(' · ') || undefined
|
|
@@ -40,7 +42,7 @@ function buildMessagePresenter(record: Record<string, unknown>): SearchResultPre
|
|
|
40
42
|
title: String(title),
|
|
41
43
|
subtitle,
|
|
42
44
|
icon: 'mail',
|
|
43
|
-
badge: 'Message',
|
|
45
|
+
badge: translate('messages.search.badge.message', 'Message'),
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
@@ -51,6 +53,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
51
53
|
enabled: true,
|
|
52
54
|
priority: 5,
|
|
53
55
|
buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {
|
|
56
|
+
const { t } = await resolveTranslations()
|
|
54
57
|
const record = ctx.record
|
|
55
58
|
const lines: string[] = []
|
|
56
59
|
appendLine(lines, 'Subject', record.subject)
|
|
@@ -59,7 +62,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
59
62
|
if (!lines.length) return null
|
|
60
63
|
return {
|
|
61
64
|
text: lines,
|
|
62
|
-
presenter: buildMessagePresenter(record),
|
|
65
|
+
presenter: buildMessagePresenter(t, record),
|
|
63
66
|
checksumSource: {
|
|
64
67
|
record: {
|
|
65
68
|
subject: record.subject,
|
|
@@ -70,7 +73,10 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
70
73
|
},
|
|
71
74
|
}
|
|
72
75
|
},
|
|
73
|
-
formatResult: async (ctx) =>
|
|
76
|
+
formatResult: async (ctx) => {
|
|
77
|
+
const { t } = await resolveTranslations()
|
|
78
|
+
return buildMessagePresenter(t, ctx.record)
|
|
79
|
+
},
|
|
74
80
|
resolveUrl: async (ctx) => {
|
|
75
81
|
const id = pickString(ctx.record.id)
|
|
76
82
|
return id ? `/backend/messages/${encodeURIComponent(id)}` : null
|
|
@@ -255,6 +255,13 @@ export class IndexerStatusLog {
|
|
|
255
255
|
@Index({ name: 'search_tokens_lookup_idx', properties: ['entityType', 'field', 'tokenHash', 'tenantId', 'organizationId'] })
|
|
256
256
|
@Index({ name: 'search_tokens_entity_idx', properties: ['entityType', 'entityId'] })
|
|
257
257
|
@Index({ name: 'search_tokens_tenant_token_hash_idx', properties: ['tenantId', 'tokenHash'] })
|
|
258
|
+
// Serves the availability probe ("does this scope have any tokens?") as a pure
|
|
259
|
+
// B-tree prefix seek, making the MISS as cheap as the hit — neither existing
|
|
260
|
+
// index can (lookup_idx buries tenant_id behind field/token_hash), which is how
|
|
261
|
+
// the probe degraded to a seq scan on large tables (#4723). Requires the
|
|
262
|
+
// index-usable `= / IS NULL` predicates the availability resolver emits; see
|
|
263
|
+
// .ai/specs/2026-07-31-search-token-probe-index.md.
|
|
264
|
+
@Index({ name: 'search_tokens_presence_idx', properties: ['entityType', 'tenantId', 'organizationId'] })
|
|
258
265
|
export class SearchToken {
|
|
259
266
|
@PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
|
|
260
267
|
id!: string
|