@vizzly/dashboard 0.15.0-dev-641cbfac7b4b489d218fea2f77a8c1c3eb2b0d96 → 0.15.0-dev-9ba9cfcf5d6fdab60b458c0b97e98590696c65ea

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.
@@ -10,8 +10,8 @@ var isEmpty$2 = _interopDefault(require('lodash/isEmpty'));
10
10
  var _ = require('lodash');
11
11
  var ___default = _interopDefault(_);
12
12
  var semanticLayerPublic = require('@vizzly/semantic-layer-public');
13
- var Joi = _interopDefault(require('@vizzly/joi'));
14
13
  var moment = _interopDefault(require('moment-timezone'));
14
+ var Joi = _interopDefault(require('@vizzly/joi'));
15
15
  var uuid = require('uuid');
16
16
  var react = require('@emotion/react');
17
17
  var jsxRuntime = require('@emotion/react/jsx-runtime');
@@ -1212,6 +1212,35 @@ function extractValue(variables, key) {
1212
1212
  return variables[key].value;
1213
1213
  }
1214
1214
 
1215
+ var getUTCDate = function getUTCDate(date) {
1216
+ if (date !== null) {
1217
+ var momentDate = moment(new Date(date));
1218
+ return momentDate.tz(Intl.DateTimeFormat().resolvedOptions().timeZone)._d;
1219
+ }
1220
+ return date;
1221
+ };
1222
+
1223
+ var filterIsDate = function filterIsDate(filter) {
1224
+ var isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
1225
+ if (!isoDateRegex.test(filter.value)) {
1226
+ return false;
1227
+ }
1228
+ var date = new Date(filter.value);
1229
+ if (isNaN(date.getTime())) {
1230
+ return false;
1231
+ }
1232
+
1233
+ // Additional check to verify that the date parts match exactly
1234
+ var _filter$value$split$ = filter.value.split('T')[0].split('-').map(Number),
1235
+ year = _filter$value$split$[0],
1236
+ month = _filter$value$split$[1],
1237
+ day = _filter$value$split$[2];
1238
+ if (date.getUTCFullYear() !== year || date.getUTCMonth() + 1 !== month || date.getUTCDate() !== day) {
1239
+ return false;
1240
+ }
1241
+ return true;
1242
+ };
1243
+
1215
1244
  var _Joi$string, _Joi$string2;
1216
1245
  var defaultDurationOptions = function defaultDurationOptions(textOverride) {
1217
1246
  return {
@@ -1324,6 +1353,175 @@ var buildRelativeRange = function buildRelativeRange(relativeFilters, dataSet, a
1324
1353
  });
1325
1354
  };
1326
1355
 
1356
+ var addAndFilters = function addAndFilters(filter, filterToAddToAll) {
1357
+ if (_.isEmpty(filterToAddToAll)) return [].concat(filter);
1358
+ if (!filter || _.isEmpty(filter)) filter = [[]];
1359
+ var result = [];
1360
+ for (var _iterator = _createForOfIteratorHelperLoose(filterToAddToAll), _step; !(_step = _iterator()).done;) {
1361
+ var additionalAndFilter = _step.value;
1362
+ for (var _iterator2 = _createForOfIteratorHelperLoose(filter), _step2; !(_step2 = _iterator2()).done;) {
1363
+ var andFilter = _step2.value;
1364
+ var combined = [].concat(additionalAndFilter, andFilter);
1365
+ if (!_.isEmpty(combined)) {
1366
+ result.push(combined);
1367
+ }
1368
+ }
1369
+ }
1370
+ return result;
1371
+ };
1372
+ var convertSingleFilterToRecursiveFilter = function convertSingleFilterToRecursiveFilter(filter, variables) {
1373
+ var field = {
1374
+ type: 'field',
1375
+ value: filter.field,
1376
+ "function": filter["function"] || 'none'
1377
+ };
1378
+ if ((filter.op === 'array_contains' || filter.op === 'array_does_not_contain') && Array.isArray(filter.value)) {
1379
+ return {
1380
+ type: 'andWhere',
1381
+ value: filter.value.map(function (value) {
1382
+ return {
1383
+ type: 'where',
1384
+ value: {
1385
+ field: field,
1386
+ op: filter.op,
1387
+ value: value
1388
+ }
1389
+ };
1390
+ })
1391
+ };
1392
+ }
1393
+ var value = useValue(filter.value, variables);
1394
+ if (isRelativeDateDefined(filter.value)) {
1395
+ value = calculateRelativeDate(filter.value);
1396
+ }
1397
+ if (filterIsDate(filter)) {
1398
+ value = getUTCDate(filter.value);
1399
+ }
1400
+ return {
1401
+ type: 'where',
1402
+ value: {
1403
+ field: field,
1404
+ op: filter.op,
1405
+ value: value
1406
+ }
1407
+ };
1408
+ };
1409
+ var convertArrayFilterStructureToQueryFilter = function convertArrayFilterStructureToQueryFilter(arrayFilterStructure, variables) {
1410
+ if (!Array.isArray(arrayFilterStructure)) {
1411
+ return arrayFilterStructure;
1412
+ }
1413
+ if (arrayFilterStructure.length === 0 || arrayFilterStructure.every(function (andFilters) {
1414
+ return andFilters.length === 0;
1415
+ })) {
1416
+ return {
1417
+ type: 'andWhere',
1418
+ value: []
1419
+ };
1420
+ }
1421
+ var convertedAndGroups = arrayFilterStructure.filter(function (andFilters) {
1422
+ return andFilters.length > 0;
1423
+ }).map(function (andFilters) {
1424
+ return {
1425
+ type: 'andWhere',
1426
+ value: andFilters.map(function (filter) {
1427
+ return convertSingleFilterToRecursiveFilter(filter, variables);
1428
+ })
1429
+ };
1430
+ });
1431
+ if (convertedAndGroups.length === 1) {
1432
+ return convertedAndGroups[0];
1433
+ }
1434
+ return {
1435
+ type: 'orWhere',
1436
+ value: convertedAndGroups
1437
+ };
1438
+ };
1439
+ var combineQueryFilters = function combineQueryFilters(filter, filterToAddToAll) {
1440
+ if (Array.isArray(filter.value) && filter.value.length === 0) {
1441
+ return filterToAddToAll;
1442
+ }
1443
+ if (Array.isArray(filterToAddToAll.value) && filterToAddToAll.value.length === 0) {
1444
+ return filter;
1445
+ }
1446
+ return {
1447
+ type: 'andWhere',
1448
+ value: [filter, filterToAddToAll]
1449
+ };
1450
+ };
1451
+
1452
+ /**
1453
+ * Iterates through a query filter and, for each custom metric field, builds a custom metric.
1454
+ */
1455
+ function buildQueryCustomMetrics(filter, dataSet, queryEngineConfig, params) {
1456
+ if (filter.type === 'where') {
1457
+ var field = getFieldFromFilter(filter);
1458
+ if (!field) return filter;
1459
+ var dataSetField = findField(dataSet, field.value);
1460
+ var fieldFunction = 'function' in field && !!field["function"] ? field["function"] : 'none';
1461
+ if (isCustomField(dataSetField)) {
1462
+ var customField = toQueryMeasure({
1463
+ field: dataSetField.id,
1464
+ "function": fieldFunction
1465
+ }, dataSetField, queryEngineConfig, dataSet, false, params);
1466
+ return {
1467
+ type: 'where',
1468
+ value: {
1469
+ field: customField,
1470
+ op: filter.value.op,
1471
+ value: filter.value.value
1472
+ }
1473
+ };
1474
+ }
1475
+ return filter;
1476
+ }
1477
+ if (filter.type === 'andWhere' || filter.type === 'orWhere') {
1478
+ var processedValues = filter.value.map(function (f) {
1479
+ return buildQueryCustomMetrics(f, dataSet, queryEngineConfig, params);
1480
+ });
1481
+ return {
1482
+ type: filter.type,
1483
+ value: processedValues
1484
+ };
1485
+ }
1486
+ return filter;
1487
+ }
1488
+ function getFieldFromFilter(filter) {
1489
+ if (filter.type === 'where') {
1490
+ if ('value' in filter.value.field && typeof filter.value.field.value === 'string') {
1491
+ return filter.value.field;
1492
+ }
1493
+ }
1494
+ return null;
1495
+ }
1496
+ var isAvailable = function isAvailable(filter) {
1497
+ return filter && _.isArray(filter) && _.isArray(filter[0]);
1498
+ };
1499
+ var isAdditionalFilter = function isAdditionalFilter(value) {
1500
+ return value && _.isArray(value) && _.isArray(value[0]) && 'field' in value[0][0] && 'op' in value[0][0] && 'value' in value[0][0];
1501
+ };
1502
+
1503
+ var combineFilters = function combineFilters(array1, array2) {
1504
+ var validArray1 = array1.length > 0 && array1[0] ? array1 : [[]];
1505
+ var validArray2 = array2.length > 0 && array2[0] ? array2 : [[]];
1506
+
1507
+ // If array1 has more than one sub-array, loop through each sub-array in array1
1508
+ if (validArray1.length > 1) {
1509
+ return validArray1.map(function (subArray) {
1510
+ return [].concat(validArray2[0] || [], subArray || []);
1511
+ });
1512
+ }
1513
+ // Otherwise, if array2 has more than one sub-array, loop through array2
1514
+ else if (validArray2.length > 1) {
1515
+ return validArray2.map(function (subArray) {
1516
+ return [].concat(validArray1[0] || [], subArray || []);
1517
+ });
1518
+ }
1519
+ // Default: merge both single sub-arrays
1520
+ else {
1521
+ return [[].concat(validArray1[0] || [], validArray2[0] || [])];
1522
+ }
1523
+ };
1524
+
1327
1525
  /** Upcasts from an old global filter, to a new "additional filter" */
