@open-mercato/core 0.6.4-develop.4264.1.53368d85fe → 0.6.4-develop.4282.1.4d95e85930
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +12 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/fieldConfig.js +10 -0
- package/dist/modules/customers/components/detail/schedule/fieldConfig.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +2 -1
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/query_index/lib/coverage.js +13 -10
- package/dist/modules/query_index/lib/coverage.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +23 -12
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +7 -1
- package/src/modules/customers/components/detail/schedule/fieldConfig.ts +8 -1
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +1 -0
- package/src/modules/customers/i18n/de.json +5 -0
- package/src/modules/customers/i18n/en.json +5 -0
- package/src/modules/customers/i18n/es.json +5 -0
- package/src/modules/customers/i18n/pl.json +5 -0
- package/src/modules/query_index/lib/coverage.ts +15 -12
- package/src/modules/query_index/lib/engine.ts +32 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.6.4-develop.
|
|
3
|
+
"version": "0.6.4-develop.4282.1.4d95e85930",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -243,16 +243,16 @@
|
|
|
243
243
|
"zod": "^4.4.3"
|
|
244
244
|
},
|
|
245
245
|
"peerDependencies": {
|
|
246
|
-
"@open-mercato/ai-assistant": "0.6.4-develop.
|
|
247
|
-
"@open-mercato/shared": "0.6.4-develop.
|
|
248
|
-
"@open-mercato/ui": "0.6.4-develop.
|
|
246
|
+
"@open-mercato/ai-assistant": "0.6.4-develop.4282.1.4d95e85930",
|
|
247
|
+
"@open-mercato/shared": "0.6.4-develop.4282.1.4d95e85930",
|
|
248
|
+
"@open-mercato/ui": "0.6.4-develop.4282.1.4d95e85930",
|
|
249
249
|
"react": "^19.0.0",
|
|
250
250
|
"react-dom": "^19.0.0"
|
|
251
251
|
},
|
|
252
252
|
"devDependencies": {
|
|
253
|
-
"@open-mercato/ai-assistant": "0.6.4-develop.
|
|
254
|
-
"@open-mercato/shared": "0.6.4-develop.
|
|
255
|
-
"@open-mercato/ui": "0.6.4-develop.
|
|
253
|
+
"@open-mercato/ai-assistant": "0.6.4-develop.4282.1.4d95e85930",
|
|
254
|
+
"@open-mercato/shared": "0.6.4-develop.4282.1.4d95e85930",
|
|
255
|
+
"@open-mercato/ui": "0.6.4-develop.4282.1.4d95e85930",
|
|
256
256
|
"@testing-library/dom": "^10.4.1",
|
|
257
257
|
"@testing-library/jest-dom": "^6.9.1",
|
|
258
258
|
"@testing-library/react": "^16.3.1",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
|
-
import { Users, Phone, Check, Mail, Calendar, AlertTriangle, X } from 'lucide-react'
|
|
4
|
+
import { Users, Phone, Check, Mail, Calendar, AlertTriangle, X, StickyNote } from 'lucide-react'
|
|
5
5
|
import { cn } from '@open-mercato/shared/lib/utils'
|
|
6
6
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
7
7
|
import { validatePhoneNumber } from '@open-mercato/shared/lib/phone'
|
|
@@ -33,6 +33,7 @@ const TYPE_TABS: Array<{ type: ActivityType; icon: React.ComponentType<{ classNa
|
|
|
33
33
|
{ type: 'call', icon: Phone, labelKey: 'customers.schedule.types.call', fallback: 'Call' },
|
|
34
34
|
{ type: 'task', icon: Check, labelKey: 'customers.schedule.types.task', fallback: 'Task' },
|
|
35
35
|
{ type: 'email', icon: Mail, labelKey: 'customers.schedule.types.email', fallback: 'Email' },
|
|
36
|
+
{ type: 'note', icon: StickyNote, labelKey: 'customers.schedule.types.note', fallback: 'Note' },
|
|
36
37
|
]
|
|
37
38
|
|
|
38
39
|
type DialogChrome = { titleKey: string; titleFallback: string; subtitleKey: string; subtitleFallback: string; saveKey: string; saveFallback: string; saveIcon: React.ComponentType<{ className?: string }> }
|
|
@@ -58,6 +59,11 @@ const TYPE_CHROME: Record<ActivityType, DialogChrome> = {
|
|
|
58
59
|
subtitleKey: 'customers.schedule.email.subtitle', subtitleFallback: 'Compose and send a tracked email',
|
|
59
60
|
saveKey: 'customers.schedule.email.save', saveFallback: 'Send email', saveIcon: Mail,
|
|
60
61
|
},
|
|
62
|
+
note: {
|
|
63
|
+
titleKey: 'customers.schedule.note.title', titleFallback: 'Add note',
|
|
64
|
+
subtitleKey: 'customers.schedule.note.subtitle', subtitleFallback: 'Write down a note about this interaction',
|
|
65
|
+
saveKey: 'customers.schedule.note.save', saveFallback: 'Save note', saveIcon: StickyNote,
|
|
66
|
+
},
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
const CALL_DIRECTIONS: Array<{ key: 'outbound' | 'inbound'; labelKey: string; labelFallback: string; dot: string }> = [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ActivityType = 'meeting' | 'call' | 'task' | 'email'
|
|
1
|
+
export type ActivityType = 'meeting' | 'call' | 'task' | 'email' | 'note'
|
|
2
2
|
|
|
3
3
|
export type ScheduleFieldId =
|
|
4
4
|
| 'title'
|
|
@@ -39,6 +39,9 @@ export const FIELD_VISIBILITY: Record<ActivityType, Set<ScheduleFieldId>> = {
|
|
|
39
39
|
'participants', 'linkedEntities', 'description',
|
|
40
40
|
'reminder', 'visibility',
|
|
41
41
|
]),
|
|
42
|
+
note: new Set([
|
|
43
|
+
'title', 'linkedEntities', 'description', 'visibility',
|
|
44
|
+
]),
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
type LabelOverride = { key: string; fallback: string }
|
|
@@ -71,6 +74,10 @@ export const FIELD_LABEL_OVERRIDES: Partial<
|
|
|
71
74
|
linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },
|
|
72
75
|
description: { key: 'customers.schedule.message', fallback: 'Message' },
|
|
73
76
|
},
|
|
77
|
+
note: {
|
|
78
|
+
linkedEntities: { key: 'customers.schedule.connections', fallback: 'Connections' },
|
|
79
|
+
description: { key: 'customers.schedule.note.content', fallback: 'Note' },
|
|
80
|
+
},
|
|
74
81
|
}
|
|
75
82
|
|
|
76
83
|
export function isVisible(type: ActivityType, fieldId: ScheduleFieldId): boolean {
|
|
@@ -2207,6 +2207,10 @@
|
|
|
2207
2207
|
"customers.schedule.meeting.title": "Neues Meeting",
|
|
2208
2208
|
"customers.schedule.message": "Message",
|
|
2209
2209
|
"customers.schedule.noResults": "No results",
|
|
2210
|
+
"customers.schedule.note.content": "Notiz",
|
|
2211
|
+
"customers.schedule.note.save": "Notiz speichern",
|
|
2212
|
+
"customers.schedule.note.subtitle": "Eine Notiz zu dieser Interaktion schreiben",
|
|
2213
|
+
"customers.schedule.note.title": "Notiz hinzufügen",
|
|
2210
2214
|
"customers.schedule.participants": "Participants",
|
|
2211
2215
|
"customers.schedule.recurrence.active": "Repeats",
|
|
2212
2216
|
"customers.schedule.recurrence.afterCount": "After {{count}} occurrences",
|
|
@@ -2253,6 +2257,7 @@
|
|
|
2253
2257
|
"customers.schedule.types.call": "Call",
|
|
2254
2258
|
"customers.schedule.types.email": "Email",
|
|
2255
2259
|
"customers.schedule.types.meeting": "Meeting",
|
|
2260
|
+
"customers.schedule.types.note": "Notiz",
|
|
2256
2261
|
"customers.schedule.types.task": "Task",
|
|
2257
2262
|
"customers.schedule.update": "Aktivität aktualisieren",
|
|
2258
2263
|
"customers.schedule.visibility": "Visibility",
|
|
@@ -2207,6 +2207,10 @@
|
|
|
2207
2207
|
"customers.schedule.meeting.title": "New meeting",
|
|
2208
2208
|
"customers.schedule.message": "Message",
|
|
2209
2209
|
"customers.schedule.noResults": "No results",
|
|
2210
|
+
"customers.schedule.note.content": "Note",
|
|
2211
|
+
"customers.schedule.note.save": "Save note",
|
|
2212
|
+
"customers.schedule.note.subtitle": "Write down a note about this interaction",
|
|
2213
|
+
"customers.schedule.note.title": "Add note",
|
|
2210
2214
|
"customers.schedule.participants": "Participants",
|
|
2211
2215
|
"customers.schedule.recurrence.active": "Repeats",
|
|
2212
2216
|
"customers.schedule.recurrence.afterCount": "After {{count}} occurrences",
|
|
@@ -2253,6 +2257,7 @@
|
|
|
2253
2257
|
"customers.schedule.types.call": "Call",
|
|
2254
2258
|
"customers.schedule.types.email": "Email",
|
|
2255
2259
|
"customers.schedule.types.meeting": "Meeting",
|
|
2260
|
+
"customers.schedule.types.note": "Note",
|
|
2256
2261
|
"customers.schedule.types.task": "Task",
|
|
2257
2262
|
"customers.schedule.update": "Update activity",
|
|
2258
2263
|
"customers.schedule.visibility": "Visibility",
|
|
@@ -2207,6 +2207,10 @@
|
|
|
2207
2207
|
"customers.schedule.meeting.title": "Nueva reunión",
|
|
2208
2208
|
"customers.schedule.message": "Message",
|
|
2209
2209
|
"customers.schedule.noResults": "No results",
|
|
2210
|
+
"customers.schedule.note.content": "Nota",
|
|
2211
|
+
"customers.schedule.note.save": "Guardar nota",
|
|
2212
|
+
"customers.schedule.note.subtitle": "Escribe una nota sobre esta interacción",
|
|
2213
|
+
"customers.schedule.note.title": "Añadir nota",
|
|
2210
2214
|
"customers.schedule.participants": "Participants",
|
|
2211
2215
|
"customers.schedule.recurrence.active": "Repeats",
|
|
2212
2216
|
"customers.schedule.recurrence.afterCount": "After {{count}} occurrences",
|
|
@@ -2253,6 +2257,7 @@
|
|
|
2253
2257
|
"customers.schedule.types.call": "Call",
|
|
2254
2258
|
"customers.schedule.types.email": "Email",
|
|
2255
2259
|
"customers.schedule.types.meeting": "Meeting",
|
|
2260
|
+
"customers.schedule.types.note": "Nota",
|
|
2256
2261
|
"customers.schedule.types.task": "Task",
|
|
2257
2262
|
"customers.schedule.update": "Actualizar actividad",
|
|
2258
2263
|
"customers.schedule.visibility": "Visibility",
|
|
@@ -2207,6 +2207,10 @@
|
|
|
2207
2207
|
"customers.schedule.meeting.title": "Nowe spotkanie",
|
|
2208
2208
|
"customers.schedule.message": "Wiadomość",
|
|
2209
2209
|
"customers.schedule.noResults": "No results",
|
|
2210
|
+
"customers.schedule.note.content": "Notatka",
|
|
2211
|
+
"customers.schedule.note.save": "Zapisz notatkę",
|
|
2212
|
+
"customers.schedule.note.subtitle": "Zapisz notatkę dotyczącą tej interakcji",
|
|
2213
|
+
"customers.schedule.note.title": "Dodaj notatkę",
|
|
2210
2214
|
"customers.schedule.participants": "Uczestnicy",
|
|
2211
2215
|
"customers.schedule.recurrence.active": "Powtarza się",
|
|
2212
2216
|
"customers.schedule.recurrence.afterCount": "Po {{count}} wystąpieniach",
|
|
@@ -2253,6 +2257,7 @@
|
|
|
2253
2257
|
"customers.schedule.types.call": "Połączenie",
|
|
2254
2258
|
"customers.schedule.types.email": "E-mail",
|
|
2255
2259
|
"customers.schedule.types.meeting": "Spotkanie",
|
|
2260
|
+
"customers.schedule.types.note": "Notatka",
|
|
2256
2261
|
"customers.schedule.types.task": "Zadanie",
|
|
2257
2262
|
"customers.schedule.update": "Aktualizuj aktywność",
|
|
2258
2263
|
"customers.schedule.visibility": "Widoczność",
|
|
@@ -261,9 +261,6 @@ export async function refreshCoverageSnapshot(
|
|
|
261
261
|
if (tenantId !== null && hasTenant) baseQuery = baseQuery.where('b.tenant_id' as any, '=', tenantId)
|
|
262
262
|
if (!withDeleted && hasDeleted) baseQuery = baseQuery.where('b.deleted_at' as any, 'is', null as any)
|
|
263
263
|
|
|
264
|
-
const baseRow = await baseQuery.executeTakeFirst() as { count: unknown } | undefined
|
|
265
|
-
const baseCount = toCount(baseRow?.count)
|
|
266
|
-
|
|
267
264
|
let indexQuery = db
|
|
268
265
|
.selectFrom('entity_indexes as ei' as any)
|
|
269
266
|
.select(sql`count(*)`.as('count'))
|
|
@@ -272,13 +269,10 @@ export async function refreshCoverageSnapshot(
|
|
|
272
269
|
if (tenantId !== null) indexQuery = indexQuery.where('ei.tenant_id' as any, '=', tenantId)
|
|
273
270
|
if (!withDeleted) indexQuery = indexQuery.where('ei.deleted_at' as any, 'is', null as any)
|
|
274
271
|
|
|
275
|
-
const
|
|
276
|
-
|
|
272
|
+
const vectorCountPromise = (async (): Promise<number | undefined> => {
|
|
273
|
+
const hasVectorTable = await tableHasColumn(db, 'vector_search', 'entity_id')
|
|
274
|
+
if (!hasVectorTable || typeof tenantId !== 'string' || tenantId.length === 0) return undefined
|
|
277
275
|
|
|
278
|
-
// Count vector entries directly from database
|
|
279
|
-
let vectorCount: number | undefined
|
|
280
|
-
const hasVectorTable = await tableHasColumn(db, 'vector_search', 'entity_id')
|
|
281
|
-
if (hasVectorTable && typeof tenantId === 'string' && tenantId.length > 0) {
|
|
282
276
|
try {
|
|
283
277
|
let vectorQuery = db
|
|
284
278
|
.selectFrom('vector_search' as any)
|
|
@@ -289,7 +283,7 @@ export async function refreshCoverageSnapshot(
|
|
|
289
283
|
vectorQuery = vectorQuery.where('organization_id' as any, '=', organizationId)
|
|
290
284
|
}
|
|
291
285
|
const vectorRow = await vectorQuery.executeTakeFirst() as { count: unknown } | undefined
|
|
292
|
-
|
|
286
|
+
return toCount(vectorRow?.count)
|
|
293
287
|
} catch (err) {
|
|
294
288
|
console.warn('[query_index] Failed to resolve vector count for coverage snapshot', {
|
|
295
289
|
entityType,
|
|
@@ -297,9 +291,18 @@ export async function refreshCoverageSnapshot(
|
|
|
297
291
|
organizationId,
|
|
298
292
|
error: err instanceof Error ? err.message : err,
|
|
299
293
|
})
|
|
300
|
-
|
|
294
|
+
return undefined
|
|
301
295
|
}
|
|
302
|
-
}
|
|
296
|
+
})()
|
|
297
|
+
|
|
298
|
+
const [baseRow, indexRow, vectorCount] = await Promise.all([
|
|
299
|
+
baseQuery.executeTakeFirst() as Promise<{ count: unknown } | undefined>,
|
|
300
|
+
indexQuery.executeTakeFirst() as Promise<{ count: unknown } | undefined>,
|
|
301
|
+
vectorCountPromise,
|
|
302
|
+
])
|
|
303
|
+
|
|
304
|
+
const baseCount = toCount(baseRow?.count)
|
|
305
|
+
const indexCount = toCount(indexRow?.count)
|
|
303
306
|
|
|
304
307
|
await writeCoverageCounts(em, { entityType, tenantId, organizationId, withDeleted }, {
|
|
305
308
|
baseCount,
|
|
@@ -1758,17 +1758,25 @@ export class HybridQueryEngine implements QueryEngine {
|
|
|
1758
1758
|
withDeleted: boolean
|
|
1759
1759
|
): Promise<{ baseCount: number; indexedCount: number } | null> {
|
|
1760
1760
|
try {
|
|
1761
|
-
if (!this.isCoverageOptimizationEnabled()) {
|
|
1762
|
-
await refreshCoverageSnapshot(this.em, {
|
|
1763
|
-
entityType: entity, tenantId, organizationId, withDeleted,
|
|
1764
|
-
})
|
|
1765
|
-
}
|
|
1766
1761
|
const db = this.getDb()
|
|
1767
|
-
const
|
|
1762
|
+
const scope = {
|
|
1768
1763
|
entityType: entity, tenantId, organizationId, withDeleted,
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
|
|
1764
|
+
}
|
|
1765
|
+
const row = await readCoverageSnapshot(db as any, scope)
|
|
1766
|
+
if (row && this.isCoverageSnapshotFresh(row)) {
|
|
1767
|
+
return { baseCount: row.baseCount, indexedCount: row.indexedCount }
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
if (this.isCoverageOptimizationEnabled()) {
|
|
1771
|
+
this.scheduleCoverageRefresh(entity, tenantId, organizationId, withDeleted)
|
|
1772
|
+
if (!row) return null
|
|
1773
|
+
return { baseCount: row.baseCount, indexedCount: row.indexedCount }
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
await refreshCoverageSnapshot(this.em, scope)
|
|
1777
|
+
const refreshed = await readCoverageSnapshot(db as any, scope)
|
|
1778
|
+
if (!refreshed) return null
|
|
1779
|
+
return { baseCount: refreshed.baseCount, indexedCount: refreshed.indexedCount }
|
|
1772
1780
|
} catch (err) {
|
|
1773
1781
|
if (this.isDebugVerbosity()) {
|
|
1774
1782
|
this.debug('coverage:snapshot:read-error', {
|
|
@@ -1780,6 +1788,21 @@ export class HybridQueryEngine implements QueryEngine {
|
|
|
1780
1788
|
}
|
|
1781
1789
|
}
|
|
1782
1790
|
|
|
1791
|
+
private isCoverageSnapshotFresh(
|
|
1792
|
+
row: Awaited<ReturnType<typeof readCoverageSnapshot>>
|
|
1793
|
+
): boolean {
|
|
1794
|
+
if (this.coverageStatsTtlMs <= 0) return false
|
|
1795
|
+
if (!row) return false
|
|
1796
|
+
const refreshedAt = row.refreshed_at instanceof Date
|
|
1797
|
+
? row.refreshed_at
|
|
1798
|
+
: row.refreshed_at
|
|
1799
|
+
? new Date(row.refreshed_at)
|
|
1800
|
+
: null
|
|
1801
|
+
const refreshedAtMs = refreshedAt?.getTime()
|
|
1802
|
+
if (!refreshedAtMs || !Number.isFinite(refreshedAtMs)) return false
|
|
1803
|
+
return Date.now() - refreshedAtMs <= this.coverageStatsTtlMs
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1783
1806
|
private scheduleAutoReindex(
|
|
1784
1807
|
entity: string,
|
|
1785
1808
|
opts: QueryOptions,
|