@sisense/sdk-data 1.10.0 → 1.11.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.
@@ -104,6 +104,7 @@ export declare class DimensionalLevelAttribute extends DimensionalAttribute impl
104
104
  dateTimeLevel?: undefined;
105
105
  };
106
106
  static translateJaqlToGranularity(json: any): string;
107
+ static getDefaultFormatForGranularity(granularity: string): string;
107
108
  }
108
109
  /**
109
110
  * Creates an Attribute instance from the given JSON object.
@@ -253,6 +253,37 @@ export class DimensionalLevelAttribute extends DimensionalAttribute {
253
253
  return returnUnsupported(json.level);
254
254
  }
255
255
  }
256
+ static getDefaultFormatForGranularity(granularity) {
257
+ switch (granularity) {
258
+ case DateLevels.Years:
259
+ return 'yyyy';
260
+ case DateLevels.Quarters:
261
+ return 'Q yyyy';
262
+ case DateLevels.Months:
263
+ return 'yyyy-MM';
264
+ case DateLevels.Weeks:
265
+ return 'ww yyyy';
266
+ case DateLevels.Days:
267
+ return 'yyyy-MM-dd';
268
+ case DateLevels.Hours:
269
+ // eslint-disable-next-line sonarjs/no-duplicate-string
270
+ return 'yyyy-MM-dd HH:mm';
271
+ case DateLevels.MinutesRoundTo30:
272
+ return 'yyyy-MM-dd HH:mm';
273
+ case DateLevels.MinutesRoundTo15:
274
+ return 'yyyy-MM-dd HH:mm';
275
+ case DateLevels.AggHours:
276
+ return 'HH:mm';
277
+ case DateLevels.AggMinutesRoundTo30:
278
+ return 'HH:mm';
279
+ case DateLevels.AggMinutesRoundTo15:
280
+ return 'HH:mm';
281
+ case DateLevels.AggMinutesRoundTo1:
282
+ return 'HH:mm';
283
+ default:
284
+ return '';
285
+ }
286
+ }
256
287
  }
257
288
  /**
258
289
  * Creates an Attribute instance from the given JSON object.
@@ -92,6 +92,12 @@ declare abstract class AbstractFilter extends DimensionalElement implements Filt
92
92
  * Global filter identifier
93
93
  */
94
94
  readonly guid: string;
95
+ /**
96
+ * Boolean flag whether the filter is disabled
97
+ *
98
+ * @internal
99
+ */
100
+ disabled: boolean;
95
101
  constructor(att: Attribute, filterType: string);
96
102
  get name(): string;
97
103
  /**
@@ -25,7 +25,7 @@ export const TextOperators = {
25
25
  DoesntEqual: 'doesntEqual',
26
26
  DoesntStartWith: 'doesntStartWith',
27
27
  DoesntContain: 'doesntContain',
28
- DoesntEndWith: 'doesntEndWidth',
28
+ DoesntEndWith: 'doesntEndWith',
29
29
  Like: 'like',
30
30
  };
31
31
  /**
@@ -99,6 +99,7 @@ class AbstractFilter extends DimensionalElement {
99
99
  AbstractFilter.checkAttributeSupport(att);
100
100
  this.attribute = att;
101
101
  this.guid = guidFast(13);
102
+ this.disabled = false;
102
103
  }
103
104
  get name() {
104
105
  return hash(this.jaql());
@@ -118,6 +119,10 @@ class AbstractFilter extends DimensionalElement {
118
119
  * @param nested - defines whether the JAQL is nested within parent JAQL statement or a root JAQL element
119
120
  */