1328
1526
  var upcastToAdditionalFilter = function upcastToAdditionalFilter(globalFilter) {
1329
1527
  if (globalFilter.type == 'globalSelectFilter') {
@@ -1375,105 +1573,6 @@ var MULTI_SELECT_FILTER = 'multiSelectFilter';
1375
1573
  var NUMERIC_FILTER = 'numericFilter';
1376
1574
  var ADVANCED_FILTER = 'advancedFilter';
1377
1575
 
1378
- var getUTCDate = function getUTCDate(date) {
1379
- if (date !== null) {
1380
- var momentDate = moment(new Date(date));
1381
- return momentDate.tz(Intl.DateTimeFormat().resolvedOptions().timeZone)._d;
1382
- }
1383
- return date;
1384
- };
1385
-
1386
- var toQueryAttributesFilter = function toQueryAttributesFilter(dataSet, filter, customTimeRangeFuncs) {
1387
- return filter.appliesToFields.flatMap(function (field) {
1388
- var _filter$value, _filter$value2, _filter$value3;
1389
- if (field.dataSetId != dataSet.id) return [];
1390
- if (filter.value == null) return [];
1391
- var dataSetField = findField(dataSet, field.fieldId);
1392
-
1393
- // might be able to remove this
1394
- if (dataSetField.dataType == 'string[]' && filter.type !== MULTI_SELECT_FILTER && !isAdditionalFilter(filter.value)) {
1395
- return [[{
1396
- field: field.fieldId,
1397
- op: 'array_contains',
1398
- value: filter.value
1399
- }]];
1400
- }
1401
- if ((filter.type == DATE_FILTER || filter.type == DATE_AND_TIME_FILTER) && ((_filter$value = filter.value) == null ? void 0 : _filter$value.type) == 'relativeRange') {
1402
- return [];
1403
- }
1404
- if ((filter.type == DATE_FILTER || filter.type == DATE_AND_TIME_FILTER) && ((_filter$value2 = filter.value) == null ? void 0 : _filter$value2.type) == 'fixedRange') {
1405
- // We have a fixed time range, so we can use those values.
1406
-
1407
- return [[{
1408
- field: field.fieldId,
1409
- op: inclusiveExclusiveCurrent(DateOp.Greater, filter),
1410
- value: getUTCDate(filter.value.after)
1411
- }, {
1412
- field: field.fieldId,
1413
- op: inclusiveExclusiveCurrent(DateOp.Less, filter),
1414
- value: getUTCDate(filter.value.before)
1415
- }]];
1416
- } else if ((filter.type == DATE_FILTER || filter.type == DATE_AND_TIME_FILTER) && ((_filter$value3 = filter.value) == null ? void 0 : _filter$value3.type) == 'relative') {
1417
- // We have a relative time filter, so need to call the time functions to get the values....
1418
-
1419
- var _customTimeRangeFuncs = customTimeRangeFuncs[filter.value.value].range,
1420
- before = _customTimeRangeFuncs.before,
1421
- after = _customTimeRangeFuncs.after;
1422
- var filters = [[]];
1423
- if (before) {
1424
- filters = filters.map(function (f) {
1425
- return [].concat(f, [{
1426
- field: field.fieldId,
1427
- op: inclusiveExclusiveCurrent(DateOp.Less, filter),
1428
- value: before
1429
- }]);
1430
- });
1431
- }
1432
- if (after) {
1433
- filters = filters.map(function (f) {
1434
- return [].concat(f, [{
1435
- field: field.fieldId,
1436
- op: inclusiveExclusiveCurrent(DateOp.Greater, filter),
1437
- value: after
1438
- }]);
1439
- });
1440
- }
1441
- return filters;
1442
- } else if (filter.type == SINGLE_SELECT_FILTER) {
1443
- var value = filter.value;
1444
- if (filter.value === NULL_VALUE_OPT) {
1445
- value = null;
1446
- }
1447
- return [[{
1448
- field: field.fieldId,
1449
- op: '=',
1450
- value: value
1451
- }]];
1452
- } else if (isAdditionalFilter(filter.value)) {
1453
- return buildAdvancedFilters(filter.value, field, dataSet.id);
1454
- } else if (filter.type == MULTI_SELECT_FILTER && filter.value.length > 0) {
1455
- return [[{
1456
- field: field.fieldId,
1457
- op: 'is_one_of',
1458
- value: filter.value
1459
- }]];
1460
- } else if (filter.type == DATE_FILTER && !filter.value || filter.type == DATE_AND_TIME_FILTER && !filter.value || filter.type == MULTI_SELECT_FILTER && filter.value.length === 0) {
1461
- // No value set on the filter, so it cannot become a query attribute.
1462
- return [];
1463
- } else if (filter.type == NUMERIC_FILTER) {
1464
- if ('op' in filter.value && 'value' in filter.value) {
1465
- return [[{
1466
- field: field.fieldId,
1467
- op: filter.value.op,
1468
- value: filter.value.value
1469
- }]];
1470
- }
1471
- return [[]];
1472
- }
1473
- throw "Cannot convert filter type " + filter.type + " to query attributes filter. " + JSON.stringify(filter);
1474
- });
1475
- };
1476
-
1477
1576
  var typeToString = function typeToString(type, textOverride) {
1478
1577
  if (type == DATE_FILTER) return textOverride('date_filter', 'Date filter');
1479
1578
  if (type == DATE_AND_TIME_FILTER) return textOverride('date_time_filter', 'Date Time filter');
@@ -1676,31 +1775,48 @@ function inclusiveExclusiveCurrent(op, filter) {
1676
1775
  throw new Error('Unknown date operation');
1677
1776
  }
1678
1777
  }
1679
- function getCascadeOptionsFilters(globalFilters, dataSets, dateFilterOptions, cascadeFilterSelection) {
1778
+ function getCascadeOptionsFilters(globalFilters, dataSets, dateFilterOptions, variables, cascadeFilterSelection) {
1680
1779
  if (!cascadeFilterSelection) return undefined;
1681
- var result = globalFilters.reduce(function (acc, dataObj) {
1682
- if (dataObj.value !== null) {
1683
- if (Array.isArray(dataObj.value) && dataObj.value.length === 0) {
1684
- return acc;
1780
+ var dataSetMap = new Map(dataSets.map(function (ds) {
1781
+ return [ds.id, ds];
1782
+ }));
1783
+ var filtersByDataSet = globalFilters.reduce(function (acc, filter) {
1784
+ if (!hasValidFilterValue(filter.value)) {
1785
+ return acc;
1786
+ }
1787
+ var uniqueDataSetIds = new Set(filter.appliesToFields.map(function (f) {
1788
+ return f.dataSetId;
1789
+ }));
1790
+ for (var _iterator = _createForOfIteratorHelperLoose(uniqueDataSetIds), _step; !(_step = _iterator()).done;) {
1791
+ var dataSetId = _step.value;
1792
+ var dataSet = dataSetMap.get(dataSetId);
1793
+ if (!dataSet) continue;
1794
+ if (!acc[dataSetId]) {
1795
+ acc[dataSetId] = [];
1685
1796
  }
1686
- var uniqueDataSetIds = new Set(dataObj.appliesToFields.map(function (f) {
1687
- return f.dataSetId;
1688
- }));
1689
- uniqueDataSetIds.forEach(function (dataSetId) {
1690
- var dataSet = find(dataSets, dataSetId);
1691
- if (!acc[dataSetId]) {
1692
- acc[dataSetId] = [];
1693
- }
1694
- if (dataSet !== null) {
1695
- var filters = toQueryAttributesFilter(dataSet, dataObj, dateFilterOptions);
1696
- acc[dataSetId] = addAndFilters(acc[dataSetId], filters);
1697
- }
1698
- });
1797
+ var queryFilters = processAdditionalFilter(filter, dataSet, dateFilterOptions, variables);
1798
+ acc[dataSetId].push(queryFilters);
1799
+ }
1800
+ return acc;
1801
+ }, {});
1802
+ var result = Object.entries(filtersByDataSet).reduce(function (acc, _ref2) {
1803
+ var dataSetId = _ref2[0],
1804
+ filters = _ref2[1];
1805
+ if (filters.length > 0) {
1806
+ acc[dataSetId] = {
1807
+ type: 'andWhere',
1808
+ value: filters
1809
+ };
1699
1810
  }
1700
1811
  return acc;
1701
1812
  }, {});
1702
1813
  return Object.keys(result).length === 0 ? undefined : result;
1703
1814
  }
1815
+ function hasValidFilterValue(value) {
1816
+ if (value === null || value === undefined) return false;
1817
+ if (Array.isArray(value) && value.length === 0) return false;
1818
+ return true;
1819
+ }
1704
1820
  var updateFilterForOptionalPulledFromOptions = function updateFilterForOptionalPulledFromOptions(filter) {
1705
1821
  if (!('optionsPulledFrom' in filter)) return filter;
1706
1822
  if (!filter.optionsPulledFrom || filter.optionsPulledFrom.length === 0) {
@@ -1755,168 +1871,182 @@ function getFilterDataType(filter, dataSets) {
1755
1871
  return findField(dataSet, filter.appliesToFields[0].fieldId).dataType;
1756
1872
  }
1757
1873
 
1758
- var fromFilterConfig = function fromFilterConfig(filterConfig, dataSet, timeRangeOptions) {
1759
- var filters = [];
1760
- (filterConfig.globalFilters || []).forEach(function (additionalFilter) {
1761
- var addFilter = [];
1762
- if (additionalFilter.type === DATE_AND_TIME_FILTER || additionalFilter.type === DATE_FILTER) {
1763
- addFilter = toRelativeQueryAttributesFilters(additionalFilter, dataSet);
1874
+ var toQueryAttributesFilter = function toQueryAttributesFilter(dataSet, filter, customTimeRangeFuncs) {
1875
+ return filter.appliesToFields.flatMap(function (field) {
1876
+ var _filter$value, _filter$value2, _filter$value3;
1877
+ if (field.dataSetId != dataSet.id) return [];
1878
+ if (filter.value == null) return [];
1879
+ var dataSetField = findField(dataSet, field.fieldId);
1880
+
1881
+ // might be able to remove this
1882
+ if (dataSetField.dataType == 'string[]' && filter.type !== MULTI_SELECT_FILTER && !isAdditionalFilter(filter.value)) {
1883
+ return [[{
1884
+ field: field.fieldId,
1885
+ op: 'array_contains',
1886
+ value: filter.value
1887
+ }]];
1764
1888
  }
1765
- filters = addAndFilters(filters, addFilter);
1766
- filters = addAndFilters(filters, toQueryAttributesFilter(dataSet, additionalFilter, timeRangeOptions));
1767
- });
1768
- var localAdditionalFilters = Object.values(filterConfig.localFilters || {}).flat();
1769
- localAdditionalFilters.forEach(function (additionalFilter) {
1770
- var addFilter = [];
1771
- if (additionalFilter.type === DATE_AND_TIME_FILTER || additionalFilter.type === DATE_FILTER) {
1772
- addFilter = toRelativeQueryAttributesFilters(additionalFilter, dataSet);
1889
+ if ((filter.type == DATE_FILTER || filter.type == DATE_AND_TIME_FILTER) && ((_filter$value = filter.value) == null ? void 0 : _filter$value.type) == 'relativeRange') {
1890
+ return [];
1773
1891
  }
1774
- filters = addAndFilters(filters, addFilter);
1775
- filters = addAndFilters(filters, toQueryAttributesFilter(dataSet, additionalFilter, timeRangeOptions));
1776
- });
1777
- return filters;
1778
- };
1779
-
1780
- var filterIsDate = function filterIsDate(filter) {
1781
- var isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
1782
- if (!isoDateRegex.test(filter.value)) {
1783
- return false;
1784
- }
1785
- var date = new Date(filter.value);
1786
- if (isNaN(date.getTime())) {
1787
- return false;
1788
- }
1892
+ if ((filter.type == DATE_FILTER || filter.type == DATE_AND_TIME_FILTER) && ((_filter$value2 = filter.value) == null ? void 0 : _filter$value2.type) == 'fixedRange') {
1893
+ // We have a fixed time range, so we can use those values.
1789
1894
 
1790
- // Additional check to verify that the date parts match exactly
1791
- var _filter$value$split$ = filter.value.split('T')[0].split('-').map(Number),
1792
- year = _filter$value$split$[0],
1793
- month = _filter$value$split$[1],
1794
- day = _filter$value$split$[2];
1795
- if (date.getUTCFullYear() !== year || date.getUTCMonth() + 1 !== month || date.getUTCDate() !== day) {
1796
- return false;
1797
- }
1798
- return true;
1799
- };
1895
+ return [[{
1896
+ field: field.fieldId,
1897
+ op: inclusiveExclusiveCurrent(DateOp.Greater, filter),
1898
+ value: getUTCDate(filter.value.after)
1899
+ }, {
1900
+ field: field.fieldId,
1901
+ op: inclusiveExclusiveCurrent(DateOp.Less, filter),
1902
+ value: getUTCDate(filter.value.before)
1903
+ }]];
1904
+ } else if ((filter.type == DATE_FILTER || filter.type == DATE_AND_TIME_FILTER) && ((_filter$value3 = filter.value) == null ? void 0 : _filter$value3.type) == 'relative') {
1905
+ // We have a relative time filter, so need to call the time functions to get the values....
1800
1906
 
1801
- var addAndFilters = function addAndFilters(filter, filterToAddToAll) {
1802
- if (_.isEmpty(filterToAddToAll)) return [].concat(filter);
1803
- if (!filter || _.isEmpty(filter)) filter = [[]];
1804
- var result = [];
1805
- for (var _iterator = _createForOfIteratorHelperLoose(filterToAddToAll), _step; !(_step = _iterator()).done;) {
1806
- var additionalAndFilter = _step.value;
1807
- for (var _iterator2 = _createForOfIteratorHelperLoose(filter), _step2; !(_step2 = _iterator2()).done;) {
1808
- var andFilter = _step2.value;
1809
- var combined = [].concat(additionalAndFilter, andFilter);
1810
- if (!_.isEmpty(combined)) {
1811
- result.push(combined);
1907
+ var _customTimeRangeFuncs = customTimeRangeFuncs[filter.value.value].range,
1908
+ before = _customTimeRangeFuncs.before,
1909
+ after = _customTimeRangeFuncs.after;
1910
+ var filters = [[]];
1911
+ if (before) {
1912
+ filters = filters.map(function (f) {
1913
+ return [].concat(f, [{
1914
+ field: field.fieldId,
1915
+ op: inclusiveExclusiveCurrent(DateOp.Less, filter),
1916
+ value: before
1917
+ }]);
1918
+ });
1919
+ }
1920
+ if (after) {
1921
+ filters = filters.map(function (f) {
1922
+ return [].concat(f, [{
1923
+ field: field.fieldId,
1924
+ op: inclusiveExclusiveCurrent(DateOp.Greater, filter),
1925
+ value: after
1926
+ }]);
1927
+ });
1928
+ }
1929
+ return filters;
1930
+ } else if (filter.type == SINGLE_SELECT_FILTER) {
1931
+ var value = filter.value;
1932
+ if (filter.value === NULL_VALUE_OPT) {
1933
+ value = null;
1812
1934
  }
1935
+ return [[{
1936
+ field: field.fieldId,
1937
+ op: '=',
1938
+ value: value
1939
+ }]];
1940
+ } else if (isAdditionalFilter(filter.value)) {
1941
+ return buildAdvancedFilters(filter.value, field, dataSet.id);
1942
+ } else if (filter.type == MULTI_SELECT_FILTER && filter.value.length > 0) {
1943
+ return [[{
1944
+ field: field.fieldId,
1945
+ op: 'is_one_of',
1946
+ value: filter.value
1947
+ }]];
1948
+ } else if (filter.type == DATE_FILTER && !filter.value || filter.type == DATE_AND_TIME_FILTER && !filter.value || filter.type == MULTI_SELECT_FILTER && filter.value.length === 0) {
1949
+ // No value set on the filter, so it cannot become a query attribute.
1950
+ return [];
1951
+ } else if (filter.type == NUMERIC_FILTER) {
1952
+ if ('op' in filter.value && 'value' in filter.value) {
1953
+ return [[{
1954
+ field: field.fieldId,
1955
+ op: filter.value.op,
1956
+ value: filter.value.value
1957
+ }]];
1958
+ }
1959
+ return [[]];
1813
1960
  }
1814
- }
1815
- return result;
1961
+ throw "Cannot convert filter type " + filter.type + " to query attributes filter. " + JSON.stringify(filter);
1962
+ });
1816
1963
  };
1817
- var filterAttributeToQueryFilter = function filterAttributeToQueryFilter(filterAttrs, queryEngineConfig, dataSet, params) {
1818
- var _params$filterConfig;
1819
- // Either build using the filter attributes passed in, or take the viewFilters in the filter config.
1820
- // They represent the same thing, however some view-filters are passed around in the filter config
1821
- // to reduce custom metrics arguments being passed around.
1822
- var filter = filterAttrs.length > 0 && filterAttrs.some(function (group) {
1823
- return group.length > 0;
1824
- }) ? filterAttrs : ((_params$filterConfig = params.filterConfig) == null ? void 0 : _params$filterConfig.viewFilters) || [];
1825
- var extraFilters = fromFilterConfig(params.filterConfig, dataSet, params.timeRangeOptions);
1826
- var combinedFilters = addAndFilters(filter, extraFilters);
1827
- if (Array.isArray(filter)) {
1828
- return {
1829
- type: 'orWhere',
1830
- value: combinedFilters.map(function (andFilters) {
1831
- return {
1832
- type: 'andWhere',
1833
- value: andFilters.map(function (filter) {
1834
- var dataSetField = findField(dataSet, filter.field);
1835
- var field = {
1836
- type: 'field',
1837
- value: filter.field,
1838
- "function": filter["function"] || 'none'
1839
- };
1840
- if (isCustomField(dataSetField)) {
1841
- var _filter$function;
1842
- field = toQueryMeasure({
1843
- field: dataSetField.id,
1844
- "function": (_filter$function = filter["function"]) != null ? _filter$function : 'none'
1845
- }, dataSetField, queryEngineConfig, dataSet, false, params);
1846
- }
1847
1964
 
1848
- // If the value is an array, and we're checking that all values ARE or ARE NOT in a field, then we need to split
1849
- // out this check into multiple filters, as a value in a filter cannot be an array.
1850
- if ((filter.op == 'array_contains' || filter.op == 'array_does_not_contain') && Array.isArray(filter.value)) {
1851
- return {
1852
- type: 'andWhere',
1853
- value: [].concat(filter.value).map(function (value) {
1854
- return {
1855
- type: 'where',
1856
- value: {
1857
- field: field,
1858
- op: filter.op,
1859
- value: value
1860
- }
1861
- };
1862
- })
1863
- };
1864
- }
1865
- var value = useValue(filter.value, params.variables);
1866
- if (isRelativeDateDefined(filter.value)) {
1867
- value = calculateRelativeDate(filter.value);
1868
- }
1869
- if (filterIsDate(filter)) {
1870
- value = getUTCDate(filter.value);
1871
- }
1872
- return {
1873
- type: 'where',
1874
- value: {
1875
- field: field,
1876
- op: filter.op,
1877
- value: value
1878
- }
1879
- };
1880
- })
1881
- };
1882
- })
1965
+ var processAdditionalFilter = function processAdditionalFilter(filter, dataSet, timeRangeOptions, variables) {
1966
+ var queryAttributesFilter = toQueryAttributesFilter(dataSet, filter, timeRangeOptions);
1967
+ var convertedFilter = convertArrayFilterStructureToQueryFilter(queryAttributesFilter, variables);
1968
+ if (filter.type === DATE_AND_TIME_FILTER || filter.type === DATE_FILTER) {
1969
+ var relativeDateFilter = toRelativeQueryAttributesFilters(filter, dataSet);
1970
+ var convertedRelativeFilter = convertArrayFilterStructureToQueryFilter(relativeDateFilter, variables);
1971
+ return {
1972
+ type: 'andWhere',
1973
+ value: [convertedFilter, convertedRelativeFilter]
1883
1974
  };
1884
1975
  }
1885
- return filter;
1886
- };
1887
- var isAvailable = function isAvailable(filter) {
1888
- return filter && _.isArray(filter) && _.isArray(filter[0]);
1976
+ return convertedFilter;
1889
1977
  };
1890
- var isAdditionalFilter = function isAdditionalFilter(value) {
1891
- return value && _.isArray(value) && _.isArray(value[0]) && 'field' in value[0][0] && 'op' in value[0][0] && 'value' in value[0][0];
1892
- };
1893
-
1894
- var combineFilters = function combineFilters(array1, array2) {
1895
- var validArray1 = array1.length > 0 && array1[0] ? array1 : [[]];
1896
- var validArray2 = array2.length > 0 && array2[0] ? array2 : [[]];
1897
-
1898
- // If array1 has more than one sub-array, loop through each sub-array in array1
1899
- if (validArray1.length > 1) {
1900
- return validArray1.map(function (subArray) {
1901
- return [].concat(validArray2[0] || [], subArray || []);
1902
- });
1903
- }
1904
- // Otherwise, if array2 has more than one sub-array, loop through array2
1905
- else if (validArray2.length > 1) {
1906
- return validArray2.map(function (subArray) {
1907
- return [].concat(validArray1[0] || [], subArray || []);
1978
+ var isAdditionalFilterValid = function isAdditionalFilterValid(filter) {
1979
+ if (Array.isArray(filter.value)) {
1980
+ return filter.value.length > 0 && filter.value.some(function (item) {
1981
+ return !Array.isArray(item) || item.length > 0;
1908
1982
  });
1909
1983
  }
1910
- // Default: merge both single sub-arrays
1911
- else {
1912
- return [[].concat(validArray1[0] || [], validArray2[0] || [])];
1913
- }
1984
+ return Boolean(filter.value);
1985
+ };
1986
+
1987
+ /**
1988
+ * Combines different types of filters (global, local, and view filters) into a single Query filter structure.
1989
+ *
1990
+ * @param filterConfig - Configuration containing different filter types
1991
+ * @param dataSet - Dataset to validate filters against
1992
+ * @param timeRangeOptions - Time range configuration for date filters
1993
+ * @param variables - Variable list for template substitution
1994
+ * @returns Combined Query filter with proper AND/OR structure
1995
+ */
1996
+ var combineFiltersFromFilterConfig = function combineFiltersFromFilterConfig(filterConfig, dataSet, timeRangeOptions, variables) {
1997
+ var globalFilters = filterConfig.globalFilters || [];
1998
+ var processedGlobalFilters = globalFilters.filter(isAdditionalFilterValid).map(function (filter) {
1999
+ return processAdditionalFilter(filter, dataSet, timeRangeOptions, variables);
2000
+ });
2001
+ var localFilters = filterConfig.localFilters || [];
2002
+ var processedLocalFilters = localFilters.filter(isAdditionalFilterValid).map(function (filter) {
2003
+ return processAdditionalFilter(filter, dataSet, timeRangeOptions, variables);
2004
+ });
2005
+ var viewFilters = filterConfig.viewFilters ? filterConfig.viewFilters.filter(function (filter) {
2006
+ return filter.length > 0;
2007
+ }) : [];
2008
+ var processedViewFilters = convertArrayFilterStructureToQueryFilter(viewFilters, variables);
2009
+ var andFilters = [].concat(processedGlobalFilters, processedLocalFilters, [processedViewFilters]).filter(function (andFilter) {
2010
+ if (Array.isArray(andFilter.value)) {
2011
+ return andFilter.value.length > 0;
2012
+ }
2013
+ return true;
2014
+ });
2015
+ return {
2016
+ type: 'andWhere',
2017
+ value: andFilters
2018
+ };
1914
2019
  };
1915
2020
 
1916
2021
  var generateId = function generateId() {
1917
2022
  return uuid.v4().replace(/-/g, '');
1918
2023
  };
1919
2024
 
2025
+ var Clause = /*#__PURE__*/function (Clause) {
2026
+ Clause["AND_WHERE"] = "andWhere";
2027
+ Clause["OR_WHERE"] = "orWhere";
2028
+ Clause["WHERE"] = "where";
2029
+ return Clause;
2030
+ }({});
2031
+
2032
+ // export type WhereClause = SqlAST.MultiWhereToken<any>;
2033
+
2034
+ var DEFAULT_ALWAYS_FILTER_VALUE = 2;
2035
+ var alwaysTrueFilter = {
2036
+ type: Clause.AND_WHERE,
2037
+ value: [{
2038
+ type: Clause.WHERE,
2039
+ value: {
2040
+ field: {
2041
+ type: 'number',
2042
+ value: DEFAULT_ALWAYS_FILTER_VALUE
2043
+ },
2044
+ op: '=',
2045
+ value: DEFAULT_ALWAYS_FILTER_VALUE
2046
+ }
2047
+ }]
2048
+ };
2049
+
1920
2050
  /**
1921
2051
  * Creates a new custom percentage field.
1922
2052
  */
@@ -1941,10 +2071,15 @@ var init$1 = function init(publicName, denominatorFieldId, denominatorAggregate,
1941
2071
  };
1942
2072
  };
1943
2073
  var build$2 = function build(customField, queryEngineConfig, dataSet, _queryHasDimension, params) {
1944
- var _params$filterConfig$, _params$filterConfig, _customField$numerato, _customField$numerato2, _customField$denomina, _customField$denomina2;
1945
- var _buildPercentageFilte = buildPercentageFilters((_params$filterConfig$ = params == null || (_params$filterConfig = params.filterConfig) == null ? void 0 : _params$filterConfig.viewFilters) != null ? _params$filterConfig$ : [], customField),
1946
- combinedNominatorFilters = _buildPercentageFilte.combinedNominatorFilters,
1947
- combinedDenominatorFilters = _buildPercentageFilte.combinedDenominatorFilters;
2074
+ var _customField$numerato, _customField$numerato2, _customField$denomina, _customField$denomina2;
2075
+ var queryFiltersFromFilterConfig = combineFiltersFromFilterConfig(params.filterConfig, dataSet, params.timeRangeOptions, params.variables);
2076
+ var _buildPercentageFilte = buildPercentageFilters(customField, params.variables),
2077
+ queryFilterFromNumeratorFilter = _buildPercentageFilte.queryFilterFromNumeratorFilter,
2078
+ queryFilterFromDenominatorFilter = _buildPercentageFilte.queryFilterFromDenominatorFilter;
2079
+ var combinedNominatorFilters = combineQueryFilters(queryFiltersFromFilterConfig, queryFilterFromNumeratorFilter);
2080
+ var combinedDenominatorFilters = combineQueryFilters(queryFiltersFromFilterConfig, queryFilterFromDenominatorFilter);
2081
+ var completeNominatorFilters = buildQueryCustomMetrics(combinedNominatorFilters, dataSet, queryEngineConfig, params);
2082
+ var completeDenominatorFilters = buildQueryCustomMetrics(combinedDenominatorFilters, dataSet, queryEngineConfig, params);
1948
2083
  var left = {
1949
2084
  fieldId: (_customField$numerato = customField.numeratorFieldId) != null ? _customField$numerato : customField.denominatorFieldId,
1950
2085
  aggregate: (_customField$numerato2 = customField.numeratorAggregate) != null ? _customField$numerato2 : customField.denominatorAggregate
@@ -1961,44 +2096,31 @@ var build$2 = function build(customField, queryEngineConfig, dataSet, _queryHasD
1961
2096
  value: customField.denominatorFieldId,
1962
2097
  "function": customField.denominatorAggregate
1963
2098
  }],
1964
- filter: filterAttributeToQueryFilter(combinedDenominatorFilters || [], queryEngineConfig, dataSet, params)
2099
+ filter: completeDenominatorFilters
1965
2100
  }
1966
2101
  };
1967
- var denominatorForWithinGroupingScope = buildSide(right, isAvailable(customField.denominatorFilter) ? filterAttributeToQueryFilter(combinedDenominatorFilters, queryEngineConfig, dataSet, params) : {
2102
+ var denominatorForWithinGroupingScope = buildSide(right, isAvailable(customField.denominatorFilter) ? completeDenominatorFilters : {
1968
2103
  type: 'andWhere',
1969
2104
  value: []
1970
- });
2105
+ }, params.variables);
1971
2106
  return {
1972
2107
  type: 'maths',
1973
- left: buildSide(left, isAvailable(customField.numeratorFilter) ? filterAttributeToQueryFilter(combinedNominatorFilters, queryEngineConfig, dataSet, params) : {
2108
+ left: buildSide(left, isAvailable(customField.numeratorFilter) ? completeNominatorFilters : {
1974
2109
  type: 'andWhere',
1975
2110
  value: []
1976
- }),
2111
+ }, params.variables),
1977
2112
  op: '/',
1978
2113
  right: customField.denominatorScope === 'withinGrouping' ? denominatorForWithinGroupingScope : denominatorForAllScope
1979
2114
  };
1980
2115
  };
1981
- var buildSide = function buildSide(field, filter) {
1982
- var alwaysTrueFilter = {
1983
- type: 'andWhere',
1984
- value: [{
1985
- type: 'where',
1986
- value: {
1987
- field: {
1988
- type: 'number',
1989
- value: 2
1990
- },
1991
- op: '=',
1992
- value: 2
1993
- }
1994
- }]
1995
- };
2116
+ var buildSide = function buildSide(field, filter, variables) {
2117
+ var value = useValue(field.fieldId, variables);
1996
2118
  var hasNumeratorFilter = filter.type === 'where' || filter.value.length > 0;
1997
2119
  if (!hasNumeratorFilter) {
1998
2120
  return {
1999
2121
  type: 'field',
2000
2122
  "function": field.aggregate,
2001
- value: field.fieldId
2123
+ value: value
2002
2124
  };
2003
2125
  } else {
2004
2126
  return {
@@ -2011,7 +2133,7 @@ var buildSide = function buildSide(field, filter) {
2011
2133
  returns: {
2012
2134
  type: 'field',
2013
2135
  "function": 'none',
2014
- value: field.fieldId
2136
+ value: value
2015
2137
  },
2016
2138
  filter: filter
2017
2139
  }, {
@@ -2026,22 +2148,24 @@ var buildSide = function buildSide(field, filter) {
2026
2148
  };
2027
2149
  }
2028
2150
  };
2029
- function buildPercentageFilters(filters, customField) {
2030
- var combinedNominatorFilters = [];
2031
- var combinedDenominatorFilters = [];
2151
+ function buildPercentageFilters(customField, variables) {
2152
+ var queryFilterFromNumeratorFilter = {
2153
+ type: 'andWhere',
2154
+ value: []
2155
+ };
2156
+ var queryFilterFromDenominatorFilter = {
2157
+ type: 'andWhere',
2158
+ value: []
2159
+ };
2032
2160
  if (customField.numeratorFilter && isAvailable(customField.numeratorFilter)) {
2033
- combinedNominatorFilters = addAndFilters(filters != null ? filters : [], customField.numeratorFilter);
2034
- } else {
2035
- combinedNominatorFilters = filters != null ? filters : [];
2161
+ queryFilterFromNumeratorFilter = convertArrayFilterStructureToQueryFilter(customField.numeratorFilter, variables);
2036
2162
  }
2037
2163
  if (customField.denominatorFilter && isAvailable(customField.denominatorFilter)) {
2038
- combinedDenominatorFilters = addAndFilters(filters != null ? filters : [], customField.denominatorFilter);
2039
- } else {
2040
- combinedDenominatorFilters = filters != null ? filters : [];
2164
+ queryFilterFromDenominatorFilter = convertArrayFilterStructureToQueryFilter(customField.denominatorFilter, variables);
2041
2165
  }
2042
2166
  return {
2043
- combinedNominatorFilters: combinedNominatorFilters,
2044
- combinedDenominatorFilters: combinedDenominatorFilters
2167
+ queryFilterFromNumeratorFilter: queryFilterFromNumeratorFilter,
2168
+ queryFilterFromDenominatorFilter: queryFilterFromDenominatorFilter
2045
2169
  };
2046
2170
  }
2047
2171
 
@@ -2089,10 +2213,7 @@ var buildSide$1 = function buildSide(value, dataSet, variables) {
2089
2213
  "function": 'none'
2090
2214
  };
2091
2215
  }
2092
- var valueAsString = value;
2093
- if (detect(value)) {
2094
- valueAsString = useValue(value, variables);
2095
- }
2216
+ var valueAsString = useValue(value, variables);
2096
2217
  var valueAsNumber = Number(valueAsString);
2097
2218
  if (isNaN(valueAsNumber)) {
2098
2219
  var message = "Invalid number for Maths field: " + value + ".";
@@ -2126,35 +2247,36 @@ var init$3 = function init(publicName, leftFieldId, leftFunction, operator, righ
2126
2247
  rightNested: rightNested
2127
2248
  };
2128
2249
  };
2129
- var build$4 = function build(customField) {
2130
- var buildSide = function buildSide(fieldId, func, nested) {
2250
+ var build$4 = function build(customField, variables) {
2251
+ var buildSide = function buildSide(fieldId, func, variables, nested) {
2252
+ var value = useValue(fieldId, variables);
2131
2253
  if (nested) {
2254
+ var nestedValue = useValue(nested.fieldId, variables);
2132
2255
  return {
2133
2256
  type: 'maths',
2134
2257
  left: {
2135
2258
  type: 'field',
2136
- value: fieldId,
2259
+ value: value,
2137
2260
  "function": func
2138
2261
  },
2139
2262
  right: {
2140
2263
  type: 'field',
2141
- value: nested.fieldId,
2264
+ value: nestedValue,
2142
2265
  "function": nested["function"]
2143
2266
  },
2144
2267
  op: nested.operator
2145
2268
  };
2146
- } else {
2147
- return {
2148
- type: 'field',
2149
- value: fieldId,
2150
- "function": func
2151
- };
2152
2269
  }
2270
+ return {
2271
+ type: 'field',
2272
+ value: value,
2273
+ "function": func
2274
+ };
2153
2275
  };
2154
2276
  return {
2155
2277
  type: 'maths',
2156
- left: buildSide(customField.leftFieldId, customField.leftFunction, customField.leftNested),
2157
- right: buildSide(customField.rightFieldId, customField.rightFunction, customField.rightNested),
2278
+ left: buildSide(customField.leftFieldId, customField.leftFunction, variables, customField.leftNested),
2279
+ right: buildSide(customField.rightFieldId, customField.rightFunction, variables, customField.rightNested),
2158
2280
  op: customField.operator
2159
2281
  };
2160
2282
  };
@@ -2175,14 +2297,9 @@ var init$4 = function init(publicName, fieldId, func, rule, queryEngineConfig) {
2175
2297
  };
2176
2298
  };
2177
2299
  var build$5 = function build(field, queryEngineConfig, dataSet, params) {
2178
- var alwaysTrueFilter = [[{
2179
- value: 1,
2180
- op: '=',
2181
- field: {
2182
- type: 'number',
2183
- value: 1
2184
- }
2185
- }]];
2300
+ var queryFilterFromField = convertArrayFilterStructureToQueryFilter(field.rule, params.variables);
2301
+ var completeFilters = buildQueryCustomMetrics(queryFilterFromField, dataSet, queryEngineConfig, params);
2302
+ var value = useValue(field.fieldId, params.variables);
2186
2303
  return {
2187
2304
  type: 'function',
2188
2305
  "function": field["function"],
@@ -2193,9 +2310,9 @@ var build$5 = function build(field, queryEngineConfig, dataSet, params) {
2193
2310
  returns: {
2194
2311
  type: 'field',
2195
2312
  "function": 'none',
2196
- value: field.fieldId
2313
+ value: value
2197
2314
  },
2198
- filter: filterAttributeToQueryFilter(field.rule, queryEngineConfig, dataSet, params)
2315
+ filter: completeFilters
2199
2316
  }, {
2200
2317
  returns: {
2201
2318
  type: 'null'
@@ -2242,12 +2359,14 @@ var convertToCases = function convertToCases(rules, queryEngineConfig, dataSet,
2242
2359
  return rules.map(function (_ref) {
2243
2360
  var rule = _ref.rule,
2244
2361
  name = _ref.name;
2362
+ var queryFilterFromRule = convertArrayFilterStructureToQueryFilter(rule, params.variables);
2363
+ var completeFilters = buildQueryCustomMetrics(queryFilterFromRule, dataSet, queryEngineConfig, params);
2245
2364
  return {
2246
2365
  returns: {
2247
2366
  type: 'string',
2248
2367
  value: name
2249
2368
  },
2250
- filter: filterAttributeToQueryFilter(rule, queryEngineConfig, dataSet, params)
2369
+ filter: completeFilters
2251
2370
  };
2252
2371
  });
2253
2372
  };
@@ -2267,7 +2386,9 @@ var init$6 = function init(publicName, leftFieldId, dateCalculationFunction, rig
2267
2386
  }, queryEngineConfig)
2268
2387
  };
2269
2388
  };
2270
- var build$7 = function build(measureAttribute, customField) {
2389
+ var build$7 = function build(measureAttribute, customField, variables) {
2390
+ var leftValue = useValue(customField.leftFieldId, variables);
2391
+ var rightValue = useValue(customField.rightFieldId, variables);
2271
2392
  if (measureAttribute["function"] != 'none') {
2272
2393
  return {
2273
2394
  type: 'function',
@@ -2278,12 +2399,12 @@ var build$7 = function build(measureAttribute, customField) {
2278
2399
  left: {
2279
2400
  type: 'field',
2280
2401
  "function": 'none',
2281
- value: customField.leftFieldId
2402
+ value: leftValue
2282
2403
  },
2283
2404
  right: {
2284
2405
  type: 'field',
2285
2406
  "function": 'none',
2286
- value: customField.rightFieldId
2407
+ value: rightValue
2287
2408
  }
2288
2409
  }
2289
2410
  };
@@ -2294,12 +2415,12 @@ var build$7 = function build(measureAttribute, customField) {
2294
2415
  left: {
2295
2416
  type: 'field',
2296
2417
  "function": 'none',
2297
- value: customField.leftFieldId
2418
+ value: leftValue
2298
2419
  },
2299
2420
  right: {
2300
2421
  type: 'field',
2301
2422
  "function": 'none',
2302
- value: customField.rightFieldId
2423
+ value: rightValue
2303
2424
  }
2304
2425
  };
2305
2426
  }
@@ -2319,13 +2440,6 @@ var init$7 = function init(publicName, metric, queryEngineConfig) {
2319
2440
  };
2320
2441
  };
2321
2442
 
2322
- function combineForCustomMetricFilters(filters, customFilters) {
2323
- if (customFilters && isAvailable(customFilters)) {
2324
- return addAndFilters(filters != null ? filters : [], customFilters);
2325
- }
2326
- return filters != null ? filters : [];
2327
- }
2328
-
2329
2443
  var PropertyType = /*#__PURE__*/function (PropertyType) {
2330
2444
  PropertyType["Operator"] = "operator";
2331
2445
  PropertyType["IfLogic"] = "ifLogic";
@@ -2359,21 +2473,13 @@ var build$8 = function build(measureAttribute, customField, dataSet, queryEngine
2359
2473
  return buildOperator(customField.metric, dataSet, params, measureAttribute, false);
2360
2474
  };
2361
2475
  var buildIfLogic = function buildIfLogic(ifLogic, dataSet, queryEngineConfig, params, measureAttribute) {
2362
- var alwaysTrueFilter = [[{
2363
- value: 1,
2364
- op: '=',
2365
- field: {
2366
- type: 'number',
2367
- value: 1
2368
- }
2369
- }]];
2370
2476
  var cases = function () {
2371
2477
  var thenCases = ifLogic.cases.map(function (c) {
2372
- var _params$filterConfig$, _params$filterConfig;
2373
- var customMetricFilter = combineForCustomMetricFilters((_params$filterConfig$ = params == null || (_params$filterConfig = params.filterConfig) == null ? void 0 : _params$filterConfig.viewFilters) != null ? _params$filterConfig$ : [], c.filter);
2478
+ var customMetricFilter = convertArrayFilterStructureToQueryFilter(c.filter, params.variables);
2479
+ var completeFilters = buildQueryCustomMetrics(customMetricFilter, dataSet, queryEngineConfig, params);
2374
2480
  return {
2375
2481
  returns: buildMetric(c.returns, dataSet, params, measureAttribute),
2376
- filter: filterAttributeToQueryFilter(customMetricFilter, queryEngineConfig, dataSet, params)
2482
+ filter: completeFilters
2377
2483
  };
2378
2484
  });
2379
2485
  if (!ifLogic["else"]) return [].concat(thenCases, [{
@@ -2386,7 +2492,12 @@ var buildIfLogic = function buildIfLogic(ifLogic, dataSet, queryEngineConfig, pa
2386
2492
  returns: buildMetric(ifLogic["else"], dataSet, params, measureAttribute),
2387
2493
  filter: alwaysTrueFilter // Do not remove
2388
2494
  };
2389
- return [].concat(thenCases, [elseCase]);
2495
+ return [].concat(thenCases, [elseCase, {
2496
+ returns: {
2497
+ type: 'null'
2498
+ },
2499
+ filter: alwaysTrueFilter // Do not remove
2500
+ }]);
2390
2501
  }();
2391
2502
  if (!(measureAttribute != null && measureAttribute["function"]) || measureAttribute["function"] === 'none') {
2392
2503
  throw new Error('measure needs to be defined for if logic');
@@ -2541,11 +2652,12 @@ var init$8 = function init(publicName, fieldId, roundToDecimalPlaces, queryEngin
2541
2652
  }, queryEngineConfig)
2542
2653
  };
2543
2654
  };
2544
- var build$9 = function build(measureAttribute, customField) {
2655
+ var build$9 = function build(measureAttribute, customField, variables) {
2656
+ var value = useValue(customField.fieldId, variables);
2545
2657
  var builtRoundedNumber = {
2546
2658
  type: 'field',
2547
2659
  "function": "round_to_" + customField.roundToDecimalPlaces + "_dp",
2548
- value: customField.fieldId
2660
+ value: value
2549
2661
  };
2550
2662
  if (measureAttribute["function"] == 'none') return builtRoundedNumber;
2551
2663
  return {
@@ -2606,19 +2718,19 @@ var toQueryMeasure = function toQueryMeasure(measureAttribute, customField, quer
2606
2718
  return build$6(measureAttribute, customField, queryEngineConfig, dataSet, params);
2607
2719
  }
2608
2720
  if (isAggregateMathField(customField)) {
2609
- return build$4(customField);
2721
+ return build$4(customField, params.variables);
2610
2722
  }
2611
2723
  if (isSimpleMathField(customField)) {
2612
2724
  return build$3(measureAttribute, customField, dataSet, params);
2613
2725
  }
2614
2726
  if (isRoundedNumberField(customField)) {
2615
- return build$9(measureAttribute, customField);
2727
+ return build$9(measureAttribute, customField, params.variables);
2616
2728
  }
2617
2729
  if (isConditional(customField)) {
2618
2730
  return build$5(customField, queryEngineConfig, dataSet, params);
2619
2731
  }
2620
2732
  if (isDateCalculation(customField)) {
2621
- return build$7(measureAttribute, customField);
2733
+ return build$7(measureAttribute, customField, params.variables);
2622
2734
  }
2623
2735
  if (isCustomBuildMetric(customField)) {
2624
2736
  return build$8(measureAttribute, customField, dataSet, queryEngineConfig, params);
@@ -2933,13 +3045,44 @@ var dimensionSchema = function dimensionSchema(supportedTimeTruncFunctions, attr
2933
3045
  }
2934
3046
  return Joi.array().items(buildDimensionJoi(Joi.string().description('The ID of the field from the data set to reference.'), true)).description('Fields to group the data by');
2935
3047
  };
2936
- var filterSchema = function filterSchema(queryEngineConfig) {
3048
+ var queryFilterSchema = function queryFilterSchema(queryEngineConfig, maxDepth) {
2937
3049
  var _Joi$string3, _Joi$string4;
3050
+ if (maxDepth === void 0) {
3051
+ maxDepth = 10;
3052
+ }
3053
+ var whereFilterSchema = Joi.object({
3054
+ field: Joi.object({
3055
+ type: Joi.string().valid('field').required(),
3056
+ value: Joi.string().required().description('The ID of the field from the data set to reference.'),
3057
+ "function": (_Joi$string3 = Joi.string()).valid.apply(_Joi$string3, Object.keys(queryEngineConfig.supportedAggregates).concat(Object.keys(queryEngineConfig.supportedTimeTruncFunctions), ['none'])).description('Which function should be applied to the field?')
3058
+ }),
3059
+ op: (_Joi$string4 = Joi.string()).valid.apply(_Joi$string4, Object.keys(queryEngineConfig.supportedOperators)).required(),
3060
+ value: Joi.alternatives()["try"](joiDate, Joi.string().allow(null), Joi.number(), Joi["boolean"](), Joi.array().items(Joi.string(), Joi.number(), Joi.allow(null)), relativeSchema).required()
3061
+ });
3062
+ var _buildRecursiveSchema = function buildRecursiveSchema(depth) {
3063
+ if (depth <= 0) {
3064
+ return Joi.object({
3065
+ type: Joi.string().valid('where').required(),
3066
+ value: whereFilterSchema.required()
3067
+ });
3068
+ }
3069
+ return Joi.alternatives()["try"](Joi.object({
3070
+ type: Joi.string().valid('where').required(),
3071
+ value: whereFilterSchema.required()
3072
+ }), Joi.object({
3073
+ type: Joi.string().valid('andWhere', 'orWhere').required(),
3074
+ value: Joi.array().items(_buildRecursiveSchema(depth - 1)).min(1).required().description('Array of nested filters')
3075
+ }));
3076
+ };
3077
+ return _buildRecursiveSchema(maxDepth);
3078
+ };
3079
+ var filterSchema = function filterSchema(queryEngineConfig) {
3080
+ var _Joi$string5, _Joi$string6;
2938
3081
  return Joi.object({
2939
3082
  field: Joi.string().required().description('The ID of the field from the data set to reference.'),
2940
- op: (_Joi$string3 = Joi.string()).valid.apply(_Joi$string3, Object.keys(queryEngineConfig.supportedOperators)).required(),
3083
+ op: (_Joi$string5 = Joi.string()).valid.apply(_Joi$string5, Object.keys(queryEngineConfig.supportedOperators)).required(),
2941
3084
  value: Joi.alternatives()["try"](joiDate, Joi.string().allow(null), Joi.number(), Joi["boolean"](), Joi.array().items(Joi.string(), Joi.number(), Joi.allow(null)), relativeSchema).required(),
2942
- "function": (_Joi$string4 = Joi.string()).valid.apply(_Joi$string4, Object.keys(queryEngineConfig.supportedAggregates).concat(Object.keys(queryEngineConfig.supportedTimeTruncFunctions), ['none'])).description('Which function should be applied to the field?')
3085
+ "function": (_Joi$string6 = Joi.string()).valid.apply(_Joi$string6, Object.keys(queryEngineConfig.supportedAggregates).concat(Object.keys(queryEngineConfig.supportedTimeTruncFunctions), ['none'])).description('Which function should be applied to the field?')
2943
3086
  });
2944
3087
  };
2945
3088
  var queryAttributesFilter = function queryAttributesFilter(queryEngineConfig) {
@@ -2949,8 +3092,8 @@ var queryAttributesLimit = function queryAttributesLimit() {
2949
3092
  return Joi.number().description('Limit the number of results returned after the query has been ran.');
2950
3093
  };
2951
3094
  var baseAttributesSchema = function baseAttributesSchema(attributeSchemaOptions) {
2952
- var _Joi$string5;
2953
- var dataSetIdSchema = attributeSchemaOptions != null && attributeSchemaOptions.restrictDataSetIds ? (_Joi$string5 = Joi.string()).valid.apply(_Joi$string5, attributeSchemaOptions.restrictDataSetIds) : Joi.string();
3095
+ var _Joi$string7;
3096
+ var dataSetIdSchema = attributeSchemaOptions != null && attributeSchemaOptions.restrictDataSetIds ? (_Joi$string7 = Joi.string()).valid.apply(_Joi$string7, attributeSchemaOptions.restrictDataSetIds) : Joi.string();
2954
3097
  return {
2955
3098
  viewId: Joi.string().allow('').optional().description('__vizzly_hide_from_docs'),
2956
3099
  displayTitle: Joi.string().allow('').description('A title that explains what is being displayed.'),
@@ -2987,16 +3130,16 @@ var timeDimensionQuerySchema = function timeDimensionQuerySchema(queryEngineConf
2987
3130
  var lineCurveSchema = /*#__PURE__*/Joi.string().valid('natural', 'straight', 'step', 'stepBefore', 'stepAfter', 'dotted');
2988
3131
  var areaCurveSchema = /*#__PURE__*/Joi.string().valid('natural', 'straight', 'step');
2989
3132
  var protectedFieldsMeasure = function protectedFieldsMeasure(queryEngineConfig) {
2990
- var _Joi$string6;
3133
+ var _Joi$string8;
2991
3134
  return Joi.array().items(Joi.object({
2992
- "function": (_Joi$string6 = Joi.string()).valid.apply(_Joi$string6, Object.keys(queryEngineConfig.supportedAggregates).concat(Object.keys(queryEngineConfig.supportedTimeTruncFunctions), ['none'])),
3135
+ "function": (_Joi$string8 = Joi.string()).valid.apply(_Joi$string8, Object.keys(queryEngineConfig.supportedAggregates).concat(Object.keys(queryEngineConfig.supportedTimeTruncFunctions), ['none'])),
2993
3136
  field: Joi.string().required().description('The ID of the field from the data set to reference.')
2994
3137
  }));
2995
3138
  };
2996
3139
  var protectedFieldsDimension = function protectedFieldsDimension(queryEngineConfig) {
2997
- var _Joi$string7;
3140
+ var _Joi$string9;
2998
3141
  return Joi.array().items(Joi.object({
2999
- "function": (_Joi$string7 = Joi.string()).valid.apply(_Joi$string7, Object.keys(queryEngineConfig.supportedAggregates).concat(Object.keys(queryEngineConfig.supportedTimeTruncFunctions), ['none'])),
3142
+ "function": (_Joi$string9 = Joi.string()).valid.apply(_Joi$string9, Object.keys(queryEngineConfig.supportedAggregates).concat(Object.keys(queryEngineConfig.supportedTimeTruncFunctions), ['none'])),
3000
3143
  truncate: Joi.string(),
3001
3144
  field: Joi.string().required().description('The ID of the field from the data set to reference.'),
3002
3145
  bucketFill: Joi["boolean"]().optional(),
@@ -15127,8 +15270,7 @@ var fieldSchema = /*#__PURE__*/Joi.object({
15127
15270
  dataSetId: /*#__PURE__*/Joi.string().required()
15128
15271
  });
15129
15272
  var optionsFiltersSchema = function optionsFiltersSchema(queryEngineConfig) {
15130
- var innerArraySchema = Joi.array().items(filterSchema(queryEngineConfig));
15131
- return Joi.object().pattern(Joi.string(), Joi.array().items(innerArraySchema).optional());
15273
+ return Joi.object().pattern(Joi.string(), queryFilterSchema(queryEngineConfig));
15132
15274
  };
15133
15275
  var sharedAdditionalFilterSchema = function sharedAdditionalFilterSchema(queryEngineConfig) {
15134
15276
  return {
@@ -26400,7 +26542,9 @@ var buildFromQueryAttributes = function buildFromQueryAttributes(dataSet, measur
26400
26542
  var measure = [];
26401
26543
  var group = [];
26402
26544
  var order = [];
26403
- var filters = filterAttributeToQueryFilter(filterAttr, queryEngineConfig, dataSet, params);
26545
+ var queryFilterConfig = combineFiltersFromFilterConfig(params.filterConfig, dataSet, params.timeRangeOptions, params.variables);
26546
+ var queryFiltersFromAttributes = convertArrayFilterStructureToQueryFilter(filterAttr, params.variables);
26547
+ var filters = combineQueryFilters(queryFilterConfig, queryFiltersFromAttributes);
26404
26548
  if (timeDimensionAttr) {
26405
26549
  // Add the measure for the time field.
26406
26550
  var addedAt = undefined;
@@ -40255,7 +40399,8 @@ var _GlobalFiltersView = /*#__PURE__*/withCustomRenderGuard(function (props) {
40255
40399
  dateFilterOptions = _useDashboardBehaviou.dateFilterOptions,
40256
40400
  featureToggles = _useDashboardBehaviou.featureToggles,
40257
40401
  cascadeFilterSelection = _useDashboardBehaviou.cascadeFilterSelection,
40258
- scope = _useDashboardBehaviou.scope;
40402
+ scope = _useDashboardBehaviou.scope,
40403
+ variables = _useDashboardBehaviou.variables;
40259
40404
  return jsxRuntime.jsxs(Flex, {
40260
40405
  gap: "0.5rem",
40261
40406
  "data-component": "filters",
@@ -40263,12 +40408,13 @@ var _GlobalFiltersView = /*#__PURE__*/withCustomRenderGuard(function (props) {
40263
40408
  wrap: true,
40264
40409
  children: [props.globalFilters.length > 0 && jsxRuntime.jsx(React.Fragment, {
40265
40410
  children: [].concat(props.globalFilters).map(function (globalFilter, globalFilterIndex) {
40411
+ var _variables$variables;
40266
40412
  return jsxRuntime.jsx(AdditionalFilter, {
40267
40413
  shouldAlwaysHaveValue: globalFilter.requiresValue,
40268
40414
  dataSets: dashboard.dataSets,
40269
40415
  dateFilterOptions: dateFilterOptions,
40270
40416
  filter: _extends({}, globalFilter, {
40271
- optionsFilters: getCascadeOptionsFilters(props == null ? void 0 : props.globalFilters, dashboard.dataSets, dateFilterOptions, cascadeFilterSelection)
40417
+ optionsFilters: getCascadeOptionsFilters(props == null ? void 0 : props.globalFilters, dashboard.dataSets, dateFilterOptions, (_variables$variables = variables == null ? void 0 : variables.variables) != null ? _variables$variables : {}, cascadeFilterSelection)
40272
40418
  }),
40273
40419
  filterIndex: globalFilterIndex,
40274
40420
  onChange: function onChange(newFilter) {
@@ -74150,7 +74296,9 @@ var toQueries$1 = function toQueries$1(additionalFilter, dataSets, queryEngineCo
74150
74296
  if (!dataSet) throw 'Data set not found for additional filter query';
74151
74297
  var dataSetField = findField(dataSet, field.fieldId);
74152
74298
  if (dataSetField.dataType == 'string[]') {
74153
- var queryFilter = filterAttributeToQueryFilter(getOptionsFilters(additionalFilter, field), queryEngineConfig, dataSet, params);
74299
+ var optionsFilter = getOptionsFilters(additionalFilter, field);
74300
+ var queryFilterConfig = combineFiltersFromFilterConfig(params.filterConfig, dataSet, params.timeRangeOptions, params.variables);
74301
+ var queryFilter = combineQueryFilters(queryFilterConfig, optionsFilter);
74154
74302
  var _QueryLogic$buildUniq = buildUniqueArrayValuesPreparedQuery(field.dataSetId, dataSetField, queryFilter),
74155
74303
  query = _QueryLogic$buildUniq.query,
74156
74304
  resultFields = _QueryLogic$buildUniq.resultFields;
@@ -74159,8 +74307,17 @@ var toQueries$1 = function toQueries$1(additionalFilter, dataSets, queryEngineCo
74159
74307
  resultFields: [resultFields]
74160
74308
  };
74161
74309
  } else {
74162
- var filterQuery = buildFilterQuery(dataSet, field.fieldId, getOptionsFilters(additionalFilter, field), getOptionsOrders(dataSetField));
74163
- return toQueries(dataSets, [filterQuery], queryEngineConfig, params);
74310
+ var optionFilters = getOptionsFilters(additionalFilter, field);
74311
+ var filterQuery = buildFilterQuery(dataSet, field.fieldId, [], getOptionsOrders(dataSetField));
74312
+ var queryWithoutFilters = toQueries(dataSets, [filterQuery], queryEngineConfig, params);
74313
+ return {
74314
+ resultFields: queryWithoutFilters.resultFields,
74315
+ queries: queryWithoutFilters.queries.map(function (q) {
74316
+ return _extends({}, q, {
74317
+ filter: optionFilters
74318
+ });
74319
+ })
74320
+ };
74164
74321
  }
74165
74322
  });
74166
74323
  return {
@@ -74173,21 +74330,45 @@ var toQueries$1 = function toQueries$1(additionalFilter, dataSets, queryEngineCo
74173
74330
  };
74174
74331
  };
74175
74332
  function getOptionsFilters(additionalFilter, field) {
74176
- if (!additionalFilter.optionsFilters) {
74177
- return [];
74333
+ var optionsFilters = additionalFilter.optionsFilters ? additionalFilter.optionsFilters[field.dataSetId] : undefined;
74334
+ if (!optionsFilters) {
74335
+ return {
74336
+ type: 'andWhere',
74337
+ value: []
74338
+ };
74178
74339
  }
74179
- if (!(field.dataSetId in additionalFilter.optionsFilters)) {
74180
- return [];
74340
+ var filteredQuery = filterOutFieldId(optionsFilters, field.fieldId);
74341
+ return filteredQuery || {
74342
+ type: 'andWhere',
74343
+ value: []
74344
+ };
74345
+ }
74346
+ function filterOutFieldId(filter, fieldIdToExclude) {
74347
+ if (filter.type === 'where') {
74348
+ var field = getFieldFromFilter(filter);
74349
+ if (field && field.value === fieldIdToExclude) {
74350
+ return null;
74351
+ }
74352
+ return filter;
74181
74353
  }
74182
- var optionsFilters = additionalFilter.optionsFilters[field.dataSetId];
74183
- var orFilter = optionsFilters.map(function (filter) {
74184
- return filter.filter(function (f) {
74185
- return f.field !== field.fieldId;
74354
+ if (filter.type === 'andWhere' || filter.type === 'orWhere') {
74355
+ var filteredValues = filter.value.map(function (f) {
74356
+ return filterOutFieldId(f, fieldIdToExclude);
74357
+ }).filter(function (f) {
74358
+ return f !== null;
74186
74359
  });
74187
- });
74188
- return orFilter.filter(function (f) {
74189
- return f.length > 0;
74190
- });
74360
+ if (filteredValues.length === 0) {
74361
+ return null;
74362
+ }
74363
+ if (filteredValues.length === 1 && filteredValues[0].type === filter.type) {
74364
+ return filteredValues[0];
74365
+ }
74366
+ return {
74367
+ type: filter.type,
74368
+ value: filteredValues
74369
+ };
74370
+ }
74371
+ return filter;
74191
74372
  }
74192
74373
  function getOptionsOrders(dataSetField) {
74193
74374
  if ((dataSetField == null ? void 0 : dataSetField.dataType) === 'string' || (dataSetField == null ? void 0 : dataSetField.dataType) === 'number') {
@@ -74473,11 +74654,7 @@ var buildVizzlyQuery = function buildVizzlyQuery(thing, queryEngineConfig, param
74473
74654
  query = _QueryLogic$buildPreA.query,
74474
74655
  rF = _QueryLogic$buildPreA.resultFields;
74475
74656
  var underlyingDataSet = find(params.dataSets, underlyingDataSetId);
74476
- var filter = filterAttributeToQueryFilter([], queryEngineConfig, underlyingDataSet, _extends({}, params, {
74477
- filterConfig: _extends({}, params.filterConfig, {
74478
- viewFilters: undefined
74479
- })
74480
- }));
74657
+ var filter = combineFiltersFromFilterConfig(params.filterConfig, underlyingDataSet, params.timeRangeOptions, params.variables);
74481
74658
  queriesToSend = [_extends({}, query, {
74482
74659
  filter: (_filter = {}, _filter[underlyingDataSet.id] = filter, _filter)
74483
74660
  })];
@@ -74530,6 +74707,14 @@ var buildVizzlyQuery = function buildVizzlyQuery(thing, queryEngineConfig, param
74530
74707
  });
74531
74708
  });
74532
74709
  }
74710
+ queriesToSend = queriesToSend.map(function (q) {
74711
+ if (q.type === 'query') {
74712
+ return _extends({}, q, {
74713
+ filter: buildQueryCustomMetrics(q.filter, find(params.dataSets, q.dataSetId), queryEngineConfig, params)
74714
+ });
74715
+ }
74716
+ return q;
74717
+ });
74533
74718
  return {
74534
74719
  queries: queriesToSend,
74535
74720
  resultFields: resultFields