@svgrid/enterprise 3.1.21 → 3.1.23
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/SvGridBoard.svelte +39 -0
- package/dist/SvGridGallery.svelte +23 -0
- package/dist/SvGridRowCount.svelte +23 -0
- package/dist/SvGridRowCount.svelte.d.ts +6 -0
- package/dist/SvGridScheduler.svelte +25 -7
- package/dist/cdn/svgrid-enterprise.svelte-external.js +13838 -13554
- package/dist/designer/assets/GridFooter-DKMfZpL4.js +2 -0
- package/dist/designer/assets/GridMenus-DWDghydL.js +6 -0
- package/dist/designer/assets/{PinSplitter-C5AwA1xV.js → PinSplitter-BfIjd7pi.js} +1 -1
- package/dist/designer/assets/grid-extension.svelte-G1ng0xd2.js +1 -0
- package/dist/designer/assets/index-CHx3F4Ij.css +1 -0
- package/dist/designer/assets/{index-DLJjuVA4.js → index-CIxqRzKJ.js} +324 -324
- package/dist/designer/assets/merges-Bg-KqPEl.js +1 -0
- package/dist/designer/index.html +3 -3
- package/dist/expressions/compile.js +11 -7
- package/dist/expressions/evaluate.js +4 -0
- package/dist/expressions/expression-columns.d.ts +4 -1
- package/dist/expressions/expression-columns.js +12 -3
- package/dist/expressions/parse.js +19 -7
- package/dist/fields/RecordView.svelte +5 -2
- package/dist/fields/activity.svelte.d.ts +5 -2
- package/dist/fields/activity.svelte.js +4 -3
- package/dist/fields/grid-access.d.ts +1 -1
- package/dist/fields/grid-access.js +13 -3
- package/dist/fields/index.d.ts +18 -0
- package/dist/fields/index.js +31 -0
- package/dist/filter-labels.d.ts +16 -0
- package/dist/filter-labels.js +83 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +7 -0
- package/dist/install.js +8 -0
- package/dist/node/studio.js +12 -5
- package/dist/relative-date-core.d.ts +40 -0
- package/dist/relative-date-core.js +85 -0
- package/dist/relative-dates.d.ts +28 -0
- package/dist/relative-dates.js +61 -0
- package/dist/review/GhostCell.svelte +60 -0
- package/dist/review/GhostCell.svelte.d.ts +14 -0
- package/dist/review/RichCellMark.svelte +72 -0
- package/dist/review/RichCellMark.svelte.d.ts +8 -0
- package/dist/review/SvReviewPanel.svelte +759 -0
- package/dist/review/SvReviewPanel.svelte.d.ts +16 -0
- package/dist/review/adapters.d.ts +79 -0
- package/dist/review/adapters.js +119 -0
- package/dist/review/agent.d.ts +52 -0
- package/dist/review/agent.js +232 -0
- package/dist/review/card-marks.svelte.d.ts +42 -0
- package/dist/review/card-marks.svelte.js +51 -0
- package/dist/review/cluster.d.ts +26 -0
- package/dist/review/cluster.js +377 -0
- package/dist/review/equal.d.ts +9 -0
- package/dist/review/equal.js +35 -0
- package/dist/review/formats.d.ts +31 -0
- package/dist/review/formats.js +37 -0
- package/dist/review/ghost.d.ts +17 -0
- package/dist/review/ghost.js +104 -0
- package/dist/review/index.d.ts +42 -0
- package/dist/review/index.js +36 -0
- package/dist/review/messages.d.ts +113 -0
- package/dist/review/messages.js +135 -0
- package/dist/review/model.svelte.d.ts +262 -0
- package/dist/review/model.svelte.js +883 -0
- package/dist/review/pending-filter.d.ts +26 -0
- package/dist/review/pending-filter.js +71 -0
- package/dist/review/rich-cells.d.ts +1 -0
- package/dist/review/rich-cells.js +36 -0
- package/dist/review/types.d.ts +83 -0
- package/dist/review/types.js +7 -0
- package/dist/row-count.d.ts +28 -0
- package/dist/row-count.js +39 -0
- package/dist/sort-blanks.d.ts +8 -0
- package/dist/sort-blanks.js +47 -0
- package/dist/studio/ui-components.generated.js +1 -1
- package/dist/upgrade-prompt.d.ts +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/wc/GridFooter-CKC4L36O.js +162 -0
- package/dist/wc/{GridMenus-DVGuqp2l.js → GridMenus-h7RsvcmI.js} +320 -303
- package/dist/wc/{PinSplitter-Btco0txr.js → PinSplitter-BN6ybmjs.js} +1 -1
- package/dist/wc/grid-extension.svelte-CDf5EUyz.js +27 -0
- package/dist/wc/merges-DQTOlMWM.js +109 -0
- package/dist/wc/sv-sheet-element.js +6753 -6792
- package/package.json +9 -3
- package/dist/designer/assets/GridFooter-CKBVItAU.js +0 -2
- package/dist/designer/assets/GridMenus-Dzwu7M9r.js +0 -6
- package/dist/designer/assets/grid-extension.svelte-BZ7AqyJI.js +0 -1
- package/dist/designer/assets/index-WCxj6WfJ.css +0 -1
- package/dist/wc/GridFooter-BgoA77TJ.js +0 -145
- package/dist/wc/grid-extension.svelte-CucBS4FL.js +0 -20
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime-Dd_uD5pT.js";var t=e({buildMergeIndex:()=>r,endOf:()=>s,expandRectToMerges:()=>c,isCovered:()=>a,mergeAt:()=>i,mergeDrawAt:()=>u,originOf:()=>o,stepPastMerge:()=>l}),n=(e,t)=>`${e}:${t}`;function r(e){if(!e||e.length===0)return null;let t=new Map,r=[];for(let i of e){let e=Math.max(1,Math.floor(i.rowSpan)),a=Math.max(1,Math.floor(i.colSpan));if(e===1&&a===1)continue;let o={rowIndex:i.rowIndex,colIndex:i.colIndex,rowSpan:e,colSpan:a};r.push(o);for(let r=o.rowIndex;r<o.rowIndex+e;r+=1)for(let e=o.colIndex;e<o.colIndex+a;e+=1)t.set(n(r,e),o)}return r.length?{list:r,byCell:t}:null}function i(e,t,r){return e?.byCell.get(n(t,r))}function a(e,t,n){let r=i(e,t,n);return!!r&&(r.rowIndex!==t||r.colIndex!==n)}function o(e,t,n){let r=i(e,t,n);return r?{rowIndex:r.rowIndex,colIndex:r.colIndex}:{rowIndex:t,colIndex:n}}function s(e,t,n){let r=i(e,t,n);return r?{rowIndex:r.rowIndex+r.rowSpan-1,colIndex:r.colIndex+r.colSpan-1}:{rowIndex:t,colIndex:n}}function c(e,t){if(!e)return t;let{minRow:n,maxRow:r,minCol:i,maxCol:a}=t;for(let t=0;t<64;t+=1){let t=!1;for(let o of e.list){let e=o.rowIndex+o.rowSpan-1,s=o.colIndex+o.colSpan-1;o.rowIndex<=r&&e>=n&&o.colIndex<=a&&s>=i&&(o.rowIndex<n&&(n=o.rowIndex,t=!0),e>r&&(r=e,t=!0),o.colIndex<i&&(i=o.colIndex,t=!0),s>a&&(a=s,t=!0))}if(!t)break}return n===t.minRow&&r===t.maxRow&&i===t.minCol&&a===t.maxCol?t:{minRow:n,maxRow:r,minCol:i,maxCol:a}}function l(e,t,n,r){if(!e)return n;let a=i(e,n.rowIndex,n.colIndex);if(!a)return n;if(i(e,t.rowIndex,t.colIndex)!==a)return{rowIndex:a.rowIndex,colIndex:a.colIndex};let o=Math.sign(n.rowIndex-t.rowIndex),s=Math.sign(n.colIndex-t.colIndex);if(o===0&&s===0)return{rowIndex:a.rowIndex,colIndex:a.colIndex};let c=n.rowIndex,l=n.colIndex;if(o>0?c=a.rowIndex+a.rowSpan:o<0&&(c=a.rowIndex-1),s>0?l=a.colIndex+a.colSpan:s<0&&(l=a.colIndex-1),c<0||c>r.maxRow||l<0||l>r.maxCol)return{rowIndex:a.rowIndex,colIndex:a.colIndex};let u=i(e,c,l);return u?{rowIndex:u.rowIndex,colIndex:u.colIndex}:{rowIndex:c,colIndex:l}}function u(e,t,n,r){let a=i(e,t,n);if(!a)return null;let o=Math.max(a.rowIndex,r.firstRow),s=Math.max(a.colIndex,r.firstCol);if(t!==o||n!==s)return{kind:`skip`};let c=o===a.rowIndex&&s===a.colIndex,l=Math.max(1,Math.min(a.rowIndex+a.rowSpan-t,r.lastRow-t+1)),u=Math.max(1,Math.min(a.colIndex+a.colSpan-n,r.lastCol-n+1));return{kind:c?`origin`:`continuation`,merge:a,rowSpan:l,colSpan:u}}export{t};
|
package/dist/designer/index.html
CHANGED
|
@@ -4,17 +4,17 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>SvGrid Studio - Designer</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-CIxqRzKJ.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-Dd_uD5pT.js">
|
|
9
9
|
<link rel="modulepreload" crossorigin href="./assets/disclose-version-CIm4S9xS.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="./assets/cell-formatting-JoxA0t65.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="./assets/SvGrid.helpers-BF2QRcNt.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="./assets/sv-grid-scrollbar-B9N6Wuj0.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="./assets/grid-extension.svelte-G1ng0xd2.js">
|
|
13
14
|
<link rel="modulepreload" crossorigin href="./assets/editor-contract-Bpoa7A5g.js">
|
|
14
15
|
<link rel="modulepreload" crossorigin href="./assets/date-format-B8JbEtIG.js">
|
|
15
16
|
<link rel="modulepreload" crossorigin href="./assets/list-option-BP_dWS66.js">
|
|
16
17
|
<link rel="modulepreload" crossorigin href="./assets/SvListBox-fn160gSB.js">
|
|
17
|
-
<link rel="modulepreload" crossorigin href="./assets/grid-extension.svelte-BZ7AqyJI.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="./assets/editor-registry-BjP16H0v.js">
|
|
19
19
|
<link rel="modulepreload" crossorigin href="./assets/preload-helper-HclGiUj8.js">
|
|
20
20
|
<link rel="modulepreload" crossorigin href="./assets/popover-CUkLsvRX.js">
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
<link rel="stylesheet" crossorigin href="./assets/SvMenuList-DJ47ba1h.css">
|
|
46
46
|
<link rel="stylesheet" crossorigin href="./assets/SvGridChart-BgLuPO7I.css">
|
|
47
47
|
<link rel="stylesheet" crossorigin href="./assets/SvGridChartPanel-4Pc8y5yO.css">
|
|
48
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
48
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CHx3F4Ij.css">
|
|
49
49
|
</head>
|
|
50
50
|
<body>
|
|
51
51
|
<div id="app"></div>
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* constants.
|
|
22
22
|
*/
|
|
23
23
|
import { compileExcelFilter } from '@svgrid/grid/filtering';
|
|
24
|
+
import { compileRelativeDateFilter, isRelativeDateOperator } from '../relative-date-core.js';
|
|
24
25
|
import { getPredicateKind } from './kinds.js';
|
|
25
26
|
const num = (v) => typeof v === 'number' ? v : v == null || v === '' ? NaN : Number(v);
|
|
26
27
|
const BUILTINS = {
|
|
@@ -258,13 +259,16 @@ function compileInternal(expr, opts, aggs) {
|
|
|
258
259
|
return test ?? (() => true);
|
|
259
260
|
}
|
|
260
261
|
case 'cmp': {
|
|
261
|
-
// The needle-side work happens once, here.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
262
|
+
// The needle-side work happens once, here. The relative date operators
|
|
263
|
+
// are this package's, not the grid's.
|
|
264
|
+
const test = isRelativeDateOperator(expr.op)
|
|
265
|
+
? compileRelativeDateFilter(expr.op)
|
|
266
|
+
: compileExcelFilter({
|
|
267
|
+
id: expr.column,
|
|
268
|
+
operator: expr.op,
|
|
269
|
+
value: expr.value,
|
|
270
|
+
valueTo: expr.valueTo,
|
|
271
|
+
}, { locale: opts.locale });
|
|
268
272
|
const column = expr.column;
|
|
269
273
|
return (row) => test(opts.getValue(row, column));
|
|
270
274
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* exactly; scalar maths and change detection are handled here.
|
|
5
5
|
*/
|
|
6
6
|
import { applyExcelFilter } from '@svgrid/grid/filtering';
|
|
7
|
+
import { compileRelativeDateFilter, isRelativeDateOperator } from '../relative-date-core.js';
|
|
7
8
|
import { getPredicateKind } from './kinds.js';
|
|
8
9
|
function readValue(ctx, row, columnId) {
|
|
9
10
|
if (ctx.getValue)
|
|
@@ -168,6 +169,9 @@ export function evaluatePredicate(expr, ctx) {
|
|
|
168
169
|
case 'not':
|
|
169
170
|
return !evaluatePredicate(expr.expr, ctx);
|
|
170
171
|
case 'cmp':
|
|
172
|
+
// The relative date operators are this package's, not the grid's.
|
|
173
|
+
if (isRelativeDateOperator(expr.op))
|
|
174
|
+
return compileRelativeDateFilter(expr.op)(readValue(ctx, ctx.row, expr.column));
|
|
171
175
|
return applyExcelFilter(readValue(ctx, ctx.row, expr.column), { id: expr.column, operator: expr.op, value: expr.value, valueTo: expr.valueTo }, { locale: ctx.locale });
|
|
172
176
|
case 'scalarCmp':
|
|
173
177
|
return compareScalar(evaluateScalar(expr.left, ctx), expr.op, evaluateScalar(expr.right, ctx));
|
|
@@ -27,7 +27,10 @@ export declare const OPERATORS: ReadonlyArray<OperatorMeta>;
|
|
|
27
27
|
export declare function operatorMeta(op: ExcelFilterOperator): OperatorMeta;
|
|
28
28
|
/** Operators valid for a column type (defaults to the text set). */
|
|
29
29
|
export declare function operatorsForType(type: ExprColumnType | undefined): OperatorMeta[];
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Whether an operator needs no value input: the grid catalogue's, or one of
|
|
32
|
+
* the relative date operators this package adds.
|
|
33
|
+
*/
|
|
31
34
|
export declare function isValueless(op: ExcelFilterOperator): boolean;
|
|
32
35
|
/** Whether an operator takes a multi-value token list. */
|
|
33
36
|
export declare function isSetOperator(op: ExcelFilterOperator): boolean;
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
// Imported from the `/filtering` subpath, not the package root: the root would
|
|
17
17
|
// drag SvGrid.svelte into a module that is otherwise pure logic.
|
|
18
18
|
import { isRangeOperator as gridIsRangeOperator, isSetOperator as gridIsSetOperator, isValuelessOperator as gridIsValuelessOperator, } from '@svgrid/grid/filtering';
|
|
19
|
+
import { isRelativeDateOperator } from '../relative-date-core.js';
|
|
19
20
|
const TEXT = ['text'];
|
|
20
21
|
const NUM = ['number'];
|
|
21
22
|
const DATES = ['date', 'datetime'];
|
|
@@ -40,11 +41,16 @@ const OPERATOR_PRESENTATION = [
|
|
|
40
41
|
{ value: 'notIn', label: 'Not in', types: ['text', 'number'] },
|
|
41
42
|
{ value: 'isBlank', label: 'Is blank', types: ALL },
|
|
42
43
|
{ value: 'isNotBlank', label: 'Is not blank', types: ALL },
|
|
44
|
+
{ value: 'today', label: 'Is today', types: DATES },
|
|
45
|
+
{ value: 'beforeToday', label: 'Before today', types: DATES },
|
|
46
|
+
{ value: 'afterToday', label: 'After today', types: DATES },
|
|
47
|
+
{ value: 'next7Days', label: 'In the next 7 days', types: DATES },
|
|
48
|
+
{ value: 'last7Days', label: 'In the last 7 days', types: DATES },
|
|
43
49
|
];
|
|
44
50
|
/** The full operator catalogue, ordered as the editor should present it. */
|
|
45
51
|
export const OPERATORS = OPERATOR_PRESENTATION.map((op) => ({
|
|
46
52
|
...op,
|
|
47
|
-
...(
|
|
53
|
+
...(isValueless(op.value) ? { valueless: true } : {}),
|
|
48
54
|
...(gridIsSetOperator(op.value) ? { set: true } : {}),
|
|
49
55
|
...(gridIsRangeOperator(op.value) ? { range: true } : {}),
|
|
50
56
|
}));
|
|
@@ -58,9 +64,12 @@ export function operatorsForType(type) {
|
|
|
58
64
|
const t = type ?? 'text';
|
|
59
65
|
return OPERATORS.filter((op) => op.types.includes(t));
|
|
60
66
|
}
|
|
61
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* Whether an operator needs no value input: the grid catalogue's, or one of
|
|
69
|
+
* the relative date operators this package adds.
|
|
70
|
+
*/
|
|
62
71
|
export function isValueless(op) {
|
|
63
|
-
return gridIsValuelessOperator(op);
|
|
72
|
+
return gridIsValuelessOperator(op) || isRelativeDateOperator(op);
|
|
64
73
|
}
|
|
65
74
|
/** Whether an operator takes a multi-value token list. */
|
|
66
75
|
export function isSetOperator(op) {
|
|
@@ -5,7 +5,19 @@ const KEYWORDS = new Set([
|
|
|
5
5
|
'AND', 'OR', 'NOT', 'TRUE', 'FALSE', 'NULL',
|
|
6
6
|
'CONTAINS', 'STARTSWITH', 'ENDSWITH', 'MATCHES',
|
|
7
7
|
'IN', 'BETWEEN', 'ISBLANK', 'ISNOTBLANK',
|
|
8
|
+
'ISTODAY', 'BEFORETODAY', 'AFTERTODAY', 'INNEXT7DAYS', 'INLAST7DAYS',
|
|
8
9
|
]);
|
|
10
|
+
/** The operators that take no value, written after the column: `Due ISTODAY`. */
|
|
11
|
+
const POSTFIX_OPS = {
|
|
12
|
+
ISBLANK: 'isBlank',
|
|
13
|
+
ISNOTBLANK: 'isNotBlank',
|
|
14
|
+
ISTODAY: 'today',
|
|
15
|
+
BEFORETODAY: 'beforeToday',
|
|
16
|
+
AFTERTODAY: 'afterToday',
|
|
17
|
+
INNEXT7DAYS: 'next7Days',
|
|
18
|
+
INLAST7DAYS: 'last7Days',
|
|
19
|
+
};
|
|
20
|
+
const POSTFIX_KEYWORD = Object.fromEntries(Object.entries(POSTFIX_OPS).map(([kw, op]) => [op, kw]));
|
|
9
21
|
const AGG_KEYWORDS = new Set(['SUM', 'AVG', 'COUNT']);
|
|
10
22
|
function tokenize(input) {
|
|
11
23
|
const tokens = [];
|
|
@@ -192,9 +204,10 @@ class Parser {
|
|
|
192
204
|
const left = this.parseScalar();
|
|
193
205
|
const t = this.peek();
|
|
194
206
|
// Postfix valueless keyword ops.
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
207
|
+
const postfix = t.kind === 'kw' ? POSTFIX_OPS[t.value] : undefined;
|
|
208
|
+
if (postfix) {
|
|
209
|
+
this.next();
|
|
210
|
+
return { kind: 'cmp', column: this.expectColumn(left), op: postfix };
|
|
198
211
|
}
|
|
199
212
|
// Keyword text/set/range ops.
|
|
200
213
|
if (t.kind === 'kw') {
|
|
@@ -424,10 +437,9 @@ export function stringifyPredicate(expr, columns = []) {
|
|
|
424
437
|
return getPredicateKind(expr.type)?.describe?.(expr.payload, (id) => columnLabel(columns, id)) ?? `[${expr.type}]`;
|
|
425
438
|
case 'cmp': {
|
|
426
439
|
const col = columnRefText(columns, expr.column);
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
return `${col} ISNOTBLANK`;
|
|
440
|
+
const postfix = POSTFIX_KEYWORD[expr.op];
|
|
441
|
+
if (postfix)
|
|
442
|
+
return `${col} ${postfix}`;
|
|
431
443
|
if (expr.op === 'between')
|
|
432
444
|
return `${col} BETWEEN ${litText(expr.value)} AND ${litText(expr.valueTo)}`;
|
|
433
445
|
if (expr.op === 'in' || expr.op === 'notIn') {
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
|
|
144
144
|
// ---- Activity ---------------------------------------------------------------
|
|
145
145
|
const allCols = $derived([...columns, ...hidden])
|
|
146
|
-
type FeedItem = { key: string; at: number; by?: string; automation?: string; remote?: boolean; kind: 'edit' | 'added' | 'comment'; field: string; text: string; from?: string }
|
|
146
|
+
type FeedItem = { key: string; at: number; by?: string; automation?: string; via?: string; remote?: boolean; kind: 'edit' | 'added' | 'comment'; field: string; text: string; from?: string }
|
|
147
147
|
const feed = $derived.by(() => {
|
|
148
148
|
if (!row) return []
|
|
149
149
|
const edits = changesOf(ctrl, row.id).map((ch): FeedItem => {
|
|
@@ -155,6 +155,7 @@
|
|
|
155
155
|
at: ch.at,
|
|
156
156
|
by: ch.by,
|
|
157
157
|
automation: ch.automation,
|
|
158
|
+
via: ch.via,
|
|
158
159
|
remote: ch.remote,
|
|
159
160
|
kind: 'edit',
|
|
160
161
|
field: c ? label(c) : ch.columnId,
|
|
@@ -166,8 +167,10 @@
|
|
|
166
167
|
const notes = commentsOf(ctrl, row.id).map((n): FeedItem => ({ key: n.id, at: n.at, by: n.by, kind: 'comment', field: '', text: n.text }))
|
|
167
168
|
return [...edits, ...notes].sort((a, b) => a.at - b.at)
|
|
168
169
|
})
|
|
170
|
+
const person = (item: FeedItem) => (item.by ? (findFieldUser(item.by)?.name ?? 'Someone') : item.remote ? 'Someone else' : 'You')
|
|
171
|
+
// A proposal someone accepted (change review) is credited to what proposed it, and to them.
|
|
169
172
|
const who = (item: FeedItem) =>
|
|
170
|
-
item.automation ? `Automation: ${item.automation}` : item.
|
|
173
|
+
item.automation ? `Automation: ${item.automation}` : item.via ? `${item.via} (accepted by ${person(item)})` : person(item)
|
|
171
174
|
// Shown here: a change made elsewhere is seen, so the grid stops marking it.
|
|
172
175
|
$effect(() => {
|
|
173
176
|
const id = row?.id
|
|
@@ -25,6 +25,8 @@ export type RecordChange = {
|
|
|
25
25
|
by?: string;
|
|
26
26
|
/** The automation that made it, by name. */
|
|
27
27
|
automation?: string;
|
|
28
|
+
/** What proposed it, when `by` accepted a proposal (change review): "CRM agent". */
|
|
29
|
+
via?: string;
|
|
28
30
|
/** Made elsewhere (another user, a script, an agent) and read from the database. */
|
|
29
31
|
remote?: boolean;
|
|
30
32
|
/** The record was added elsewhere: one entry, with no field. */
|
|
@@ -60,9 +62,10 @@ export declare function setRecordComments(next: RecordCommentStore | null): void
|
|
|
60
62
|
/**
|
|
61
63
|
* Note a change to a cell (called after every edit, paste, fill and clear).
|
|
62
64
|
* `scope` is the grid, or the table (its base and id) for a change made
|
|
63
|
-
* outside it (an automation). `automation` names the automation that made it
|
|
65
|
+
* outside it (an automation). `automation` names the automation that made it;
|
|
66
|
+
* `via` names what proposed a change the signed-in user accepted.
|
|
64
67
|
*/
|
|
65
|
-
export declare function noteChange(scope: ActivityScope, rowId: string, columnId: string, value: unknown, automation?: string): void;
|
|
68
|
+
export declare function noteChange(scope: ActivityScope, rowId: string, columnId: string, value: unknown, automation?: string, via?: string): void;
|
|
66
69
|
export declare function changesOf(scope: ActivityScope, rowId: string): ReadonlyArray<RecordChange>;
|
|
67
70
|
/**
|
|
68
71
|
* Note a change made elsewhere and read from the database: an activity entry
|
|
@@ -50,13 +50,14 @@ export function setRecordComments(next) {
|
|
|
50
50
|
/**
|
|
51
51
|
* Note a change to a cell (called after every edit, paste, fill and clear).
|
|
52
52
|
* `scope` is the grid, or the table (its base and id) for a change made
|
|
53
|
-
* outside it (an automation). `automation` names the automation that made it
|
|
53
|
+
* outside it (an automation). `automation` names the automation that made it;
|
|
54
|
+
* `via` names what proposed a change the signed-in user accepted.
|
|
54
55
|
*/
|
|
55
|
-
export function noteChange(scope, rowId, columnId, value, automation) {
|
|
56
|
+
export function noteChange(scope, rowId, columnId, value, automation, via) {
|
|
56
57
|
const byRow = rowsOf(changes, scope, true);
|
|
57
58
|
const list = byRow.get(rowId) ?? [];
|
|
58
59
|
// Kept short: the panel shows the latest.
|
|
59
|
-
list.push({ at: Date.now(), ...(automation ? { automation } : { by: getCurrentUser()?.id }), columnId, value: Array.isArray(value) ? [...value] : value });
|
|
60
|
+
list.push({ at: Date.now(), ...(automation ? { automation } : { by: getCurrentUser()?.id }), ...(via ? { via } : {}), columnId, value: Array.isArray(value) ? [...value] : value });
|
|
60
61
|
if (list.length > 50)
|
|
61
62
|
list.splice(0, list.length - 50);
|
|
62
63
|
byRow.set(rowId, list);
|
|
@@ -16,7 +16,7 @@ export type FieldColumn = {
|
|
|
16
16
|
};
|
|
17
17
|
/** Called on every draw of a grid with fields turned on. */
|
|
18
18
|
export declare function rememberGrid(ctrl: any): void;
|
|
19
|
-
/** The grid an api belongs to; undefined until that grid has drawn once. */
|
|
19
|
+
/** The grid an api belongs to (or a `$state` proxy of it); undefined until that grid has drawn once. */
|
|
20
20
|
export declare function gridOf(api: unknown): any;
|
|
21
21
|
export declare const columnIdOf: (def: Record<string, any>) => string;
|
|
22
22
|
/** Every data column (declared ones with a field), in screen order, hidden ones last. */
|
|
@@ -7,15 +7,25 @@
|
|
|
7
7
|
import { getAdvancedFilterEngine } from '@svgrid/grid';
|
|
8
8
|
// The grid behind each api object (the grid keeps one api per grid).
|
|
9
9
|
const grids = new WeakMap();
|
|
10
|
+
// The same, by one of the api's methods. An app that keeps the api in
|
|
11
|
+
// `$state` hands over a proxy of it, which is not the object above; Svelte
|
|
12
|
+
// does not proxy functions, so the proxy's methods are the api's own.
|
|
13
|
+
const byMethod = new WeakMap();
|
|
10
14
|
/** Called on every draw of a grid with fields turned on. */
|
|
11
15
|
export function rememberGrid(ctrl) {
|
|
12
16
|
const api = ctrl?.buildApi?.();
|
|
13
|
-
if (api && !grids.has(api))
|
|
17
|
+
if (api && !grids.has(api)) {
|
|
14
18
|
grids.set(api, ctrl);
|
|
19
|
+
if (typeof api.getData === 'function')
|
|
20
|
+
byMethod.set(api.getData, ctrl);
|
|
21
|
+
}
|
|
15
22
|
}
|
|
16
|
-
/** The grid an api belongs to; undefined until that grid has drawn once. */
|
|
23
|
+
/** The grid an api belongs to (or a `$state` proxy of it); undefined until that grid has drawn once. */
|
|
17
24
|
export function gridOf(api) {
|
|
18
|
-
|
|
25
|
+
if (!api || typeof api !== 'object')
|
|
26
|
+
return undefined;
|
|
27
|
+
const getData = api.getData;
|
|
28
|
+
return grids.get(api) ?? (typeof getData === 'function' ? byMethod.get(getData) : undefined);
|
|
19
29
|
}
|
|
20
30
|
export const columnIdOf = (def) => String(def.id ?? def.field ?? '');
|
|
21
31
|
/** Every data column (declared ones with a field), in screen order, hidden ones last. */
|
package/dist/fields/index.d.ts
CHANGED
|
@@ -25,6 +25,24 @@ export type { FieldView, FieldViewType, ColorSetting } from './view-model.js';
|
|
|
25
25
|
export type { FieldPropertyDef, FieldEditorContext, FieldFillContext, FieldRowContext } from './registry.svelte.js';
|
|
26
26
|
export { BUILTIN_FIELD_TYPES } from './builtin-types.js';
|
|
27
27
|
export { setAttachmentUploader, attachmentsFromText, attachmentsText, toAttachments, type Attachment, type AttachmentFieldProps, type AttachmentUploader, type AttachmentUploadContext, } from './attachments.js';
|
|
28
|
+
/**
|
|
29
|
+
* Change review (`@svgrid/enterprise/review`) in SvGrid Base: what an edit
|
|
30
|
+
* does, done for each accepted proposal. Last modified time / by fields are
|
|
31
|
+
* stamped, and the record's activity notes the change, credited to the
|
|
32
|
+
* signed-in user who accepted it and to what proposed it ("CRM agent
|
|
33
|
+
* (accepted by Dana)"). An undo is noted as the user's own change.
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* const review = createReview({ api: () => api, setRows, onApply: baseReviewApplied(() => api) })
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function baseReviewApplied(api: unknown): (applied: ReadonlyArray<{
|
|
40
|
+
rowId: string;
|
|
41
|
+
field: string;
|
|
42
|
+
source: {
|
|
43
|
+
label: string;
|
|
44
|
+
};
|
|
45
|
+
}>, how: 'accept' | 'undo' | 'redo', rows?: ReadonlyArray<unknown>) => void;
|
|
28
46
|
/**
|
|
29
47
|
* Turn field types on for every `<SvGrid>` on the page: registers the
|
|
30
48
|
* built-in types and plugs the cell drawing into the grid. Safe to call more
|
package/dist/fields/index.js
CHANGED
|
@@ -184,6 +184,37 @@ function stampModified(ctrl, row, columnId) {
|
|
|
184
184
|
overlay(id, (row[c.field] = author));
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Change review (`@svgrid/enterprise/review`) in SvGrid Base: what an edit
|
|
189
|
+
* does, done for each accepted proposal. Last modified time / by fields are
|
|
190
|
+
* stamped, and the record's activity notes the change, credited to the
|
|
191
|
+
* signed-in user who accepted it and to what proposed it ("CRM agent
|
|
192
|
+
* (accepted by Dana)"). An undo is noted as the user's own change.
|
|
193
|
+
*
|
|
194
|
+
* ```ts
|
|
195
|
+
* const review = createReview({ api: () => api, setRows, onApply: baseReviewApplied(() => api) })
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export function baseReviewApplied(api) {
|
|
199
|
+
return (applied, how, next) => {
|
|
200
|
+
const ctrl = gridOf(typeof api === 'function' ? api() : api);
|
|
201
|
+
if (!ctrl)
|
|
202
|
+
return;
|
|
203
|
+
const gridApi = ctrl.buildApi?.();
|
|
204
|
+
const idOf = gridApi?.getOption?.('getRowId');
|
|
205
|
+
const rows = new Map();
|
|
206
|
+
(next ?? gridApi?.getData?.() ?? []).forEach((r, i) => rows.set(String(idOf ? idOf(r, i) : i), r));
|
|
207
|
+
const columnOf = new Map((ctrl.allColumns ?? []).map((c) => [c.columnDef?.field, c.id]));
|
|
208
|
+
for (const p of applied) {
|
|
209
|
+
const row = rows.get(p.rowId);
|
|
210
|
+
const columnId = columnOf.get(p.field);
|
|
211
|
+
if (!row || !columnId)
|
|
212
|
+
continue;
|
|
213
|
+
stampModified(ctrl, row, columnId);
|
|
214
|
+
noteChange(ctrl, p.rowId, columnId, row[p.field], undefined, how === 'undo' ? undefined : p.source.label);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
187
218
|
/** The record's activity: what a cell now holds after an edit. */
|
|
188
219
|
function noteEdit(ctrl, row, columnId) {
|
|
189
220
|
if (!row)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type FacetOption = {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
hint?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* The checklist as the cells show it. Exported for tests and for a custom
|
|
8
|
+
* menu; `enableFilterLabels` wires it into every grid.
|
|
9
|
+
*/
|
|
10
|
+
export declare function labelFacetOptions(ctrl: any, column: any, options: ReadonlyArray<FacetOption>): FacetOption[];
|
|
11
|
+
/**
|
|
12
|
+
* Label every grid's filter checklists as their cells show them. Idempotent;
|
|
13
|
+
* also invoked by {@link installEnterprise}.
|
|
14
|
+
*/
|
|
15
|
+
export declare function enableFilterLabels(): void;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filter checklist labels - the column filter's value list shows each value
|
|
3
|
+
* the way its cell shows it, while the filter still matches the raw value. A
|
|
4
|
+
* status stored as MARKED_AS_FAILED and drawn as "Failed" is offered as
|
|
5
|
+
* "Failed", so a column's accessor can stay the raw value that sorting needs.
|
|
6
|
+
*
|
|
7
|
+
* The label comes from the first of these the column has: a `cell` renderer
|
|
8
|
+
* that returns a string, static `editorOptions` labels, then `formatter` /
|
|
9
|
+
* `format`. Text values are ordered by label; number and date values stay in
|
|
10
|
+
* value order. It plugs into the grid's `facetOptions` seam, which runs in the
|
|
11
|
+
* menu chunk.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { enableFilterLabels } from '@svgrid/enterprise'
|
|
15
|
+
* enableFilterLabels()
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
import { columnDataType, registerGridExtension } from '@svgrid/grid';
|
|
19
|
+
import { hasValidLicense } from './license.js';
|
|
20
|
+
import { emitUnlicensedNudge } from './watermark.js';
|
|
21
|
+
/** The text a cell shows for `raw` in `row`, or null when the column draws markup only. */
|
|
22
|
+
function cellText(ctrl, column, raw, row) {
|
|
23
|
+
const def = column.columnDef;
|
|
24
|
+
if (typeof def.cell === 'function') {
|
|
25
|
+
const rendered = def.cell({
|
|
26
|
+
cell: { id: `${row.id}_${column.id}`, row, column, getValue: () => raw, getContext: () => ({}) },
|
|
27
|
+
row,
|
|
28
|
+
column,
|
|
29
|
+
table: ctrl.grid,
|
|
30
|
+
getValue: () => raw,
|
|
31
|
+
});
|
|
32
|
+
if (typeof rendered === 'string' || typeof rendered === 'number')
|
|
33
|
+
return String(rendered);
|
|
34
|
+
}
|
|
35
|
+
// Static lists only: a function or promise source would fetch.
|
|
36
|
+
if (Array.isArray(def.editorOptions))
|
|
37
|
+
return ctrl.formatListCellValue(column, raw, row);
|
|
38
|
+
if (def.formatter || def.format)
|
|
39
|
+
return ctrl.formatCellValue(column, raw, row);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The checklist as the cells show it. Exported for tests and for a custom
|
|
44
|
+
* menu; `enableFilterLabels` wires it into every grid.
|
|
45
|
+
*/
|
|
46
|
+
export function labelFacetOptions(ctrl, column, options) {
|
|
47
|
+
// One row per distinct value, found once per menu open.
|
|
48
|
+
const wanted = new Set(options.map((o) => o.value));
|
|
49
|
+
const rowFor = new Map();
|
|
50
|
+
for (const row of ctrl.grid.getRowModel().rows) {
|
|
51
|
+
if (rowFor.size === wanted.size)
|
|
52
|
+
break;
|
|
53
|
+
const raw = row.getCellValueByColumnId(column.id);
|
|
54
|
+
const key = String(raw ?? '');
|
|
55
|
+
if (wanted.has(key) && !rowFor.has(key))
|
|
56
|
+
rowFor.set(key, { raw, row });
|
|
57
|
+
}
|
|
58
|
+
const out = options.map((o) => {
|
|
59
|
+
const hit = o.value === '' ? undefined : rowFor.get(o.value);
|
|
60
|
+
const text = hit ? cellText(ctrl, column, hit.raw, hit.row) : null;
|
|
61
|
+
return text == null ? o : { ...o, label: text };
|
|
62
|
+
});
|
|
63
|
+
// Numbers and dates keep value order ("$1,000" would collate before "$200").
|
|
64
|
+
const type = columnDataType(column.columnDef);
|
|
65
|
+
if (type === 'number' || type === 'date' || type === 'dateString')
|
|
66
|
+
return out;
|
|
67
|
+
return out.sort((a, b) => a.value === '' || b.value === ''
|
|
68
|
+
? (a.value === '' ? 0 : 1) - (b.value === '' ? 0 : 1)
|
|
69
|
+
: a.label.localeCompare(b.label, undefined, { numeric: true }));
|
|
70
|
+
}
|
|
71
|
+
let enabled = false;
|
|
72
|
+
/**
|
|
73
|
+
* Label every grid's filter checklists as their cells show them. Idempotent;
|
|
74
|
+
* also invoked by {@link installEnterprise}.
|
|
75
|
+
*/
|
|
76
|
+
export function enableFilterLabels() {
|
|
77
|
+
if (enabled)
|
|
78
|
+
return;
|
|
79
|
+
enabled = true;
|
|
80
|
+
registerGridExtension({ facetOptions: labelFacetOptions });
|
|
81
|
+
if (!hasValidLicense())
|
|
82
|
+
emitUnlicensedNudge();
|
|
83
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,10 @@ export { enableBoardView, SvGridBoard } from './board.js';
|
|
|
12
12
|
export { enableGalleryView, SvGridGallery } from './gallery.js';
|
|
13
13
|
export * from './gantt/index.js';
|
|
14
14
|
export { enableSelectionBar, SvGridSelectionBar } from './selection-bar.js';
|
|
15
|
+
export { enableRelativeDateFilters, resolveRelativeDateFilter, compileRelativeDateFilter, isRelativeDateOperator, relativeDateOperators, RELATIVE_DATE_OPERATOR_IDS, type RelativeDateOperator, } from './relative-dates.js';
|
|
16
|
+
export { enableFilterLabels, labelFacetOptions } from './filter-labels.js';
|
|
17
|
+
export { enableRowCount, getRowCounts, SvGridRowCount } from './row-count.js';
|
|
18
|
+
export { blanksLast, blanksFirst, type BlanksSortType } from './sort-blanks.js';
|
|
15
19
|
export { applyBulkEdit, bulkEditableFields, bulkEditInitialValues, coerceBulkValue, type BulkEditField, type BulkEditResult } from './bulk-edit.js';
|
|
16
20
|
export { default as SvGridBulkEditDrawer } from './SvGridBulkEditDrawer.svelte';
|
|
17
21
|
export { enablePivot } from './pivot-enable.js';
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,13 @@ export * from './gantt/index.js';
|
|
|
33
33
|
// the renderer so `<SvGrid selectionBar={...}>` floats a bar over the grid while
|
|
34
34
|
// rows are selected. The prop + its config types live in @svgrid/grid.
|
|
35
35
|
export { enableSelectionBar, SvGridSelectionBar } from './selection-bar.js';
|
|
36
|
+
// Filter and sort additions for every grid (Pro), each through a grid seam so
|
|
37
|
+
// the free grid carries none of it: relative date operators, checklist labels
|
|
38
|
+
// taken from the cells, a status-bar row count, and blanks held at one end.
|
|
39
|
+
export { enableRelativeDateFilters, resolveRelativeDateFilter, compileRelativeDateFilter, isRelativeDateOperator, relativeDateOperators, RELATIVE_DATE_OPERATOR_IDS, } from './relative-dates.js';
|
|
40
|
+
export { enableFilterLabels, labelFacetOptions } from './filter-labels.js';
|
|
41
|
+
export { enableRowCount, getRowCounts, SvGridRowCount } from './row-count.js';
|
|
42
|
+
export { blanksLast, blanksFirst } from './sort-blanks.js';
|
|
36
43
|
// Bulk edit engine behind the bar's `editFields` button - exported so an app
|
|
37
44
|
// can drive the same write from its own UI.
|
|
38
45
|
export { applyBulkEdit, bulkEditableFields, bulkEditInitialValues, coerceBulkValue } from './bulk-edit.js';
|
package/dist/install.js
CHANGED
|
@@ -12,6 +12,9 @@ import { enableBoardView } from './board.js';
|
|
|
12
12
|
import { enableGalleryView } from './gallery.js';
|
|
13
13
|
import { enableGanttView } from './gantt/gantt.js';
|
|
14
14
|
import { enableSelectionBar } from './selection-bar.js';
|
|
15
|
+
import { enableRelativeDateFilters } from './relative-dates.js';
|
|
16
|
+
import { enableFilterLabels } from './filter-labels.js';
|
|
17
|
+
import { enableRowCount } from './row-count.js';
|
|
15
18
|
import { enableAdvancedFilter } from './advanced-filter-enable.js';
|
|
16
19
|
import { enablePivot } from './pivot-enable.js';
|
|
17
20
|
import { registerSheetKeymap } from './sheet-enable.js';
|
|
@@ -52,6 +55,11 @@ export function installEnterprise(api) {
|
|
|
52
55
|
// Register the Gantt view (no-op without the `gantt` prop).
|
|
53
56
|
enableGanttView();
|
|
54
57
|
enableSelectionBar();
|
|
58
|
+
// Relative date operators, cell-text checklist labels and the status-bar row
|
|
59
|
+
// count (each a no-op until a grid uses it).
|
|
60
|
+
enableRelativeDateFilters();
|
|
61
|
+
enableFilterLabels();
|
|
62
|
+
enableRowCount();
|
|
55
63
|
// Register the export engine so built-in AI exports (aiExport) can write the
|
|
56
64
|
// enterprise formats (xlsx / pdf / ...); free grids without it get the plan only.
|
|
57
65
|
registerExportProvider(exportGrid);
|
package/dist/node/studio.js
CHANGED
|
@@ -2242,8 +2242,15 @@ var kinds = /* @__PURE__ */ new Map();
|
|
|
2242
2242
|
function getPredicateKind(type) {
|
|
2243
2243
|
return kinds.get(type);
|
|
2244
2244
|
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2245
|
+
Object.fromEntries(Object.entries({
|
|
2246
|
+
ISBLANK: "isBlank",
|
|
2247
|
+
ISNOTBLANK: "isNotBlank",
|
|
2248
|
+
ISTODAY: "today",
|
|
2249
|
+
BEFORETODAY: "beforeToday",
|
|
2250
|
+
AFTERTODAY: "afterToday",
|
|
2251
|
+
INNEXT7DAYS: "next7Days",
|
|
2252
|
+
INLAST7DAYS: "last7Days"
|
|
2253
|
+
}).map(([kw, op]) => [op, kw]));
|
|
2247
2254
|
/** Every column id referenced anywhere in a predicate (deduped, in order). */
|
|
2248
2255
|
function collectColumnRefs(expr) {
|
|
2249
2256
|
const out = /* @__PURE__ */ new Set();
|
|
@@ -9336,7 +9343,7 @@ var GENERATED_UI_SURFACE = {
|
|
|
9336
9343
|
"key": "statusBar",
|
|
9337
9344
|
"label": "Status Bar",
|
|
9338
9345
|
"type": "boolean",
|
|
9339
|
-
"description": "Excel-style status bar under the grid showing live aggregates of the selected cell range (count, numeric count, sum, average, min, max). `true` shows the default set; pass `{ aggregates: [...] }` to choose which.
|
|
9346
|
+
"description": "Excel-style status bar under the grid showing live aggregates of the selected cell range (count, numeric count, sum, average, min, max). `true` shows the default set; pass `{ aggregates: [...] }` to choose which. The aggregates need `enableCellSelection`. `rows: true` adds a row count that is always shown, \"250 rows\" or \"12 of 250 rows\" while filters hide some, once `@svgrid/enterprise`'s `enableRowCount()` has run. `{ rows: true, aggregates: [] }` shows the count alone.",
|
|
9340
9347
|
"group": "common"
|
|
9341
9348
|
},
|
|
9342
9349
|
{
|
|
@@ -16499,7 +16506,7 @@ function hasFieldConditions(schema) {
|
|
|
16499
16506
|
*
|
|
16500
16507
|
* `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
|
|
16501
16508
|
*/
|
|
16502
|
-
var SVGRID_VERSION = "3.1.
|
|
16509
|
+
var SVGRID_VERSION = "3.1.23";
|
|
16503
16510
|
/**
|
|
16504
16511
|
* The version of `@svgrid/grid`, which releases on its own line: enterprise is
|
|
16505
16512
|
* on 3.1.x while the grid is on 3.0.x.
|
|
@@ -16512,7 +16519,7 @@ var SVGRID_VERSION = "3.1.21";
|
|
|
16512
16519
|
*
|
|
16513
16520
|
* `version.test.ts` asserts this matches packages/grid/package.json.
|
|
16514
16521
|
*/
|
|
16515
|
-
var GRID_VERSION = "3.0.
|
|
16522
|
+
var GRID_VERSION = "3.0.22";
|
|
16516
16523
|
//#endregion
|
|
16517
16524
|
//#region src/studio/emit-project.ts
|
|
16518
16525
|
var has = (blocks, kind) => blocks.some((b) => b.config.kind === kind);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The relative date operators' semantics, with no grid import: what the
|
|
3
|
+
* filter menu (relative-dates.ts) and the expression engine both run, so a
|
|
4
|
+
* server that evaluates expressions loads none of the grid.
|
|
5
|
+
*/
|
|
6
|
+
declare module '@svgrid/grid/filtering' {
|
|
7
|
+
interface FilterOperatorExtensions {
|
|
8
|
+
today: true;
|
|
9
|
+
beforeToday: true;
|
|
10
|
+
afterToday: true;
|
|
11
|
+
next7Days: true;
|
|
12
|
+
last7Days: true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** The relative date operator ids, in menu order. */
|
|
16
|
+
export declare const RELATIVE_DATE_OPERATOR_IDS: readonly ["today", "beforeToday", "afterToday", "next7Days", "last7Days"];
|
|
17
|
+
export type RelativeDateOperator = (typeof RELATIVE_DATE_OPERATOR_IDS)[number];
|
|
18
|
+
/** Whether `op` is one of the relative date operators. */
|
|
19
|
+
export declare function isRelativeDateOperator(op: string): op is RelativeDateOperator;
|
|
20
|
+
/**
|
|
21
|
+
* The test for one relative date operator. "Today" is read once, here, so a
|
|
22
|
+
* page left open past midnight keeps the old day until the filter changes.
|
|
23
|
+
* A blank or unparseable cell never matches.
|
|
24
|
+
*/
|
|
25
|
+
export declare function compileRelativeDateFilter(op: RelativeDateOperator, now?: Date): (cellValue: unknown) => boolean;
|
|
26
|
+
/**
|
|
27
|
+
* A relative date filter as the absolute one it means today, for a backend
|
|
28
|
+
* with no "today" of its own: `beforeToday` becomes `lessThan` today's date,
|
|
29
|
+
* `next7Days` becomes `between` today and a week out, and so on, with dates as
|
|
30
|
+
* local 'YYYY-MM-DD'. Any other filter is returned as it is.
|
|
31
|
+
*
|
|
32
|
+
* A server data source gets this applied for it. Under `externalFilter` the
|
|
33
|
+
* `onFiltersChange` payload keeps the relative operator, so a saved view still
|
|
34
|
+
* means "overdue" tomorrow; call this when you build the query.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveRelativeDateFilter<T extends {
|
|
37
|
+
operator: string;
|
|
38
|
+
value?: unknown;
|
|
39
|
+
valueTo?: unknown;
|
|
40
|
+
}>(filter: T, now?: Date): T;
|