@sisense/sdk-data 2.22.0 → 2.24.0
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/cjs/dimensional-model/attributes.d.ts +10 -2
- package/dist/cjs/dimensional-model/attributes.js +11 -9
- package/dist/cjs/dimensional-model/dimensions/dimensions.d.ts +1 -1
- package/dist/cjs/dimensional-model/dimensions/dimensions.js +20 -17
- package/dist/cjs/dimensional-model/dimensions/utils.js +4 -0
- package/dist/cjs/dimensional-model/filters/factory.d.ts +8 -8
- package/dist/cjs/dimensional-model/filters/factory.js +30 -7
- package/dist/cjs/dimensional-model/filters/filter-relations.d.ts +16 -1
- package/dist/cjs/dimensional-model/filters/filter-relations.js +50 -13
- package/dist/cjs/dimensional-model/filters/filters.js +2 -2
- package/dist/cjs/dimensional-model/interfaces.d.ts +12 -0
- package/dist/cjs/dimensional-model/measures/factory.d.ts +2 -2
- package/dist/cjs/dimensional-model/measures/factory.js +5 -2
- package/dist/cjs/dimensional-model/measures/measures.d.ts +2 -2
- package/dist/cjs/dimensional-model/measures/measures.js +4 -1
- package/dist/cjs/dimensional-model/types.d.ts +15 -9
- package/dist/cjs/dimensional-model/types.js +1 -0
- package/dist/cjs/utils.d.ts +16 -3
- package/dist/cjs/utils.js +20 -8
- package/dist/dimensional-model/attributes.d.ts +10 -2
- package/dist/dimensional-model/attributes.js +11 -9
- package/dist/dimensional-model/dimensions/dimensions.d.ts +1 -1
- package/dist/dimensional-model/dimensions/dimensions.js +20 -17
- package/dist/dimensional-model/dimensions/utils.js +4 -0
- package/dist/dimensional-model/filters/factory.d.ts +8 -8
- package/dist/dimensional-model/filters/factory.js +30 -7
- package/dist/dimensional-model/filters/filter-relations.d.ts +16 -1
- package/dist/dimensional-model/filters/filter-relations.js +50 -13
- package/dist/dimensional-model/filters/filters.js +3 -3
- package/dist/dimensional-model/interfaces.d.ts +12 -0
- package/dist/dimensional-model/measures/factory.d.ts +2 -2
- package/dist/dimensional-model/measures/factory.js +5 -2
- package/dist/dimensional-model/measures/measures.d.ts +2 -2
- package/dist/dimensional-model/measures/measures.js +4 -1
- package/dist/dimensional-model/types.d.ts +15 -9
- package/dist/dimensional-model/types.js +1 -0
- package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -1
- package/dist/utils.d.ts +16 -3
- package/dist/utils.js +17 -6
- package/package.json +2 -2
|
@@ -113,14 +113,21 @@ export function isTrivialSingleNodeRelations(relations) {
|
|
|
113
113
|
/**
|
|
114
114
|
* Calculates new relations based on the changes in filters.
|
|
115
115
|
*
|
|
116
|
+
* @param prevFilters - The previous array of filters that the relations were built for.
|
|
117
|
+
* @param prevRelations - The previous relation rules.
|
|
118
|
+
* @param newFilters - The updated array of filters to build new relations for.
|
|
119
|
+
* @param options - Optional flags controlling how the diff is computed:
|
|
120
|
+
* - `shouldReplaceSameAttributeFilters`: when `true`, a new filter on the same attribute as
|
|
121
|
+
* an existing one (but with a different GUID) is treated as an in-place replacement rather
|
|
122
|
+
* than a remove + add pair, preserving the original relation tree structure.
|
|
116
123
|
* @internal
|
|
117
124
|
*/
|
|
118
|
-
export function calculateNewRelations(prevFilters, prevRelations, newFilters) {
|
|
125
|
+
export function calculateNewRelations(prevFilters, prevRelations, newFilters, options = {}) {
|
|
119
126
|
// If there are no previous relations - no need to recalculate them
|
|
120
127
|
if (prevRelations === null) {
|
|
121
128
|
return null;
|
|
122
129
|
}
|
|
123
|
-
const performedActions = diffFilters(prevFilters, newFilters);
|
|
130
|
+
const performedActions = diffFilters(prevFilters, newFilters, options.shouldReplaceSameAttributeFilters);
|
|
124
131
|
if (performedActions.length === 0) {
|
|
125
132
|
return prevRelations;
|
|
126
133
|
}
|
|
@@ -130,6 +137,8 @@ export function calculateNewRelations(prevFilters, prevRelations, newFilters) {
|
|
|
130
137
|
return addFilterToRelations(action.payload, relations);
|
|
131
138
|
case 'remove':
|
|
132
139
|
return removeFilterFromRelations(action.payload, relations);
|
|
140
|
+
case 'replace':
|
|
141
|
+
return getRelationsWithReplacedFilter(relations, action.payload.prevFilter, action.payload.newFilter);
|
|
133
142
|
}
|
|
134
143
|
}, prevRelations);
|
|
135
144
|
}
|
|
@@ -170,26 +179,54 @@ export function getRelationsWithReplacedFilter(relations, filterToReplace, newFi
|
|
|
170
179
|
* Compares two arrays of Filter objects and determines the actions needed
|
|
171
180
|
* to transform prevFilters into newFilters.
|
|
172
181
|
*
|
|
182
|
+
* When `shouldReplaceSameAttributeFilters` is enabled, a new filter whose attribute matches
|
|
183
|
+
* an existing one (same `getFilterCompareId`) but has a different GUID is emitted as a single
|
|
184
|
+
* `replace` action instead of a `remove` + `add` pair. This preserves the relation tree node
|
|
185
|
+
* at the original position rather than appending the new filter with AND at the root.
|
|
186
|
+
* The disabled existing filters are excluded from the same-attribute replacement check
|
|
187
|
+
* and will therefore never be replaced in-place.
|
|
188
|
+
*
|
|
173
189
|
* @param prevFilters - The original array of filters.
|
|
174
190
|
* @param newFilters - The updated array of filters.
|
|
175
|
-
* @param
|
|
191
|
+
* @param shouldReplaceSameAttributeFilters - Optional flag to enable same-attribute filter replacement.
|
|
176
192
|
* @returns An array of FilterAction objects representing the changes.
|
|
177
193
|
*/
|
|
178
|
-
function diffFilters(prevFilters, newFilters) {
|
|
194
|
+
function diffFilters(prevFilters, newFilters, shouldReplaceSameAttributeFilters = false) {
|
|
179
195
|
const actions = [];
|
|
180
|
-
//
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
196
|
+
// Track which filters from each side have already been matched to avoid double-counting.
|
|
197
|
+
const matchedPrevFilters = new Set();
|
|
198
|
+
const matchedNewFilters = new Set();
|
|
199
|
+
if (shouldReplaceSameAttributeFilters) {
|
|
200
|
+
prevFilters.forEach((prevFilter, prevIdx) => {
|
|
201
|
+
// Disabled filters are never eligible for in-place replacement.
|
|
202
|
+
if (prevFilter.config.disabled) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// Look for a new filter on the same attribute with a different GUID.
|
|
206
|
+
const newIdx = newFilters.findIndex((newFilter, idx) => !matchedNewFilters.has(idx) &&
|
|
207
|
+
!areFiltersEqualForRelations(prevFilter, newFilter) &&
|
|
208
|
+
getFilterCompareId(prevFilter) === getFilterCompareId(newFilter));
|
|
209
|
+
if (newIdx !== -1) {
|
|
210
|
+
actions.push({ type: 'replace', payload: { prevFilter, newFilter: newFilters[newIdx] } });
|
|
211
|
+
matchedPrevFilters.add(prevIdx);
|
|
212
|
+
matchedNewFilters.add(newIdx);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
// Removals: prev filters not matched by GUID in new filters (and not already handled as replace).
|
|
217
|
+
prevFilters.forEach((prevFilter, prevIdx) => {
|
|
218
|
+
if (matchedPrevFilters.has(prevIdx))
|
|
219
|
+
return;
|
|
220
|
+
const existsInNew = newFilters.some((newFilter) => areFiltersEqualForRelations(prevFilter, newFilter));
|
|
186
221
|
if (!existsInNew) {
|
|
187
222
|
actions.push({ type: 'remove', payload: prevFilter });
|
|
188
223
|
}
|
|
189
224
|
});
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
225
|
+
// Additions: new filters not matched by GUID in prev filters (and not already handled as replace).
|
|
226
|
+
newFilters.forEach((newFilter, newIdx) => {
|
|
227
|
+
if (matchedNewFilters.has(newIdx))
|
|
228
|
+
return;
|
|
229
|
+
const existsInPrev = prevFilters.some((prevFilter) => areFiltersEqualForRelations(newFilter, prevFilter));
|
|
193
230
|
if (!existsInPrev) {
|
|
194
231
|
actions.push({ type: 'add', payload: newFilter });
|
|
195
232
|
}
|
|
@@ -5,7 +5,7 @@ import omit from 'lodash-es/omit.js';
|
|
|
5
5
|
import { TranslatableError } from '../../translation/translatable-error.js';
|
|
6
6
|
import { DimensionalElement } from '../base.js';
|
|
7
7
|
import { create } from '../factory.js';
|
|
8
|
-
import { isDimensionalBaseMeasure } from '../measures/measures.js';
|
|
8
|
+
import { isDimensionalBaseMeasure, isDimensionalCalculatedMeasure } from '../measures/measures.js';
|
|
9
9
|
import { DateLevels, MetadataTypes } from '../types.js';
|
|
10
10
|
import { getDefaultBaseFilterConfig, getDefaultMembersFilterConfig, } from './filter-config-utils.js';
|
|
11
11
|
/**
|
|
@@ -470,7 +470,7 @@ export class MeasureFilter extends DoubleOperatorFilter {
|
|
|
470
470
|
return AbstractFilter.disabledJaql(nested);
|
|
471
471
|
}
|
|
472
472
|
const result = super.jaql(nested);
|
|
473
|
-
if (isDimensionalBaseMeasure(this.measure)) {
|
|
473
|
+
if (isDimensionalBaseMeasure(this.measure) || isDimensionalCalculatedMeasure(this.measure)) {
|
|
474
474
|
Object.entries(this.measure.jaql().jaql).forEach(([key, value]) => {
|
|
475
475
|
result.jaql[key] = value;
|
|
476
476
|
});
|
|
@@ -561,7 +561,7 @@ export class MeasureRankingFilter extends AbstractFilter {
|
|
|
561
561
|
return AbstractFilter.disabledJaql(nested);
|
|
562
562
|
}
|
|
563
563
|
const result = super.jaql(nested);
|
|
564
|
-
if (isDimensionalBaseMeasure(this.measure)) {
|
|
564
|
+
if (isDimensionalBaseMeasure(this.measure) || isDimensionalCalculatedMeasure(this.measure)) {
|
|
565
565
|
Object.entries(this.measure.jaql().jaql).forEach(([key, value]) => {
|
|
566
566
|
result.jaql[key] = value;
|
|
567
567
|
});
|
|
@@ -82,6 +82,18 @@ export interface Element {
|
|
|
82
82
|
* @internal
|
|
83
83
|
*/
|
|
84
84
|
composeCode?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Merged from DataSourceField. It is used for the aggregation filtering
|
|
87
|
+
*
|
|
88
|
+
* @internal
|
|
89
|
+
*/
|
|
90
|
+
readonly merged?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Indexed from DataSourceField. It is used for the aggregation filtering
|
|
93
|
+
*
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
readonly indexed?: boolean;
|
|
85
97
|
}
|
|
86
98
|
/**
|
|
87
99
|
* Base interface for measure, which is typically numeric aggregation over {@link Attribute}(s).
|
|
@@ -80,13 +80,13 @@ export declare const RankingSortTypes: {
|
|
|
80
80
|
* ```
|
|
81
81
|
* @param title - Title of the measure to be displayed in legend
|
|
82
82
|
* @param formula - Formula to be used for the measure
|
|
83
|
-
* @param context -
|
|
83
|
+
* @param context - Optional formula context as a map of strings to attributes, measures, or filters
|
|
84
84
|
* @param format - Optional format string for the measure
|
|
85
85
|
* @param description - Optional description of the measure
|
|
86
86
|
* @returns A calculated measure instance
|
|
87
87
|
* @group Advanced Analytics
|
|
88
88
|
*/
|
|
89
|
-
export declare const customFormula: (title: string, formula: string, context
|
|
89
|
+
export declare const customFormula: (title: string, formula: string, context?: CustomFormulaContext, format?: string, description?: string) => CalculatedMeasure;
|
|
90
90
|
/**
|
|
91
91
|
* Creates an aggregated measure.
|
|
92
92
|
*
|
|
@@ -120,7 +120,7 @@ function measureFunction(measure, name, func, options) {
|
|
|
120
120
|
* ```
|
|
121
121
|
* @param title - Title of the measure to be displayed in legend
|
|
122
122
|
* @param formula - Formula to be used for the measure
|
|
123
|
-
* @param context -
|
|
123
|
+
* @param context - Optional formula context as a map of strings to attributes, measures, or filters
|
|
124
124
|
* @param format - Optional format string for the measure
|
|
125
125
|
* @param description - Optional description of the measure
|
|
126
126
|
* @returns A calculated measure instance
|
|
@@ -128,7 +128,10 @@ function measureFunction(measure, name, func, options) {
|
|
|
128
128
|
*/
|
|
129
129
|
export const customFormula = withComposeCodeForMeasure((title, formula, context, format, description) => {
|
|
130
130
|
// context keys must be in brackets
|
|
131
|
-
const newContext = Object.fromEntries(Object.entries(context).map(([key, val]) => [
|
|
131
|
+
const newContext = Object.fromEntries(Object.entries(context !== null && context !== void 0 ? context : {}).map(([key, val]) => [
|
|
132
|
+
key.startsWith('[') ? key : `[${key}]`,
|
|
133
|
+
val,
|
|
134
|
+
]));
|
|
132
135
|
return new DimensionalCalculatedMeasure(title, formula, newContext, format, description);
|
|
133
136
|
}, 'customFormula');
|
|
134
137
|
function arithmetic(operand1, operator, operand2, name, withParentheses) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DimensionalElement } from '../base.js';
|
|
2
2
|
import { Attribute, BaseMeasure, CalculatedMeasure, Measure, MeasureContext, MeasureTemplate } from '../interfaces.js';
|
|
3
|
-
import { AnyObject, JaqlDataSource, JSONObject, Sort } from '../types.js';
|
|
3
|
+
import { AggregationType, AnyObject, JaqlDataSource, JSONObject, Sort } from '../types.js';
|
|
4
4
|
/**
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
@@ -57,7 +57,7 @@ export declare class DimensionalBaseMeasure extends AbstractMeasure implements B
|
|
|
57
57
|
* @internal
|
|
58
58
|
*/
|
|
59
59
|
readonly __serializable: string;
|
|
60
|
-
static aggregationFromJAQL(agg: string):
|
|
60
|
+
static aggregationFromJAQL(agg: string): AggregationType;
|
|
61
61
|
static aggregationToJAQL(agg: string): string;
|
|
62
62
|
constructor(name: string, attribute: Attribute, agg: string, format?: string, desc?: string, sort?: Sort, dataSource?: JaqlDataSource, composeCode?: string);
|
|
63
63
|
/**
|
|
@@ -235,7 +235,10 @@ export class DimensionalCalculatedMeasure extends AbstractMeasure {
|
|
|
235
235
|
};
|
|
236
236
|
const context = {};
|
|
237
237
|
const keys = Object.getOwnPropertyNames(this.context);
|
|
238
|
-
keys.forEach((k) =>
|
|
238
|
+
keys.forEach((k) => {
|
|
239
|
+
const v = this.context[k];
|
|
240
|
+
context[k] = v && typeof v.jaql === 'function' ? v.jaql(true) : v;
|
|
241
|
+
});
|
|
239
242
|
r.jaql.context = context;
|
|
240
243
|
if (this._format) {
|
|
241
244
|
r.format = { number: this._format };
|
|
@@ -9,24 +9,29 @@ export type { JaqlDataSource, JaqlDataSourceForDto };
|
|
|
9
9
|
*/
|
|
10
10
|
export declare const AggregationTypes: {
|
|
11
11
|
/** Sum aggregation type */
|
|
12
|
-
Sum:
|
|
12
|
+
readonly Sum: "sum";
|
|
13
13
|
/** Average aggregation type */
|
|
14
|
-
Average:
|
|
14
|
+
readonly Average: "avg";
|
|
15
15
|
/** Min aggregation type */
|
|
16
|
-
Min:
|
|
16
|
+
readonly Min: "min";
|
|
17
17
|
/** Max aggregation type */
|
|
18
|
-
Max:
|
|
18
|
+
readonly Max: "max";
|
|
19
19
|
/** Count aggregation type */
|
|
20
|
-
Count:
|
|
20
|
+
readonly Count: "count";
|
|
21
21
|
/** Count distinct aggregation type */
|
|
22
|
-
CountDistinct:
|
|
22
|
+
readonly CountDistinct: "countDistinct";
|
|
23
23
|
/** Median aggregation type */
|
|
24
|
-
Median:
|
|
24
|
+
readonly Median: "median";
|
|
25
25
|
/** Variance aggregation type */
|
|
26
|
-
Variance:
|
|
26
|
+
readonly Variance: "var";
|
|
27
27
|
/** Standard deviation aggregation type */
|
|
28
|
-
StandardDeviation:
|
|
28
|
+
readonly StandardDeviation: "stdev";
|
|
29
29
|
};
|
|
30
|
+
declare const aggTypes: ("sum" | "avg" | "min" | "max" | "count" | "countDistinct" | "median" | "var" | "stdev")[];
|
|
31
|
+
/**
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export declare type AggregationType = (typeof aggTypes)[number];
|
|
30
35
|
/**
|
|
31
36
|
* Different sort types.
|
|
32
37
|
*/
|
|
@@ -202,6 +207,7 @@ export declare type BaseJaql = {
|
|
|
202
207
|
jaql: FilterJaql;
|
|
203
208
|
};
|
|
204
209
|
};
|
|
210
|
+
indexed?: boolean;
|
|
205
211
|
merged?: boolean;
|
|
206
212
|
panel?: 'rows' | 'columns';
|
|
207
213
|
};
|