120
121
  jaql(nested) {
122
+ // if the filter is disabled, return empty filter JAQL
123
+ if (this.disabled) {
124
+ return nested ? { filter: {} } : { jaql: { filter: {} } };
125
+ }
121
126
  const result = this.attribute.jaql(false);
122
127
  const level = this.attribute;
123
128
  if (level.getFormat && level.getFormat() !== undefined) {
@@ -349,6 +354,10 @@ export class MeasureFilter extends DoubleOperatorFilter {
349
354
  return result;
350
355
  }
351
356
  jaql(nested) {
357
+ // if the filter is disabled, return empty filter JAQL
358
+ if (this.disabled) {
359
+ return nested ? { filter: {} } : { jaql: { filter: {} } };
360
+ }
352
361
  const result = super.jaql(nested);
353
362
  if (this.measure instanceof DimensionalBaseMeasure) {
354
363
  Object.entries(this.measure.jaql().jaql).forEach(([key, value]) => {
@@ -11,7 +11,7 @@ import { FilterJaqlInternal, RankingFilterJaql } from './types.js';
11
11
  * @param dataType - Data type
12
12
  * @returns attribute or level attribute
13
13
  */
14
- export declare const createAttributeHelper: (dim: string, table: string, column: string, level: string | undefined, dataType: string) => Attribute | LevelAttribute;
14
+ export declare const createAttributeHelper: (dim: string, table: string | undefined, column: string, level: string | undefined, dataType: string) => Attribute | LevelAttribute;
15
15
  /**
16
16
  * Creates an attribute or level attribute from the provided filter JAQL object
17
17
  *
@@ -30,7 +30,7 @@ export declare const createAttributeFromFilterJaql: (jaql: FilterJaql | FilterJa
30
30
  * @param agg - Aggregation function
31
31
  * @returns measure
32
32
  */
33
- export declare const createMeasureHelper: (dim: string, table: string, column: string, level: string | undefined, dataType: string, agg: string) => BaseMeasure;
33
+ export declare const createMeasureHelper: (dim: string, table: string | undefined, column: string, level: string | undefined, dataType: string, agg: string) => BaseMeasure;
34
34
  /**
35
35
  * Creates a measure from the provided filter JAQL object
36
36
  *
@@ -14,17 +14,20 @@ const DATA_MODEL_MODULE_NAME = 'DM';
14
14
  * @returns attribute or level attribute
15
15
  */
16
16
  export const createAttributeHelper = (dim, table, column, level, dataType) => {
17
+ // if table is undefined, extract it from dim
18
+ const dimTable = table !== null && table !== void 0 ? table : dim.slice(1, -1).split('.')[0];
17
19
  if (level) {
18
20
  const dateLevel = DimensionalLevelAttribute.translateJaqlToGranularity({ level });
19
- const levelAttribute = new DimensionalLevelAttribute(column, dim, dateLevel);
20
- levelAttribute.composeCode = normalizeAttributeName(table, column, level, DATA_MODEL_MODULE_NAME);
21
+ const format = DimensionalLevelAttribute.getDefaultFormatForGranularity(dateLevel);
22
+ const levelAttribute = new DimensionalLevelAttribute(column, dim, dateLevel, format);
23
+ levelAttribute.composeCode = normalizeAttributeName(dimTable, column, level, DATA_MODEL_MODULE_NAME);
21
24
  return levelAttribute;
22
25
  }
23
26
  const attributeType = isNumber(dataType)
24
27
  ? MetadataTypes.NumericAttribute
25
28
  : MetadataTypes.TextAttribute;
26
29
  const attribute = new DimensionalAttribute(column, dim, attributeType);
27
- attribute.composeCode = normalizeAttributeName(table, column, undefined, DATA_MODEL_MODULE_NAME);
30
+ attribute.composeCode = normalizeAttributeName(dimTable, column, undefined, DATA_MODEL_MODULE_NAME);
28
31
  return attribute;
29
32
  };
30
33
  /**
@@ -35,12 +35,8 @@ export const getSelectedConditionOption = (filter) => {
35
35
  return ConditionFilterType.IS_WITHIN;
36
36
  if (isGreaterThanCondition(filter))
37
37
  return ConditionFilterType.GREATER_THAN;
38
- if (isGreaterThanOrEqualCondition(filter))
39
- return ConditionFilterType.GREATER_THAN_OR_EQUAL;
40
38
  if (isLessThanCondition(filter))
41
39
  return ConditionFilterType.LESS_THAN;
42
- if (isLessThanOrEqualCondition(filter))
43
- return ConditionFilterType.LESS_THAN_OR_EQUAL;
44
40
  if (isEqualsCondition(filter))
45
41
  return ConditionFilterType.EQUALS;
46
42
  if (isNotEqualCondition(filter))
@@ -61,14 +57,19 @@ export const getSelectedConditionOption = (filter) => {
61
57
  return ConditionFilterType.ENDS_WITH;
62
58
  if (isStartsWithCondition(filter))
63
59
  return ConditionFilterType.STARTS_WITH;
64
- if (isBetweenCondition(filter))
65
- return ConditionFilterType.BETWEEN;
66
60
  if (isNotBetweenCondition(filter))
67
61
  return ConditionFilterType.IS_NOT_BETWEEN;
68
62
  if (isMembersCondition(filter))
69
63
  return ConditionFilterType.IS;
70
64
  if (isMultipleCondition(filter))
71
65
  return ConditionFilterType.MULTIPLE_CONDITION;
66
+ // Need to verify BETWEEN case before the GREATER_THAN_OR_EQUAL and LESS_THAN_OR_EQUAL due to missing `filter.isBetween` property in some cases
67
+ if (isBetweenCondition(filter))
68
+ return ConditionFilterType.BETWEEN;
69
+ if (isGreaterThanOrEqualCondition(filter))
70
+ return ConditionFilterType.GREATER_THAN_OR_EQUAL;
71
+ if (isLessThanOrEqualCondition(filter))
72
+ return ConditionFilterType.LESS_THAN_OR_EQUAL;
72
73
  return ConditionFilterType.NONE;
73
74
  };
74
75
  /**
@@ -0,0 +1,5 @@
1
+ import { FilterJaql } from '../../types.js';
2
+ declare type FilterMatcher = (value?: string | number) => boolean;
3
+ /** @internal */
4
+ export declare function createFilterMatcher(filterJaql: FilterJaql): FilterMatcher;
5
+ export {};
@@ -0,0 +1,170 @@
1
+ import { getSelectedConditionOption } from './condition-filter-util.js';
2
+ import { isConditionFilter, isSpecificItemsFilter } from './filter-types-util.js';
3
+ import { ConditionFilterType, } from './types.js';
4
+ const defaultFormatter = (value) => {
5
+ if (value === undefined) {
6
+ return undefined;
7
+ }
8
+ return `${value}`;
9
+ };
10
+ const defaultDatetimeFormatter = (value) => {
11
+ if (value === undefined) {
12
+ return undefined;
13
+ }
14
+ return new Date(value).toISOString();
15
+ };
16
+ const defaultMatcher = () => false;
17
+ function createCombinedFilterMatcher(createFilterMatcherFn, filterJaql) {
18
+ const filter = filterJaql.filter;
19
+ if ('or' in filter) {
20
+ return (value) => {
21
+ return filter.or
22
+ .map((filterItem) => createFilterMatcherFn(Object.assign(Object.assign({}, filterJaql), { filter: filterItem })))
23
+ .reduce((acc, filterMatcher) => {
24
+ return acc || filterMatcher(value);
25
+ }, false);
26
+ };
27
+ }
28
+ if ('and' in filter) {
29
+ return (value) => {
30
+ return filter.and
31
+ .map((filterItem) => createFilterMatcherFn(Object.assign(Object.assign({}, filterJaql), { filter: filterItem })))
32
+ .reduce((acc, filterMatcher) => {
33
+ return acc && filterMatcher(value);
34
+ }, true);
35
+ };
36
+ }
37
+ return createFilterMatcherFn(filterJaql);
38
+ }
39
+ function createMembersFilterMatcher(filterJaql) {
40
+ const { datatype } = filterJaql;
41
+ const filter = filterJaql.filter;
42
+ const formatter = datatype === 'datetime' ? defaultDatetimeFormatter : defaultFormatter;
43
+ return (value) => {
44
+ const formattedMembers = filter.members.map(formatter);
45
+ const formattedValue = formatter(value);
46
+ return formattedMembers.includes(formattedValue);
47
+ };
48
+ }
49
+ function createExcludeMembersFilterMatcher(filterJaql) {
50
+ const { datatype } = filterJaql;
51
+ const filter = filterJaql.filter;
52
+ const formatter = datatype === 'datetime' ? defaultDatetimeFormatter : defaultFormatter;
53
+ return (value) => {
54
+ var _a, _b;
55
+ const formattedMembers = ((_b = (_a = filter.exclude) === null || _a === void 0 ? void 0 : _a.members) === null || _b === void 0 ? void 0 : _b.map(formatter)) || [];
56
+ const formattedValue = formatter(value);
57
+ return !formattedMembers.includes(formattedValue);
58
+ };
59
+ }
60
+ function createTextFilterMatcher(filterJaql) {
61
+ const filter = filterJaql.filter;
62
+ const conditionFilterType = getSelectedConditionOption(filter);
63
+ if (conditionFilterType === ConditionFilterType.STARTS_WITH) {
64
+ return (value) => {
65
+ return new RegExp(`^${filter.startsWith}`, 'i').test(value);
66
+ };
67
+ }
68
+ if (conditionFilterType === ConditionFilterType.ENDS_WITH) {
69
+ return (value) => {
70
+ return new RegExp(`${filter.endsWith}$`, 'i').test(value);
71
+ };
72
+ }
73
+ if (conditionFilterType === ConditionFilterType.CONTAINS) {
74
+ return (value) => {
75
+ return new RegExp(filter.contains, 'i').test(value);
76
+ };
77
+ }
78
+ if (conditionFilterType === ConditionFilterType.EQUALS) {
79
+ return (value) => {
80
+ return (value.localeCompare(filter.equals, undefined, {
81
+ sensitivity: 'base',
82
+ }) === 0);
83
+ };
84
+ }
85
+ if (conditionFilterType === ConditionFilterType.DOESNT_START_WITH) {
86
+ return (value) => {
87
+ return !new RegExp(`^${filter.doesntStartWith}`, 'i').test(value);
88
+ };
89
+ }
90
+ if (conditionFilterType === ConditionFilterType.DOESNT_END_WITH) {
91
+ return (value) => {
92
+ return !new RegExp(`${filter.doesntEndWith}$`, 'i').test(value);
93
+ };
94
+ }
95
+ if (conditionFilterType === ConditionFilterType.DOESNT_CONTAIN) {
96
+ return (value) => {
97
+ return !new RegExp(filter.doesntContain, 'i').test(value);
98
+ };
99
+ }
100
+ if (conditionFilterType === ConditionFilterType.DOESNT_EQUAL) {
101
+ return (value) => {
102
+ return (value.localeCompare(filter.doesntEqual, undefined, {
103
+ sensitivity: 'base',
104
+ }) !== 0);
105
+ };
106
+ }
107
+ return defaultMatcher;
108
+ }
109
+ function createNumericFilterMatcher(filterJaql) {
110
+ const filter = filterJaql.filter;
111
+ const conditionFilterType = getSelectedConditionOption(filter);
112
+ if (conditionFilterType === ConditionFilterType.EQUALS) {
113
+ return (value) => {
114
+ return Number(filter.equals) === Number(value);
115
+ };
116
+ }
117
+ if (conditionFilterType === ConditionFilterType.DOESNT_EQUAL) {
118
+ return (value) => {
119
+ return Number(filter.doesntEqual) !== Number(value);
120
+ };
121
+ }
122
+ if (conditionFilterType === ConditionFilterType.LESS_THAN) {
123
+ return (value) => {
124
+ return Number(value) < Number(filter.toNotEqual);
125
+ };
126
+ }
127
+ if (conditionFilterType === ConditionFilterType.GREATER_THAN) {
128
+ return (value) => {
129
+ return Number(value) > Number(filter.fromNotEqual);
130
+ };
131
+ }
132
+ if (conditionFilterType === ConditionFilterType.BETWEEN) {
133
+ return (value) => {
134
+ return Number(filter.to) >= Number(value) && Number(value) >= Number(filter.from);
135
+ };
136
+ }
137
+ if (conditionFilterType === ConditionFilterType.GREATER_THAN_OR_EQUAL) {
138
+ return (value) => {
139
+ return Number(value) >= Number(filter.from);
140
+ };
141
+ }
142
+ if (conditionFilterType === ConditionFilterType.LESS_THAN_OR_EQUAL) {
143
+ return (value) => {
144
+ return Number(filter.to) >= Number(value);
145
+ };
146
+ }
147
+ return defaultMatcher;
148
+ }
149
+ /** @internal */
150
+ export function createFilterMatcher(filterJaql) {
151
+ const filterJaqlInternal = filterJaql;
152
+ const { datatype } = filterJaqlInternal;
153
+ const filter = filterJaqlInternal.filter;
154
+ if (isSpecificItemsFilter(filter)) {
155
+ return createMembersFilterMatcher(filterJaqlInternal);
156
+ }
157
+ if (isConditionFilter(filter) &&
158
+ getSelectedConditionOption(filter) === ConditionFilterType.IS_NOT) {
159
+ return createExcludeMembersFilterMatcher(filterJaqlInternal);
160
+ }
161
+ // text filters
162
+ if (datatype === 'text') {
163
+ return createCombinedFilterMatcher(createTextFilterMatcher, filterJaqlInternal);
164
+ }
165
+ // // numeric filters
166
+ if (datatype === 'numeric') {
167
+ return createCombinedFilterMatcher(createNumericFilterMatcher, filterJaqlInternal);
168
+ }
169
+ return defaultMatcher;
170
+ }
@@ -1,5 +1,7 @@
1
- import { FilterModalType, AnyTypeFilterJaql, DatetimeLevel, FilterType, FilterJaqlInternal, FilterJaqlWrapperWithType } from './types.js';
1
+ import { FilterModalType, AnyTypeFilterJaql, DatetimeLevel, FilterType, SpecificItemsFilterJaql, ConditionFilterJaql, FilterJaqlInternal, FilterJaqlWrapperWithType } from './types.js';
2
+ export declare const isSpecificItemsFilter: (filter: AnyTypeFilterJaql) => filter is SpecificItemsFilterJaql;
2
3
  export declare const isNumericRangeFilter: (filter: AnyTypeFilterJaql) => boolean;
4
+ export declare const isConditionFilter: (filter: AnyTypeFilterJaql) => filter is ConditionFilterJaql;
3
5
  export declare const getFilterType: (filter: AnyTypeFilterJaql, dataType?: FilterModalType, timeData?: {
4
6
  level?: DatetimeLevel;
5
7
  bucket?: string;
@@ -4,7 +4,7 @@ import { getCorrectTimeLevel } from './date-time-filter-util.js';
4
4
  const isIncludeAllFilter = (filter) => filter === null || filter === void 0 ? void 0 : filter.all;
5
5
  const getInnerPeriodFilter = (filter) => (filter.last ? filter.last : filter.next);
6
6
  const isPeriodFilter = (filter) => { var _a; return ((_a = getInnerPeriodFilter(filter)) === null || _a === void 0 ? void 0 : _a.offset) < 2; };
7
- const isSpecificItemsFilter = (filter) => { var _a; return ((_a = filter === null || filter === void 0 ? void 0 : filter.members) === null || _a === void 0 ? void 0 : _a.length) > 0; };
7
+ export const isSpecificItemsFilter = (filter) => { var _a; return ((_a = filter === null || filter === void 0 ? void 0 : filter.members) === null || _a === void 0 ? void 0 : _a.length) > 0; };
8
8
  const isFromOrToDefined = (fromRange, toRange) => (fromRange && typeof fromRange === 'string') || (toRange && typeof toRange === 'string');
9
9
  const isFromAndToEmpty = (from, to) => from === '' && to === '';
10
10
  const isDateRangeFilter = (filter, dataType) => {
@@ -19,7 +19,7 @@ export const isNumericRangeFilter = (filter) => {
19
19
  const { from, to } = filter;
20
20
  return !!(from !== undefined && to !== undefined && !filter.isBetween);
21
21
  };
22
- const isConditionFilter = (filter) => getSelectedConditionOption(filter) !== ConditionFilterType.NONE;
22
+ export const isConditionFilter = (filter) => getSelectedConditionOption(filter) !== ConditionFilterType.NONE;
23
23
  const isAdvancedFilter = (filter) => Object.keys(filter).includes('isAdvanced');
24
24
  const isTimeLevelNotSupported = (timeData) => !!(timeData.level &&
25
25
  timeData.bucket &&
@@ -121,7 +121,7 @@ export declare type FilterJaqlInternal = {
121
121
  fiscal?: string;
122
122
  firstday?: string;
123
123
  merged?: boolean;
124
- table: string;
124
+ table?: string;
125
125
  filter?: AnyTypeFilterJaql;
126
126
  level?: DatetimeLevel;
127
127
  locale?: string;
@@ -340,6 +340,12 @@ export interface Filter extends Element {
340
340
  * Boolean flag whether the filter is a scope filter
341
341
  */
342
342
  isScope: boolean;
343
+ /**
344
+ * Boolean flag whether the filter is disabled
345
+ *
346
+ * @internal
347
+ */
348
+ disabled: boolean;
343
349
  /**
344
350
  * Gets JAQL representing this Filter instance
345
351
  *
@@ -1,3 +1,4 @@
1
+ import { type ConditionFilterJaql } from './filters/utils/types.js';
1
2
  /**
2
3
  * Different aggregation types
3
4
  */
@@ -175,13 +176,18 @@ export declare type PivotJaql = (BaseJaql | FormulaJaql) & {
175
176
  /** @internal */
176
177
  export declare type BaseJaql = {
177
178
  agg?: string;
178
- datatype: DataType;
179
+ datatype: `${DataType}`;
179
180
  dim: string;
180
181
  table: string;
181
182
  column: string;
182
183
  title: string;
183
184
  level?: 'years' | 'quarters' | 'months' | 'weeks' | 'minutes' | 'days';
184
- sort?: JaqlSortDirection;
185
+ sort?: `${JaqlSortDirection}`;
186
+ in?: {
187
+ selected?: {
188
+ jaql: FilterJaql;
189
+ };
190
+ };
185
191
  };
186
192
  /** @internal */
187
193
  export declare type FormulaID = string;
@@ -196,7 +202,7 @@ export declare type FormulaJaql = {
196
202
  context?: Record<FormulaID, FormulaContext>;
197
203
  };
198
204
  /** @internal */
199
- export declare type BaseFilter = IncludeAllFilter | IncludeMembersFilter | ExcludeMembersFilter | JaqlNumericFilter | AndFilter<JaqlNumericFilter> | OrFilter<JaqlNumericFilter>;
205
+ export declare type BaseFilter = IncludeAllFilter | IncludeMembersFilter | ExcludeMembersFilter | JaqlNumericFilter | ConditionFilterJaql | AndFilter<JaqlNumericFilter | ConditionFilterJaql> | OrFilter<JaqlNumericFilter | ConditionFilterJaql>;
200
206
  /** @internal */
201
207
  export declare type BackgroundFilter = BaseFilter & {
202
208
  level?: 'string';
package/dist/index.d.ts CHANGED
@@ -15,6 +15,7 @@ export * from './dimensional-model/attributes.js';
15
15
  export * from './dimensional-model/dimensions.js';
16
16
  export * from './dimensional-model/factory.js';
17
17
  export * from './dimensional-model/filters/filters.js';
18
+ export { createFilterMatcher } from './dimensional-model/filters/utils/filter-matcher-utils.js';
18
19
  /**
19
20
  * Functions to create date, text, or numeric filters on specified data.
20
21
  *
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ export * from './dimensional-model/attributes.js';
15
15
  export * from './dimensional-model/dimensions.js';
16
16
  export * from './dimensional-model/factory.js';
17
17
  export * from './dimensional-model/filters/filters.js';
18
+ export { createFilterMatcher } from './dimensional-model/filters/utils/filter-matcher-utils.js';
18
19
  /**
19
20
  * Functions to create date, text, or numeric filters on specified data.
20
21
  *
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "Sisense",
12
12
  "Compose SDK"
13
13
  ],
14
- "version": "1.10.0",
14
+ "version": "1.11.0",
15
15
  "type": "module",
16
16
  "exports": {
17
17
  ".": "./dist/index.js",
@@ -23,8 +23,8 @@
23
23
  "author": "Sisense",
24
24
  "license": "SEE LICENSE IN LICENSE.md",
25
25
  "dependencies": {
26
- "@sisense/sdk-common": "^1.10.0",
27
- "@sisense/sdk-rest-client": "^1.10.0",
26
+ "@sisense/sdk-common": "^1.11.0",
27
+ "@sisense/sdk-rest-client": "^1.11.0",
28
28
  "guid-typescript": "^1.0.9",
29
29
  "lodash": "^4.17.21",
30
30
  "numeral": "^2.0.6",