@svgrid/enterprise 2.2.1 → 2.3.1

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.
Files changed (126) hide show
  1. package/README.md +95 -81
  2. package/dist/cdn/svgrid-enterprise.svelte-external.js +26642 -11252
  3. package/dist/designer/assets/GridMenus-BtWVk9Ab.js +7 -0
  4. package/dist/designer/assets/SvGridChartPanel-DWlBO2SD.js +10 -0
  5. package/dist/designer/assets/SvGridChartView-8c8Mb4j8.js +1 -0
  6. package/dist/designer/assets/SvGridChartView-DX9HfkBR.css +1 -0
  7. package/dist/designer/assets/index-DsDgp9Xq.js +78758 -0
  8. package/dist/designer/assets/index-tTY_Dx4P.css +1 -0
  9. package/dist/designer/assets/jszip.min-fkJdmAmj.js +2 -0
  10. package/dist/designer/assets/pdfmake-DeCsnyl9.js +242 -0
  11. package/dist/designer/assets/smart.export-BZlSCE8T.js +35 -0
  12. package/dist/designer/assets/vfs_fonts-eX2NpmfX.js +1 -0
  13. package/dist/designer/index.html +13 -0
  14. package/dist/node/studio.js +15304 -2708
  15. package/package.json +35 -11
  16. package/src/SvAlertRuleEditor.svelte +294 -0
  17. package/src/SvAlertsManager.svelte +210 -0
  18. package/src/SvAlertsPanel.svelte +129 -0
  19. package/src/SvBoard.svelte +3 -1
  20. package/src/SvExpressionEditor.svelte +341 -0
  21. package/src/SvGridAlerts.dom.test.ts +113 -0
  22. package/src/SvGridAlerts.svelte +265 -0
  23. package/src/SvGridBoard.svelte +2358 -0
  24. package/src/SvGridEditPanel.svelte +849 -794
  25. package/src/SvGridScheduler.svelte +5358 -4410
  26. package/src/SvPivotDesigner.svelte +3 -3
  27. package/src/SvRecordDetail.svelte +6 -2
  28. package/src/SvSchedule.svelte +3 -1
  29. package/src/{ai-export-pdf.test.ts → ai-export-pdf.dom.test.ts} +77 -74
  30. package/src/{ai-export-xlsx.test.ts → ai-export-xlsx.dom.test.ts} +90 -87
  31. package/src/{ai-export.test.ts → ai-export.dom.test.ts} +114 -110
  32. package/src/alerts/alert-engine-attach.ts +165 -0
  33. package/src/alerts/alert-engine.test.ts +135 -0
  34. package/src/alerts/alert-engine.ts +260 -0
  35. package/src/alerts/alert-formats.test.ts +87 -0
  36. package/src/alerts/alert-formats.ts +77 -0
  37. package/src/alerts/alert-observer.test.ts +189 -0
  38. package/src/alerts/alert-observer.ts +208 -0
  39. package/src/alerts/alert-scheduler.ts +96 -0
  40. package/src/alerts/alert-storage.test.ts +54 -0
  41. package/src/alerts/alert-storage.ts +116 -0
  42. package/src/alerts/alert-store.svelte.ts +80 -0
  43. package/src/alerts/alert-types.ts +94 -0
  44. package/src/alerts.ts +28 -0
  45. package/src/board.dom.test.ts +941 -0
  46. package/src/board.ts +36 -0
  47. package/src/export-ooxml.ts +4 -0
  48. package/src/export-xls.ts +3 -0
  49. package/src/export.ts +6 -0
  50. package/src/expressions/evaluate.test.ts +111 -0
  51. package/src/expressions/evaluate.ts +237 -0
  52. package/src/expressions/expression-columns.ts +133 -0
  53. package/src/expressions/expression-types.ts +84 -0
  54. package/src/expressions/parse.test.ts +106 -0
  55. package/src/expressions/parse.ts +610 -0
  56. package/src/import.test.ts +1 -1
  57. package/src/import.ts +3 -1
  58. package/src/index.ts +192 -46
  59. package/src/install.ts +12 -2
  60. package/src/pivot-enable.ts +44 -0
  61. package/src/pivot.test.ts +0 -1
  62. package/src/scheduler-assignments.test.ts +97 -0
  63. package/src/scheduler-assignments.ts +134 -0
  64. package/src/scheduler-axis.test.ts +108 -0
  65. package/src/scheduler-axis.ts +238 -0
  66. package/src/scheduler-booking.test.ts +57 -0
  67. package/src/scheduler-booking.ts +63 -0
  68. package/src/scheduler-config.ts +179 -0
  69. package/src/scheduler-dependencies.test.ts +155 -0
  70. package/src/scheduler-dependencies.ts +223 -0
  71. package/src/scheduler-freebusy.test.ts +41 -0
  72. package/src/scheduler-freebusy.ts +36 -0
  73. package/src/scheduler-heatmap.test.ts +39 -0
  74. package/src/scheduler-heatmap.ts +55 -0
  75. package/src/scheduler-resource-tree.test.ts +84 -0
  76. package/src/scheduler-resource-tree.ts +107 -0
  77. package/src/scheduler-slots.test.ts +53 -0
  78. package/src/scheduler-slots.ts +94 -0
  79. package/src/scheduler-summary.test.ts +47 -0
  80. package/src/scheduler-summary.ts +81 -0
  81. package/src/schema-designer.ts +1 -1
  82. package/src/sources/index.ts +1 -1
  83. package/src/sources/introspect-supabase.test.ts +13 -1
  84. package/src/sources/introspect-supabase.ts +20 -0
  85. package/src/studio/copilot-core.test.ts +45 -0
  86. package/src/studio/copilot-core.ts +65 -0
  87. package/src/studio/deploy-cli.test.ts +56 -0
  88. package/src/studio/deploy-cli.ts +100 -0
  89. package/src/studio/emit-project.test.ts +800 -24
  90. package/src/studio/emit-project.ts +1307 -135
  91. package/src/studio/emit-schema.test.ts +17 -0
  92. package/src/studio/emit-schema.ts +182 -41
  93. package/src/studio/index.ts +59 -1
  94. package/src/studio/init-flow.test.ts +239 -0
  95. package/src/studio/init-flow.ts +358 -0
  96. package/src/studio/introspect-openapi.test.ts +84 -0
  97. package/src/studio/introspect-openapi.ts +252 -0
  98. package/src/studio/project.test.ts +57 -1
  99. package/src/studio/project.ts +302 -8
  100. package/src/studio/samples/crm.ts +282 -258
  101. package/src/studio/samples/datasets.test.ts +84 -0
  102. package/src/studio/samples/datasets.ts +340 -0
  103. package/src/studio/samples/fleet.ts +213 -186
  104. package/src/studio/samples/insurance.ts +223 -195
  105. package/src/studio/samples/inventory.ts +213 -182
  106. package/src/studio/samples/live-data.test.ts +99 -98
  107. package/src/studio/samples/live-data.ts +8 -10
  108. package/src/studio/samples/projects.ts +212 -190
  109. package/src/studio/samples/samples.test.ts +268 -216
  110. package/src/studio/samples/shared.ts +22 -145
  111. package/src/studio/samples/starter.ts +251 -0
  112. package/src/studio/samples/support.ts +209 -184
  113. package/src/studio/screen-suites.test.ts +226 -0
  114. package/src/studio/screen-suites.ts +445 -0
  115. package/src/studio/ui-components-surface.test.ts +185 -0
  116. package/src/studio/ui-components.generated.ts +7154 -0
  117. package/src/studio/ui-components.ts +273 -3
  118. package/src/sveltekit/index.ts +1 -0
  119. package/src/sveltekit/sql-source.test.ts +13 -0
  120. package/src/sveltekit/sql-source.ts +12 -7
  121. package/src/sveltekit/transport-scope.test.ts +125 -0
  122. package/src/sveltekit/transport.ts +76 -2
  123. package/src/upgrade-prompt.ts +2 -2
  124. package/src/watermark.ts +2 -2
  125. package/src/ai.test.ts +0 -522
  126. package/src/ai.ts +0 -1388
