@open-mercato/core 0.6.7-develop.6788.1.c2a1520a30 → 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/customers/cli.js +17 -7
- package/dist/modules/customers/cli.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/customers/cli.ts +17 -7
- 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,17 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260731105052_query_index extends Migration {
|
|
3
|
+
isTransactional() {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
up() {
|
|
7
|
+
this.addSql(`drop index concurrently if exists "search_tokens_presence_idx";`);
|
|
8
|
+
this.addSql(`create index concurrently "search_tokens_presence_idx" on "search_tokens" ("entity_type", "tenant_id", "organization_id");`);
|
|
9
|
+
}
|
|
10
|
+
down() {
|
|
11
|
+
this.addSql(`drop index concurrently if exists "search_tokens_presence_idx";`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
Migration20260731105052_query_index
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=Migration20260731105052_query_index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/query_index/migrations/Migration20260731105052_query_index.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\n// Availability-probe index (.ai/specs/2026-07-31-search-token-probe-index.md).\n// The query engines gate like/ilike routing on \"does (entity_type, tenant, org)\n// have any search tokens?\". Neither existing index serves that probe as an\n// access path \u2014 lookup_idx buries tenant_id behind field/token_hash \u2014 so on a\n// large search_tokens the planner degraded the probe to a seq scan and the MISS\n// answer had to exhaust every entry for the entity type (p95 12.5 s in\n// production, #4723). With this (entity_type, tenant_id, organization_id)\n// prefix and the index-usable `= / IS NULL` predicates the availability\n// resolver emits, both the hit AND the miss become a B-tree prefix seek.\n//\n// search_tokens is high-churn, so the index is built CONCURRENTLY to avoid\n// blocking writes during the build. CREATE INDEX CONCURRENTLY cannot run\n// inside a transaction, hence isTransactional() => false; the migration runner\n// applies migrations one-by-one, so this opt-out is safe (same pattern as\n// Migration20260611103000_query_index). Drop first so retrying a failed\n// concurrent build removes PostgreSQL's invalid index stub instead of letting\n// IF NOT EXISTS silently accept it.\nexport class Migration20260731105052_query_index extends Migration {\n\n override isTransactional(): boolean {\n return false;\n }\n\n override up(): void | Promise<void> {\n this.addSql(`drop index concurrently if exists \"search_tokens_presence_idx\";`);\n this.addSql(`create index concurrently \"search_tokens_presence_idx\" on \"search_tokens\" (\"entity_type\", \"tenant_id\", \"organization_id\");`);\n }\n\n override down(): void | Promise<void> {\n this.addSql(`drop index concurrently if exists \"search_tokens_presence_idx\";`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAmBnB,MAAM,4CAA4C,UAAU;AAAA,EAExD,kBAA2B;AAClC,WAAO;AAAA,EACT;AAAA,EAES,KAA2B;AAClC,SAAK,OAAO,iEAAiE;AAC7E,SAAK,OAAO,4HAA4H;AAAA,EAC1I;AAAA,EAES,OAA6B;AACpC,SAAK,OAAO,iEAAiE;AAAA,EAC/E;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.6.7-develop.
|
|
3
|
+
"version": "0.6.7-develop.6795.1.8a3f27921c",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -228,9 +228,9 @@
|
|
|
228
228
|
}
|
|
229
229
|
},
|
|
230
230
|
"dependencies": {
|
|
231
|
-
"@mikro-orm/core": "^7.1.
|
|
232
|
-
"@mikro-orm/decorators": "^7.1.
|
|
233
|
-
"@mikro-orm/postgresql": "^7.1.
|
|
231
|
+
"@mikro-orm/core": "^7.1.8",
|
|
232
|
+
"@mikro-orm/decorators": "^7.1.8",
|
|
233
|
+
"@mikro-orm/postgresql": "^7.1.8",
|
|
234
234
|
"@types/html-to-text": "^9.0.4",
|
|
235
235
|
"@types/leaflet": "^1.9.12",
|
|
236
236
|
"@types/leaflet.markercluster": "^1.5.5",
|
|
@@ -245,25 +245,25 @@
|
|
|
245
245
|
"leaflet.markercluster": "^1.5.3",
|
|
246
246
|
"mammoth": "^1.9.0",
|
|
247
247
|
"pdfjs-dist": "^6.1.200",
|
|
248
|
-
"resend": "^6.
|
|
249
|
-
"sanitize-html": "
|
|
248
|
+
"resend": "^6.18.1",
|
|
249
|
+
"sanitize-html": "2.17.5",
|
|
250
250
|
"semver": "^7.8.5",
|
|
251
251
|
"sharp": "^0.35.3",
|
|
252
|
-
"svix": "^1.
|
|
252
|
+
"svix": "^1.99.1",
|
|
253
253
|
"ts-pattern": "^5.0.0",
|
|
254
254
|
"zod": "^4.4.3"
|
|
255
255
|
},
|
|
256
256
|
"peerDependencies": {
|
|
257
|
-
"@open-mercato/ai-assistant": "0.6.7-develop.
|
|
258
|
-
"@open-mercato/shared": "0.6.7-develop.
|
|
259
|
-
"@open-mercato/ui": "0.6.7-develop.
|
|
257
|
+
"@open-mercato/ai-assistant": "0.6.7-develop.6795.1.8a3f27921c",
|
|
258
|
+
"@open-mercato/shared": "0.6.7-develop.6795.1.8a3f27921c",
|
|
259
|
+
"@open-mercato/ui": "0.6.7-develop.6795.1.8a3f27921c",
|
|
260
260
|
"react": "^19.0.0",
|
|
261
261
|
"react-dom": "^19.0.0"
|
|
262
262
|
},
|
|
263
263
|
"devDependencies": {
|
|
264
|
-
"@open-mercato/ai-assistant": "0.6.7-develop.
|
|
265
|
-
"@open-mercato/shared": "0.6.7-develop.
|
|
266
|
-
"@open-mercato/ui": "0.6.7-develop.
|
|
264
|
+
"@open-mercato/ai-assistant": "0.6.7-develop.6795.1.8a3f27921c",
|
|
265
|
+
"@open-mercato/shared": "0.6.7-develop.6795.1.8a3f27921c",
|
|
266
|
+
"@open-mercato/ui": "0.6.7-develop.6795.1.8a3f27921c",
|
|
267
267
|
"@testing-library/dom": "^10.4.1",
|
|
268
268
|
"@testing-library/jest-dom": "^6.9.1",
|
|
269
269
|
"@testing-library/react": "^16.3.1",
|
|
@@ -274,9 +274,9 @@
|
|
|
274
274
|
"chance": "^1.1.13",
|
|
275
275
|
"jest": "^30.4.2",
|
|
276
276
|
"jest-environment-jsdom": "^30.4.1",
|
|
277
|
-
"react": "19.2.
|
|
278
|
-
"react-dom": "19.2.
|
|
279
|
-
"ts-jest": "^29.4.
|
|
277
|
+
"react": "19.2.8",
|
|
278
|
+
"react-dom": "19.2.8",
|
|
279
|
+
"ts-jest": "^29.4.12",
|
|
280
280
|
"typescript": "7.0.2"
|
|
281
281
|
},
|
|
282
282
|
"publishConfig": {
|
|
@@ -12,6 +12,7 @@ import { E as CoreEntities } from '#generated/entities.ids.generated'
|
|
|
12
12
|
import { createProgressBar } from '@open-mercato/shared/lib/cli/progress'
|
|
13
13
|
import { buildIndexDocument, type IndexCustomFieldValue } from '@open-mercato/core/modules/query_index/lib/document'
|
|
14
14
|
import { parseBooleanToken } from '@open-mercato/shared/lib/boolean'
|
|
15
|
+
import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
15
16
|
import { resolveSearchConfig } from '@open-mercato/shared/lib/search/config'
|
|
16
17
|
import type { QueryEngine } from '@open-mercato/shared/lib/query/types'
|
|
17
18
|
import type { EntityId } from '@open-mercato/shared/modules/entities'
|
|
@@ -1396,13 +1397,22 @@ async function seedCustomerExamples(
|
|
|
1396
1397
|
)
|
|
1397
1398
|
)
|
|
1398
1399
|
if (exampleDealTitles.length > 0) {
|
|
1399
|
-
const
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1400
|
+
const exampleTitles = new Set(exampleDealTitles)
|
|
1401
|
+
const batchSize = 100
|
|
1402
|
+
let offset = 0
|
|
1403
|
+
while (true) {
|
|
1404
|
+
const existingDeals = await findWithDecryption(
|
|
1405
|
+
em,
|
|
1406
|
+
CustomerDeal,
|
|
1407
|
+
{ tenantId, organizationId },
|
|
1408
|
+
{ fields: ['title'], limit: batchSize, offset, orderBy: { id: 'asc' } },
|
|
1409
|
+
{ tenantId, organizationId },
|
|
1410
|
+
)
|
|
1411
|
+
if (existingDeals.some((deal) => typeof deal.title === 'string' && exampleTitles.has(deal.title))) {
|
|
1412
|
+
return false
|
|
1413
|
+
}
|
|
1414
|
+
if (existingDeals.length < batchSize) break
|
|
1415
|
+
offset += existingDeals.length
|
|
1406
1416
|
}
|
|
1407
1417
|
}
|
|
1408
1418
|
|
|
@@ -2651,6 +2651,23 @@
|
|
|
2651
2651
|
"customers.schedule.visibility": "Visibility",
|
|
2652
2652
|
"customers.schedule.visibility.public": "Public",
|
|
2653
2653
|
"customers.schedule.visibility.team": "Team only",
|
|
2654
|
+
"customers.search.badge.activity": "Aktivität",
|
|
2655
|
+
"customers.search.badge.company": "Unternehmen",
|
|
2656
|
+
"customers.search.badge.deal": "Deal",
|
|
2657
|
+
"customers.search.badge.person": "Person",
|
|
2658
|
+
"customers.search.fallback.activity": "Aktivität: {{type}}",
|
|
2659
|
+
"customers.search.fallback.activityUpdate": "Aktualisierung",
|
|
2660
|
+
"customers.search.fallback.company": "Unternehmen",
|
|
2661
|
+
"customers.search.fallback.customerNote": "Kundennotiz",
|
|
2662
|
+
"customers.search.fallback.customerTask": "Kundenaufgabe",
|
|
2663
|
+
"customers.search.fallback.deal": "Deal",
|
|
2664
|
+
"customers.search.fallback.person": "Person",
|
|
2665
|
+
"customers.search.link.edit": "Bearbeiten",
|
|
2666
|
+
"customers.search.link.openCompany": "Unternehmen öffnen",
|
|
2667
|
+
"customers.search.link.openDeal": "Deal öffnen",
|
|
2668
|
+
"customers.search.link.openPerson": "Person öffnen",
|
|
2669
|
+
"customers.search.link.openTodo": "Aufgabe öffnen",
|
|
2670
|
+
"customers.search.link.viewCustomer": "Kunde anzeigen",
|
|
2654
2671
|
"customers.tags.manage.addCategory": "Neue Kategorie",
|
|
2655
2672
|
"customers.tags.manage.addCategoryPlaceholder": "Kategoriename...",
|
|
2656
2673
|
"customers.tags.manage.addCategoryRequired": "Geben Sie zuerst einen Kategorienamen ein.",
|
|
@@ -2651,6 +2651,23 @@
|
|
|
2651
2651
|
"customers.schedule.visibility": "Visibility",
|
|
2652
2652
|
"customers.schedule.visibility.public": "Public",
|
|
2653
2653
|
"customers.schedule.visibility.team": "Team only",
|
|
2654
|
+
"customers.search.badge.activity": "Activity",
|
|
2655
|
+
"customers.search.badge.company": "Company",
|
|
2656
|
+
"customers.search.badge.deal": "Deal",
|
|
2657
|
+
"customers.search.badge.person": "Person",
|
|
2658
|
+
"customers.search.fallback.activity": "Activity: {{type}}",
|
|
2659
|
+
"customers.search.fallback.activityUpdate": "update",
|
|
2660
|
+
"customers.search.fallback.company": "Company",
|
|
2661
|
+
"customers.search.fallback.customerNote": "Customer note",
|
|
2662
|
+
"customers.search.fallback.customerTask": "Customer task",
|
|
2663
|
+
"customers.search.fallback.deal": "Deal",
|
|
2664
|
+
"customers.search.fallback.person": "Person",
|
|
2665
|
+
"customers.search.link.edit": "Edit",
|
|
2666
|
+
"customers.search.link.openCompany": "Open company",
|
|
2667
|
+
"customers.search.link.openDeal": "Open deal",
|
|
2668
|
+
"customers.search.link.openPerson": "Open person",
|
|
2669
|
+
"customers.search.link.openTodo": "Open todo",
|
|
2670
|
+
"customers.search.link.viewCustomer": "View customer",
|
|
2654
2671
|
"customers.tags.manage.addCategory": "New category",
|
|
2655
2672
|
"customers.tags.manage.addCategoryPlaceholder": "Category name...",
|
|
2656
2673
|
"customers.tags.manage.addCategoryRequired": "Enter a category name first.",
|
|
@@ -2651,6 +2651,23 @@
|
|
|
2651
2651
|
"customers.schedule.visibility": "Visibility",
|
|
2652
2652
|
"customers.schedule.visibility.public": "Public",
|
|
2653
2653
|
"customers.schedule.visibility.team": "Team only",
|
|
2654
|
+
"customers.search.badge.activity": "Actividad",
|
|
2655
|
+
"customers.search.badge.company": "Empresa",
|
|
2656
|
+
"customers.search.badge.deal": "Oportunidad",
|
|
2657
|
+
"customers.search.badge.person": "Persona",
|
|
2658
|
+
"customers.search.fallback.activity": "Actividad: {{type}}",
|
|
2659
|
+
"customers.search.fallback.activityUpdate": "actualización",
|
|
2660
|
+
"customers.search.fallback.company": "Empresa",
|
|
2661
|
+
"customers.search.fallback.customerNote": "Nota del cliente",
|
|
2662
|
+
"customers.search.fallback.customerTask": "Tarea del cliente",
|
|
2663
|
+
"customers.search.fallback.deal": "Oportunidad",
|
|
2664
|
+
"customers.search.fallback.person": "Persona",
|
|
2665
|
+
"customers.search.link.edit": "Editar",
|
|
2666
|
+
"customers.search.link.openCompany": "Abrir empresa",
|
|
2667
|
+
"customers.search.link.openDeal": "Abrir oportunidad",
|
|
2668
|
+
"customers.search.link.openPerson": "Abrir persona",
|
|
2669
|
+
"customers.search.link.openTodo": "Abrir tarea",
|
|
2670
|
+
"customers.search.link.viewCustomer": "Ver cliente",
|
|
2654
2671
|
"customers.tags.manage.addCategory": "Nueva categoría",
|
|
2655
2672
|
"customers.tags.manage.addCategoryPlaceholder": "Nombre de la categoría...",
|
|
2656
2673
|
"customers.tags.manage.addCategoryRequired": "Primero introduce un nombre de categoría.",
|
|
@@ -2651,6 +2651,23 @@
|
|
|
2651
2651
|
"customers.schedule.visibility": "Widoczność",
|
|
2652
2652
|
"customers.schedule.visibility.public": "Publiczny",
|
|
2653
2653
|
"customers.schedule.visibility.team": "Tylko zespół",
|
|
2654
|
+
"customers.search.badge.activity": "Aktywność",
|
|
2655
|
+
"customers.search.badge.company": "Firma",
|
|
2656
|
+
"customers.search.badge.deal": "Szansa sprzedaży",
|
|
2657
|
+
"customers.search.badge.person": "Osoba",
|
|
2658
|
+
"customers.search.fallback.activity": "Aktywność: {{type}}",
|
|
2659
|
+
"customers.search.fallback.activityUpdate": "aktualizacja",
|
|
2660
|
+
"customers.search.fallback.company": "Firma",
|
|
2661
|
+
"customers.search.fallback.customerNote": "Notatka klienta",
|
|
2662
|
+
"customers.search.fallback.customerTask": "Zadanie klienta",
|
|
2663
|
+
"customers.search.fallback.deal": "Szansa sprzedaży",
|
|
2664
|
+
"customers.search.fallback.person": "Osoba",
|
|
2665
|
+
"customers.search.link.edit": "Edytuj",
|
|
2666
|
+
"customers.search.link.openCompany": "Otwórz firmę",
|
|
2667
|
+
"customers.search.link.openDeal": "Otwórz szansę",
|
|
2668
|
+
"customers.search.link.openPerson": "Otwórz osobę",
|
|
2669
|
+
"customers.search.link.openTodo": "Otwórz zadanie",
|
|
2670
|
+
"customers.search.link.viewCustomer": "Zobacz klienta",
|
|
2654
2671
|
"customers.tags.manage.addCategory": "Nowa kategoria",
|
|
2655
2672
|
"customers.tags.manage.addCategoryPlaceholder": "Nazwa kategorii...",
|
|
2656
2673
|
"customers.tags.manage.addCategoryRequired": "Najpierw wpisz nazwę kategorii.",
|
|
@@ -6,6 +6,8 @@ import type {
|
|
|
6
6
|
SearchResultLink,
|
|
7
7
|
SearchIndexSource,
|
|
8
8
|
} from '@open-mercato/shared/modules/search'
|
|
9
|
+
import type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'
|
|
10
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
9
11
|
import { CUSTOMER_INTERACTION_TASK_SOURCE, EXAMPLE_TODO_SOURCE } from './lib/interactionCompatibility'
|
|
10
12
|
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
11
13
|
|
|
@@ -480,6 +482,7 @@ function ensureFallbackLines(lines: string[], record: Record<string, unknown>, o
|
|
|
480
482
|
// =============================================================================
|
|
481
483
|
|
|
482
484
|
function resolvePersonPresenter(
|
|
485
|
+
translate: TranslateFn,
|
|
483
486
|
record: Record<string, unknown>,
|
|
484
487
|
entity: Record<string, unknown> | null,
|
|
485
488
|
customFields: Record<string, unknown>,
|
|
@@ -495,7 +498,7 @@ function resolvePersonPresenter(
|
|
|
495
498
|
(nameParts.length ? nameParts : undefined) ??
|
|
496
499
|
fallbackEntityId ??
|
|
497
500
|
(record.id as string | undefined) ??
|
|
498
|
-
'Person'
|
|
501
|
+
translate('customers.search.fallback.person', 'Person')
|
|
499
502
|
const subtitlePieces: string[] = []
|
|
500
503
|
const jobTitle = record.job_title ?? record.jobTitle ?? customFields.job_title ?? customFields.jobTitle
|
|
501
504
|
if (jobTitle) subtitlePieces.push(String(jobTitle))
|
|
@@ -515,11 +518,14 @@ function resolvePersonPresenter(
|
|
|
515
518
|
title: String(title),
|
|
516
519
|
subtitle: subtitlePieces.length ? subtitlePieces.join(' · ') : undefined,
|
|
517
520
|
icon: 'user',
|
|
518
|
-
badge: pickValue(entity, 'display_name', 'displayName')
|
|
521
|
+
badge: pickValue(entity, 'display_name', 'displayName')
|
|
522
|
+
? translate('customers.search.badge.person', 'Person')
|
|
523
|
+
: undefined,
|
|
519
524
|
}
|
|
520
525
|
}
|
|
521
526
|
|
|
522
527
|
function resolveCompanyPresenter(
|
|
528
|
+
translate: TranslateFn,
|
|
523
529
|
record: Record<string, unknown>,
|
|
524
530
|
entity: Record<string, unknown> | null,
|
|
525
531
|
customFields: Record<string, unknown>,
|
|
@@ -537,7 +543,7 @@ function resolveCompanyPresenter(
|
|
|
537
543
|
(entity?.id && entity?.display_name ? entity.display_name as string : undefined) ??
|
|
538
544
|
fallbackEntityId ??
|
|
539
545
|
(record.id as string | undefined) ??
|
|
540
|
-
'Company'
|
|
546
|
+
translate('customers.search.fallback.company', 'Company')
|
|
541
547
|
const subtitlePieces: string[] = []
|
|
542
548
|
const industry = record.industry
|
|
543
549
|
if (industry) subtitlePieces.push(String(industry))
|
|
@@ -567,7 +573,9 @@ function resolveCompanyPresenter(
|
|
|
567
573
|
title: String(title),
|
|
568
574
|
subtitle: subtitlePieces.length ? subtitlePieces.join(' · ') : undefined,
|
|
569
575
|
icon: 'building',
|
|
570
|
-
badge: pickValue(entity, 'display_name', 'displayName')
|
|
576
|
+
badge: pickValue(entity, 'display_name', 'displayName')
|
|
577
|
+
? translate('customers.search.badge.company', 'Company')
|
|
578
|
+
: undefined,
|
|
571
579
|
}
|
|
572
580
|
}
|
|
573
581
|
|
|
@@ -605,6 +613,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
605
613
|
|
|
606
614
|
buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {
|
|
607
615
|
assertTenantContext(ctx)
|
|
616
|
+
const { t } = await resolveTranslations()
|
|
608
617
|
const lines: string[] = []
|
|
609
618
|
const record = ctx.record
|
|
610
619
|
appendLine(lines, 'Preferred name', record.preferred_name ?? record.preferredName ?? ctx.customFields.preferred_name)
|
|
@@ -643,9 +652,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
643
652
|
})
|
|
644
653
|
}
|
|
645
654
|
|
|
646
|
-
const presenter = resolvePersonPresenter(record, entity, ctx.customFields)
|
|
655
|
+
const presenter = resolvePersonPresenter(t, record, entity, ctx.customFields)
|
|
647
656
|
logMissingPresenterTitle('person', record, entity, presenter)
|
|
648
|
-
const presenterLabel = pickLabel(presenter.title) ?? 'Open person'
|
|
657
|
+
const presenterLabel = pickLabel(presenter.title) ?? t('customers.search.link.openPerson', 'Open person')
|
|
649
658
|
const links: SearchResultLink[] = []
|
|
650
659
|
if (entityId) {
|
|
651
660
|
const href = buildCustomerUrl('person', entityId)
|
|
@@ -669,8 +678,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
669
678
|
|
|
670
679
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
671
680
|
assertTenantContext(ctx)
|
|
681
|
+
const { t } = await resolveTranslations()
|
|
672
682
|
const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record))
|
|
673
|
-
return resolvePersonPresenter(ctx.record, entity, ctx.customFields)
|
|
683
|
+
return resolvePersonPresenter(t, ctx.record, entity, ctx.customFields)
|
|
674
684
|
},
|
|
675
685
|
|
|
676
686
|
resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {
|
|
@@ -679,11 +689,12 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
679
689
|
},
|
|
680
690
|
|
|
681
691
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
692
|
+
const { t } = await resolveTranslations()
|
|
682
693
|
const entityId = resolveCustomerEntityId(ctx.record)
|
|
683
694
|
if (!entityId) return null
|
|
684
695
|
const href = buildCustomerUrl('person', entityId)
|
|
685
696
|
if (!href) return null
|
|
686
|
-
return [{ href: `${href}/edit`, label: 'Edit', kind: 'secondary' }]
|
|
697
|
+
return [{ href: `${href}/edit`, label: t('customers.search.link.edit', 'Edit'), kind: 'secondary' }]
|
|
687
698
|
},
|
|
688
699
|
|
|
689
700
|
fieldPolicy: {
|
|
@@ -714,6 +725,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
714
725
|
|
|
715
726
|
buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {
|
|
716
727
|
assertTenantContext(ctx)
|
|
728
|
+
const { t } = await resolveTranslations()
|
|
717
729
|
const lines: string[] = []
|
|
718
730
|
const record = ctx.record
|
|
719
731
|
appendLine(lines, 'Legal name', record.legal_name ?? record.legalName ?? ctx.customFields.legal_name)
|
|
@@ -734,9 +746,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
734
746
|
ensureFallbackLines(lines, record)
|
|
735
747
|
if (!lines.length) return null
|
|
736
748
|
|
|
737
|
-
const presenter = resolveCompanyPresenter(record, entity, ctx.customFields)
|
|
749
|
+
const presenter = resolveCompanyPresenter(t, record, entity, ctx.customFields)
|
|
738
750
|
logMissingPresenterTitle('company', record, entity, presenter)
|
|
739
|
-
const primaryLabel = pickLabel(presenter.title) ?? 'Open company'
|
|
751
|
+
const primaryLabel = pickLabel(presenter.title) ?? t('customers.search.link.openCompany', 'Open company')
|
|
740
752
|
const links: SearchResultLink[] = []
|
|
741
753
|
if (entityId) {
|
|
742
754
|
const href = buildCustomerUrl('company', entityId)
|
|
@@ -760,8 +772,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
760
772
|
|
|
761
773
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
762
774
|
assertTenantContext(ctx)
|
|
775
|
+
const { t } = await resolveTranslations()
|
|
763
776
|
const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record))
|
|
764
|
-
return resolveCompanyPresenter(ctx.record, entity, ctx.customFields)
|
|
777
|
+
return resolveCompanyPresenter(t, ctx.record, entity, ctx.customFields)
|
|
765
778
|
},
|
|
766
779
|
|
|
767
780
|
resolveUrl: async (ctx: SearchBuildContext): Promise<string | null> => {
|
|
@@ -770,11 +783,12 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
770
783
|
},
|
|
771
784
|
|
|
772
785
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
786
|
+
const { t } = await resolveTranslations()
|
|
773
787
|
const entityId = resolveCustomerEntityId(ctx.record)
|
|
774
788
|
if (!entityId) return null
|
|
775
789
|
const href = buildCustomerUrl('company', entityId)
|
|
776
790
|
if (!href) return null
|
|
777
|
-
return [{ href: `${href}/edit`, label: 'Edit', kind: 'secondary' }]
|
|
791
|
+
return [{ href: `${href}/edit`, label: t('customers.search.link.edit', 'Edit'), kind: 'secondary' }]
|
|
778
792
|
},
|
|
779
793
|
|
|
780
794
|
fieldPolicy: {
|
|
@@ -832,8 +846,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
832
846
|
|
|
833
847
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
834
848
|
assertTenantContext(ctx)
|
|
849
|
+
const { t } = await resolveTranslations()
|
|
835
850
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
836
|
-
const title = (parent?.display_name as string | undefined) ?? 'Customer note'
|
|
851
|
+
const title = (parent?.display_name as string | undefined) ?? t('customers.search.fallback.customerNote', 'Customer note')
|
|
837
852
|
return {
|
|
838
853
|
title,
|
|
839
854
|
subtitle: snippet(ctx.record.body),
|
|
@@ -850,15 +865,16 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
850
865
|
|
|
851
866
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
852
867
|
assertTenantContext(ctx)
|
|
868
|
+
const { t } = await resolveTranslations()
|
|
853
869
|
const links: SearchResultLink[] = []
|
|
854
870
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
855
871
|
const parentUrl = buildCustomerUrl(parent?.kind as string ?? null, (parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId) as string)
|
|
856
872
|
if (parentUrl) {
|
|
857
|
-
links.push({ href: parentUrl, label: (parent?.display_name as string | undefined) ?? 'View customer', kind: 'primary' })
|
|
873
|
+
links.push({ href: parentUrl, label: (parent?.display_name as string | undefined) ?? t('customers.search.link.viewCustomer', 'View customer'), kind: 'primary' })
|
|
858
874
|
}
|
|
859
875
|
if (ctx.record.deal_id) {
|
|
860
876
|
const dealUrl = `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id as string)}`
|
|
861
|
-
links.push({ href: dealUrl, label: 'Open deal', kind: 'secondary' })
|
|
877
|
+
links.push({ href: dealUrl, label: t('customers.search.link.openDeal', 'Open deal'), kind: 'secondary' })
|
|
862
878
|
}
|
|
863
879
|
return links.length ? links : null
|
|
864
880
|
},
|
|
@@ -880,6 +896,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
880
896
|
priority: 8,
|
|
881
897
|
|
|
882
898
|
buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {
|
|
899
|
+
const { t } = await resolveTranslations()
|
|
883
900
|
const lines: string[] = []
|
|
884
901
|
const record = ctx.record
|
|
885
902
|
appendLine(lines, 'Title', record.title)
|
|
@@ -898,10 +915,10 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
898
915
|
return {
|
|
899
916
|
text: lines,
|
|
900
917
|
presenter: {
|
|
901
|
-
title: String(record.title ?? 'Deal'),
|
|
918
|
+
title: String(record.title ?? t('customers.search.fallback.deal', 'Deal')),
|
|
902
919
|
subtitle: subtitleParts.join(' · ') || undefined,
|
|
903
920
|
icon: 'briefcase',
|
|
904
|
-
badge: 'Deal',
|
|
921
|
+
badge: t('customers.search.badge.deal', 'Deal'),
|
|
905
922
|
},
|
|
906
923
|
checksumSource: {
|
|
907
924
|
title: record.title,
|
|
@@ -913,8 +930,9 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
913
930
|
},
|
|
914
931
|
|
|
915
932
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
933
|
+
const { t } = await resolveTranslations()
|
|
916
934
|
const { record } = ctx
|
|
917
|
-
const title = pickString(record.title as string, 'Deal')
|
|
935
|
+
const title = pickString(record.title as string, t('customers.search.fallback.deal', 'Deal'))
|
|
918
936
|
const subtitleParts: string[] = []
|
|
919
937
|
if (record.pipeline_stage) subtitleParts.push(String(record.pipeline_stage))
|
|
920
938
|
if (record.status) subtitleParts.push(String(record.status))
|
|
@@ -925,10 +943,10 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
925
943
|
}
|
|
926
944
|
|
|
927
945
|
return {
|
|
928
|
-
title: title ?? 'Deal',
|
|
946
|
+
title: title ?? t('customers.search.fallback.deal', 'Deal'),
|
|
929
947
|
subtitle: subtitleParts.length ? subtitleParts.join(' · ') : undefined,
|
|
930
948
|
icon: 'briefcase',
|
|
931
|
-
badge: 'Deal',
|
|
949
|
+
badge: t('customers.search.badge.deal', 'Deal'),
|
|
932
950
|
}
|
|
933
951
|
},
|
|
934
952
|
|
|
@@ -939,12 +957,13 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
939
957
|
},
|
|
940
958
|
|
|
941
959
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
960
|
+
const { t } = await resolveTranslations()
|
|
942
961
|
const id = ctx.record.id
|
|
943
962
|
if (!id) return null
|
|
944
963
|
return [
|
|
945
964
|
{
|
|
946
965
|
href: `/backend/customers/deals/${encodeURIComponent(String(id))}/edit`,
|
|
947
|
-
label: 'Edit',
|
|
966
|
+
label: t('customers.search.link.edit', 'Edit'),
|
|
948
967
|
kind: 'secondary',
|
|
949
968
|
},
|
|
950
969
|
]
|
|
@@ -968,6 +987,7 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
968
987
|
|
|
969
988
|
buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {
|
|
970
989
|
assertTenantContext(ctx)
|
|
990
|
+
const { t } = await resolveTranslations()
|
|
971
991
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
972
992
|
const lines: string[] = []
|
|
973
993
|
if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`)
|
|
@@ -976,7 +996,11 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
976
996
|
if (ctx.record.body) lines.push(`Body: ${ctx.record.body}`)
|
|
977
997
|
|
|
978
998
|
const presenter: SearchResultPresenter = {
|
|
979
|
-
title: ctx.record.subject
|
|
999
|
+
title: ctx.record.subject
|
|
1000
|
+
? String(ctx.record.subject)
|
|
1001
|
+
: t('customers.search.fallback.activity', 'Activity: {{type}}', {
|
|
1002
|
+
type: String(ctx.record.activity_type ?? t('customers.search.fallback.activityUpdate', 'update')),
|
|
1003
|
+
}),
|
|
980
1004
|
subtitle: (parent?.display_name as string | undefined) ?? snippet(ctx.record.body),
|
|
981
1005
|
icon: 'bolt',
|
|
982
1006
|
}
|
|
@@ -995,12 +1019,17 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
995
1019
|
|
|
996
1020
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
997
1021
|
assertTenantContext(ctx)
|
|
1022
|
+
const { t } = await resolveTranslations()
|
|
998
1023
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
999
1024
|
return {
|
|
1000
|
-
title: ctx.record.subject
|
|
1025
|
+
title: ctx.record.subject
|
|
1026
|
+
? String(ctx.record.subject)
|
|
1027
|
+
: t('customers.search.fallback.activity', 'Activity: {{type}}', {
|
|
1028
|
+
type: String(ctx.record.activity_type ?? t('customers.search.fallback.activityUpdate', 'update')),
|
|
1029
|
+
}),
|
|
1001
1030
|
subtitle: (parent?.display_name as string | undefined) ?? snippet(ctx.record.body),
|
|
1002
1031
|
icon: 'bolt',
|
|
1003
|
-
badge: 'Activity',
|
|
1032
|
+
badge: t('customers.search.badge.activity', 'Activity'),
|
|
1004
1033
|
}
|
|
1005
1034
|
},
|
|
1006
1035
|
|
|
@@ -1012,11 +1041,12 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
1012
1041
|
},
|
|
1013
1042
|
|
|
1014
1043
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
1044
|
+
const { t } = await resolveTranslations()
|
|
1015
1045
|
const links: SearchResultLink[] = []
|
|
1016
1046
|
if (ctx.record.deal_id) {
|
|
1017
1047
|
links.push({
|
|
1018
1048
|
href: `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id as string)}`,
|
|
1019
|
-
label: 'Open deal',
|
|
1049
|
+
label: t('customers.search.link.openDeal', 'Open deal'),
|
|
1020
1050
|
kind: 'secondary',
|
|
1021
1051
|
})
|
|
1022
1052
|
}
|
|
@@ -1064,10 +1094,11 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
1064
1094
|
|
|
1065
1095
|
formatResult: async (ctx: SearchBuildContext): Promise<SearchResultPresenter | null> => {
|
|
1066
1096
|
assertTenantContext(ctx)
|
|
1097
|
+
const { t } = await resolveTranslations()
|
|
1067
1098
|
const todo = await getLinkedTodo(ctx) as Record<string, unknown> | null
|
|
1068
1099
|
const parent = await getCustomerEntity(ctx, ctx.record.entity_id as string ?? ctx.record.entityId as string)
|
|
1069
1100
|
return {
|
|
1070
|
-
title: (todo?.title as string | undefined) ?? 'Customer task',
|
|
1101
|
+
title: (todo?.title as string | undefined) ?? t('customers.search.fallback.customerTask', 'Customer task'),
|
|
1071
1102
|
subtitle: parent?.display_name as string | undefined,
|
|
1072
1103
|
icon: 'check-square',
|
|
1073
1104
|
}
|
|
@@ -1081,11 +1112,12 @@ export const searchConfig: SearchModuleConfig = {
|
|
|
1081
1112
|
},
|
|
1082
1113
|
|
|
1083
1114
|
resolveLinks: async (ctx: SearchBuildContext): Promise<SearchResultLink[] | null> => {
|
|
1115
|
+
const { t } = await resolveTranslations()
|
|
1084
1116
|
const todoId = ctx.record.todo_id ?? ctx.record.todoId
|
|
1085
1117
|
if (!todoId) return null
|
|
1086
1118
|
return [{
|
|
1087
1119
|
href: `/backend/todos/${encodeURIComponent(todoId as string)}/edit`,
|
|
1088
|
-
label: 'Open todo',
|
|
1120
|
+
label: t('customers.search.link.openTodo', 'Open todo'),
|
|
1089
1121
|
kind: 'secondary',
|
|
1090
1122
|
}]
|
|
1091
1123
|
},
|
|
@@ -9,6 +9,7 @@ The `data_sync` module provides a streaming data synchronization hub for import/
|
|
|
9
9
|
## Always
|
|
10
10
|
|
|
11
11
|
- **Always scope by organizationId + tenantId** — every entity query
|
|
12
|
+
- **Resolve the organization in API routes with `resolveActiveOrganizationId(auth)`** from `@open-mercato/shared/lib/auth/organizationScope`, never with raw `auth.orgId` — a super-admin viewing "all organizations" has `auth.orgId === null`. The fallback is tenant-aware: it never pairs the actor organization with a foreign selected tenant. When it returns `null` for an authenticated caller, answer with `organizationScopeRequiredResponse()` (400) — never 401, which sends `apiFetch` into a session-refresh loop
|
|
12
13
|
- **Use the queue system** — never run syncs inline in API handlers
|
|
13
14
|
- **New sync providers MUST support provider-owned env preconfiguration** when fresh installs need credentials or default mappings/locales/channels from deployment env
|
|
14
15
|
- **Persist cursor after each batch** — enables resume on failure
|