@@ -0,0 +1,106 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ ExpressionParseError,
4
+ collectColumnRefs,
5
+ parsePredicate,
6
+ stringifyPredicate,
7
+ validateExpression,
8
+ } from './parse'
9
+ import { evaluatePredicate } from './evaluate'
10
+ import type { ExprColumn } from './expression-columns'
11
+ import type { PredicateExpr } from './expression-types'
12
+
13
+ const columns: ExprColumn[] = [
14
+ { id: 'price', name: 'Unit Price', type: 'number' },
15
+ { id: 'qty', name: 'Qty', type: 'number' },
16
+ { id: 'name', name: 'Name', type: 'text' },
17
+ { id: 'region', name: 'Region', type: 'text' },
18
+ ]
19
+
20
+ describe('parsePredicate', () => {
21
+ it('parses a col-vs-literal comparison into a cmp node (grid-filter semantics)', () => {
22
+ const e = parsePredicate('price > 100', columns)
23
+ expect(e).toEqual({ kind: 'cmp', column: 'price', op: 'greaterThan', value: 100 })
24
+ })
25
+
26
+ it('resolves [Bracketed Name] references to ids', () => {
27
+ const e = parsePredicate('[Unit Price] >= 50', columns) as Extract<PredicateExpr, { kind: 'scalarCmp' }>
28
+ // >= has no cmp equivalent, so it becomes a scalarCmp over the resolved column id
29
+ expect(e.kind).toBe('scalarCmp')
30
+ expect(e.left).toEqual({ kind: 'col', id: 'price' })
31
+ })
32
+
33
+ it('parses keyword text/set/range operators', () => {
34
+ expect(parsePredicate('name CONTAINS "wid"', columns)).toEqual({ kind: 'cmp', column: 'name', op: 'contains', value: 'wid' })
35
+ expect(parsePredicate('region IN ("EU", "US")', columns)).toEqual({ kind: 'cmp', column: 'region', op: 'in', value: ['EU', 'US'] })
36
+ expect(parsePredicate('price BETWEEN 10 AND 20', columns)).toEqual({ kind: 'cmp', column: 'price', op: 'between', value: 10, valueTo: 20 })
37
+ expect(parsePredicate('name ISBLANK', columns)).toEqual({ kind: 'cmp', column: 'name', op: 'isBlank' })
38
+ })
39
+
40
+ it('honours AND/OR/NOT precedence and grouping', () => {
41
+ const e = parsePredicate('price > 100 AND (region = "EU" OR region = "US")', columns) as Extract<PredicateExpr, { kind: 'and' }>
42
+ expect(e.kind).toBe('and')
43
+ expect(e.parts[1]!.kind).toBe('or')
44
+ })
45
+
46
+ it('parses cross-column scalar maths', () => {
47
+ const e = parsePredicate('price / qty >= 40', columns) as Extract<PredicateExpr, { kind: 'scalarCmp' }>
48
+ expect(e.kind).toBe('scalarCmp')
49
+ expect(e.op).toBe('>=')
50
+ expect(e.left).toEqual({ kind: 'bin', op: '/', left: { kind: 'col', id: 'price' }, right: { kind: 'col', id: 'qty' } })
51
+ })
52
+
53
+ it('throws a positioned error on a syntax problem', () => {
54
+ expect(() => parsePredicate('price >', columns)).toThrow(ExpressionParseError)
55
+ try {
56
+ parsePredicate('price @ 5', columns)
57
+ } catch (err) {
58
+ expect(err).toBeInstanceOf(ExpressionParseError)
59
+ expect((err as ExpressionParseError).pos).toBeGreaterThan(0)
60
+ }
61
+ })
62
+
63
+ it('parsed expressions evaluate correctly end to end', () => {
64
+ const e = parsePredicate('price > 100 AND region = "EU"', columns)
65
+ expect(evaluatePredicate(e, { row: { price: 120, region: 'EU' } })).toBe(true)
66
+ expect(evaluatePredicate(e, { row: { price: 120, region: 'US' } })).toBe(false)
67
+ })
68
+ })
69
+
70
+ describe('stringifyPredicate', () => {
71
+ it('round-trips through parse for the common forms', () => {
72
+ for (const src of [
73
+ 'price > 100',
74
+ 'name CONTAINS "wid"',
75
+ 'region IN ("EU", "US")',
76
+ 'price BETWEEN 10 AND 20',
77
+ 'name ISBLANK',
78
+ ]) {
79
+ const ast = parsePredicate(src, columns)
80
+ const back = stringifyPredicate(ast, columns)
81
+ expect(stringifyPredicate(parsePredicate(back, columns), columns)).toBe(back)
82
+ }
83
+ })
84
+
85
+ it('writes [bracketed] names when a label has spaces', () => {
86
+ const ast = parsePredicate('price > 100', columns)
87
+ expect(stringifyPredicate(ast, columns)).toBe('[Unit Price] > 100')
88
+ })
89
+ })
90
+
91
+ describe('validateExpression + collectColumnRefs', () => {
92
+ it('collects every referenced column id', () => {
93
+ const ast = parsePredicate('price / qty >= 40 AND region = "EU"', columns)
94
+ expect(collectColumnRefs(ast).sort()).toEqual(['price', 'qty', 'region'])
95
+ })
96
+
97
+ it('flags unknown columns and functions', () => {
98
+ const ast = parsePredicate('bogus > 5', columns)
99
+ expect(validateExpression(ast, columns)).toContain('Unknown column "bogus"')
100
+ })
101
+
102
+ it('passes a sound expression', () => {
103
+ const ast = parsePredicate('price > 100', columns)
104
+ expect(validateExpression(ast, columns)).toEqual([])
105
+ })
106
+ })