@lightdash/common 0.1477.4 → 0.1478.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,17 @@
1
1
  import { type ConditionalOperator, type ConditionalRule } from './conditionalRule';
2
2
  import { type FieldTarget } from './filter';
3
- export type ConditionalFormattingWithConditionalOperator<T = number> = ConditionalRule<ConditionalOperator, T> & {
4
- values: T[];
5
- };
6
- export type ConditionalFormattingWithRange<T = number> = {
3
+ export type ConditionalFormattingMinMax<T = number> = {
7
4
  min: T;
8
5
  max: T;
9
6
  };
7
+ export type ConditionalFormattingColorRange = {
8
+ start: string;
9
+ end: string;
10
+ steps: number;
11
+ };
12
+ export type ConditionalFormattingWithConditionalOperator<T = number> = ConditionalRule<ConditionalOperator, T> & {
13
+ values: T[];
14
+ };
10
15
  export type ConditionalFormattingConfigWithSingleColor = {
11
16
  target: FieldTarget | null;
12
17
  color: string;
@@ -15,12 +20,8 @@ export type ConditionalFormattingConfigWithSingleColor = {
15
20
  export declare const isConditionalFormattingConfigWithSingleColor: (rule: ConditionalFormattingConfig) => rule is ConditionalFormattingConfigWithSingleColor;
16
21
  export type ConditionalFormattingConfigWithColorRange = {
17
22
  target: FieldTarget | null;
18
- color: {
19
- start: string;
20
- end: string;
21
- steps: 5;
22
- };
23
- rule: ConditionalFormattingWithRange;
23
+ color: ConditionalFormattingColorRange;
24
+ rule: ConditionalFormattingMinMax<number | 'auto'>;
24
25
  };
25
26
  export declare const isConditionalFormattingConfigWithColorRange: (config: ConditionalFormattingConfig) => config is ConditionalFormattingConfigWithColorRange;
26
27
  export type ConditionalFormattingConfig = ConditionalFormattingConfigWithSingleColor | ConditionalFormattingConfigWithColorRange;
@@ -29,3 +30,4 @@ export declare enum ConditionalFormattingConfigType {
29
30
  Range = "range"
30
31
  }
31
32
  export declare const getConditionalFormattingConfigType: (rule: ConditionalFormattingConfig) => ConditionalFormattingConfigType;
33
+ export type ConditionalFormattingMinMaxMap = Record<string, ConditionalFormattingMinMax>;
@@ -1,5 +1,5 @@
1
1
  import type { ItemsMap } from '..';
2
- import { type ConditionalFormattingConfig, type ConditionalFormattingConfigWithColorRange, type ConditionalFormattingConfigWithSingleColor, type ConditionalFormattingWithConditionalOperator } from '../types/conditionalFormatting';
2
+ import { type ConditionalFormattingColorRange, type ConditionalFormattingConfig, type ConditionalFormattingConfigWithColorRange, type ConditionalFormattingConfigWithSingleColor, type ConditionalFormattingMinMax, type ConditionalFormattingMinMaxMap, type ConditionalFormattingWithConditionalOperator } from '../types/conditionalFormatting';
3
3
  import { type ConditionalRuleLabels } from '../types/conditionalRule';
4
4
  import { type FilterableItem } from '../types/field';
5
5
  import { type FieldTarget } from '../types/filter';
@@ -7,17 +7,35 @@ export declare const createConditionalFormatingRule: () => ConditionalFormatting
7
7
  export declare const createConditionalFormattingConfigWithSingleColor: (defaultColor: string, target?: FieldTarget | null) => ConditionalFormattingConfigWithSingleColor;
8
8
  export declare const createConditionalFormattingConfigWithColorRange: (defaultColor: string, target?: FieldTarget | null) => ConditionalFormattingConfigWithColorRange;
9
9
  export declare const hasPercentageFormat: (field: ItemsMap[string] | undefined) => boolean;
10
- export declare const hasMatchingConditionalRules: (field: ItemsMap[string], value: unknown, config: ConditionalFormattingConfig | undefined) => boolean;
11
- export declare const getConditionalFormattingConfig: (field: ItemsMap[string] | undefined, value: unknown | undefined, conditionalFormattings: ConditionalFormattingConfig[] | undefined) => ConditionalFormattingConfig | undefined;
10
+ export declare const convertFormattedValue: <T extends unknown>(value: T, field: ItemsMap[string] | undefined) => number | T;
11
+ export declare const getMinMaxFromMinMaxMap: (minMaxMap: ConditionalFormattingMinMaxMap) => {
12
+ min: number;
13
+ max: number;
14
+ };
15
+ export declare const hasMatchingConditionalRules: (field: ItemsMap[string], value: unknown, minMaxMap: ConditionalFormattingMinMaxMap, config: ConditionalFormattingConfig | undefined) => boolean;
16
+ export declare const getConditionalFormattingConfig: ({ field, value, minMaxMap, conditionalFormattings, }: {
17
+ field: ItemsMap[string] | undefined;
18
+ value: unknown | undefined;
19
+ minMaxMap: ConditionalFormattingMinMaxMap | undefined;
20
+ conditionalFormattings: ConditionalFormattingConfig[] | undefined;
21
+ }) => ConditionalFormattingConfig | undefined;
12
22
  export declare const getConditionalFormattingDescription: (field: ItemsMap[string] | undefined, conditionalFormattingConfig: ConditionalFormattingConfig | undefined, getConditionalRuleLabel: (rule: ConditionalFormattingWithConditionalOperator, item: FilterableItem) => ConditionalRuleLabels) => string | undefined;
13
- export declare const getConditionalFormattingColor: (field: ItemsMap[string] | undefined, value: unknown, conditionalFormattingConfig: ConditionalFormattingConfig | undefined, getColorFromRange: (value: number, config: {
14
- color: {
15
- start: string;
16
- end: string;
17
- steps: number;
18
- };
19
- rule: {
20
- min: number;
21
- max: number;
22
- };
23
- }) => string | undefined) => string | undefined;
23
+ type GetColorFromRangeFunction = (value: number, colorRange: ConditionalFormattingColorRange, minMaxRange: ConditionalFormattingMinMax) => string | undefined;
24
+ export declare const getConditionalFormattingColorWithColorRange: ({ field, value, config, minMaxMap, getColorFromRange, }: {
25
+ field: ItemsMap[string] | undefined;
26
+ value: unknown;
27
+ config: ConditionalFormattingConfigWithColorRange;
28
+ minMaxMap: ConditionalFormattingMinMaxMap | undefined;
29
+ getColorFromRange: GetColorFromRangeFunction;
30
+ }) => string | undefined;
31
+ export declare const getConditionalFormattingColorWithSingleColor: ({ config, }: {
32
+ config: ConditionalFormattingConfigWithSingleColor;
33
+ }) => string;
34
+ export declare const getConditionalFormattingColor: ({ field, value, config, minMaxMap, getColorFromRange, }: {
35
+ field: ItemsMap[string] | undefined;
36
+ value: unknown;
37
+ config: ConditionalFormattingConfig | undefined;
38
+ minMaxMap: ConditionalFormattingMinMaxMap | undefined;
39
+ getColorFromRange: GetColorFromRangeFunction;
40
+ }) => string | undefined;
41
+ export {};
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getConditionalFormattingColor = exports.getConditionalFormattingDescription = exports.getConditionalFormattingConfig = exports.hasMatchingConditionalRules = exports.hasPercentageFormat = exports.createConditionalFormattingConfigWithColorRange = exports.createConditionalFormattingConfigWithSingleColor = exports.createConditionalFormatingRule = void 0;
3
+ exports.getConditionalFormattingColor = exports.getConditionalFormattingColorWithSingleColor = exports.getConditionalFormattingColorWithColorRange = exports.getConditionalFormattingDescription = exports.getConditionalFormattingConfig = exports.hasMatchingConditionalRules = exports.getMinMaxFromMinMaxMap = exports.convertFormattedValue = exports.hasPercentageFormat = exports.createConditionalFormattingConfigWithColorRange = exports.createConditionalFormattingConfigWithSingleColor = exports.createConditionalFormatingRule = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const lodash_1 = require("lodash");
5
6
  const uuid_1 = require("uuid");
6
7
  const conditionalFormatting_1 = require("../types/conditionalFormatting");
7
8
  const conditionalRule_1 = require("../types/conditionalRule");
@@ -49,11 +50,22 @@ const convertFormattedValue = (value, field) => {
49
50
  }
50
51
  return value;
51
52
  };
52
- const hasMatchingConditionalRules = (field, value, config) => {
53
+ exports.convertFormattedValue = convertFormattedValue;
54
+ const getMinMaxFromMinMaxMap = (minMaxMap) => ({
55
+ min: Math.min(...Object.values(minMaxMap).map((m) => m.min)),
56
+ max: Math.max(...Object.values(minMaxMap).map((m) => m.max)),
57
+ });
58
+ exports.getMinMaxFromMinMaxMap = getMinMaxFromMinMaxMap;
59
+ const hasMatchingConditionalRules = (field, value, minMaxMap, config) => {
53
60
  if (!config)
54
61
  return false;
55
62
  const parsedValue = typeof value === 'string' ? Number(value) : value;
56
- const convertedValue = convertFormattedValue(parsedValue, field);
63
+ const convertedValue = (0, exports.convertFormattedValue)(parsedValue, field);
64
+ const currentFieldId = (0, item_1.getItemId)(field);
65
+ const targetFieldId = config.target?.fieldId;
66
+ if (targetFieldId !== undefined && targetFieldId !== currentFieldId) {
67
+ return false;
68
+ }
57
69
  if ((0, conditionalFormatting_1.isConditionalFormattingConfigWithSingleColor)(config)) {
58
70
  return config.rules.every((rule) => {
59
71
  switch (rule.operator) {
@@ -94,23 +106,37 @@ const hasMatchingConditionalRules = (field, value, config) => {
94
106
  if ((0, conditionalFormatting_1.isConditionalFormattingConfigWithColorRange)(config)) {
95
107
  if (typeof convertedValue !== 'number')
96
108
  return false;
97
- return (convertedValue >= config.rule.min &&
98
- convertedValue <= config.rule.max);
109
+ let min;
110
+ let max;
111
+ if (config.rule.min === 'auto') {
112
+ min = targetFieldId
113
+ ? minMaxMap[targetFieldId].min
114
+ : (0, exports.getMinMaxFromMinMaxMap)(minMaxMap).min;
115
+ }
116
+ else {
117
+ min = config.rule.min;
118
+ }
119
+ if (config.rule.max === 'auto') {
120
+ max = targetFieldId
121
+ ? minMaxMap[targetFieldId].max
122
+ : (0, exports.getMinMaxFromMinMaxMap)(minMaxMap).max;
123
+ }
124
+ else {
125
+ max = config.rule.max;
126
+ }
127
+ return convertedValue >= min && convertedValue <= max;
99
128
  }
100
129
  return (0, assertUnreachable_1.default)(config, 'Unknown conditional formatting config');
101
130
  };
102
131
  exports.hasMatchingConditionalRules = hasMatchingConditionalRules;
103
- const getConditionalFormattingConfig = (field, value, conditionalFormattings) => {
132
+ const getConditionalFormattingConfig = ({ field, value, minMaxMap = {}, conditionalFormattings, }) => {
104
133
  // For backwards compatibility with old table calculations without type
105
134
  const isCalculationTypeUndefined = field && (0, field_1.isTableCalculation)(field) && field.type === undefined;
106
135
  if (!conditionalFormattings ||
107
136
  !field ||
108
137
  (!(0, item_1.isNumericItem)(field) && !isCalculationTypeUndefined))
109
138
  return undefined;
110
- const fieldConfigs = conditionalFormattings.filter((c) => c.target?.fieldId === (0, item_1.getItemId)(field) || !c.target);
111
- return fieldConfigs
112
- .reverse()
113
- .find((config) => (0, exports.hasMatchingConditionalRules)(field, value, config));
139
+ return (0, lodash_1.findLast)(conditionalFormattings, (config) => (0, exports.hasMatchingConditionalRules)(field, value, minMaxMap, config));
114
140
  };
115
141
  exports.getConditionalFormattingConfig = getConditionalFormattingConfig;
116
142
  const getConditionalFormattingDescription = (field, conditionalFormattingConfig, getConditionalRuleLabel) => {
@@ -119,8 +145,12 @@ const getConditionalFormattingDescription = (field, conditionalFormattingConfig,
119
145
  }
120
146
  if ((0, conditionalFormatting_1.isConditionalFormattingConfigWithColorRange)(conditionalFormattingConfig)) {
121
147
  return [
122
- `is greater than or equal to ${conditionalFormattingConfig.rule.min}`,
123
- `is less than or equal to ${conditionalFormattingConfig.rule.max}`,
148
+ `is greater than or equal to ${conditionalFormattingConfig.rule.min === 'auto'
149
+ ? 'min value in table'
150
+ : conditionalFormattingConfig.rule.min}`,
151
+ `is less than or equal to ${conditionalFormattingConfig.rule.max === 'auto'
152
+ ? 'max value in table'
153
+ : conditionalFormattingConfig.rule.max}`,
124
154
  ].join(' and ');
125
155
  }
126
156
  if ((0, conditionalFormatting_1.isConditionalFormattingConfigWithSingleColor)(conditionalFormattingConfig)) {
@@ -132,20 +162,53 @@ const getConditionalFormattingDescription = (field, conditionalFormattingConfig,
132
162
  return (0, assertUnreachable_1.default)(conditionalFormattingConfig, 'Unknown conditional formatting config');
133
163
  };
134
164
  exports.getConditionalFormattingDescription = getConditionalFormattingDescription;
135
- const getConditionalFormattingColor = (field, value, conditionalFormattingConfig, getColorFromRange) => {
136
- if (!conditionalFormattingConfig) {
165
+ const getConditionalFormattingColorWithColorRange = ({ field, value, config, minMaxMap = {}, getColorFromRange, }) => {
166
+ if (!field)
167
+ return undefined;
168
+ const numericValue = typeof value === 'string' ? parseFloat(value) : value;
169
+ const convertedValue = (0, exports.convertFormattedValue)(numericValue, field);
170
+ const currentFieldId = (0, item_1.getItemId)(field);
171
+ const targetFieldId = config.target?.fieldId;
172
+ if (targetFieldId !== undefined && targetFieldId !== currentFieldId) {
137
173
  return undefined;
138
174
  }
139
- if ((0, conditionalFormatting_1.isConditionalFormattingConfigWithColorRange)(conditionalFormattingConfig)) {
140
- const numericValue = typeof value === 'string' ? parseFloat(value) : value;
141
- const convertedValue = convertFormattedValue(numericValue, field);
142
- if (typeof convertedValue !== 'number')
143
- return undefined;
144
- return getColorFromRange(convertedValue, conditionalFormattingConfig);
175
+ if (typeof convertedValue !== 'number')
176
+ return undefined;
177
+ let min;
178
+ let max;
179
+ if (config.rule.min === 'auto') {
180
+ min = targetFieldId
181
+ ? minMaxMap[targetFieldId].min
182
+ : (0, exports.getMinMaxFromMinMaxMap)(minMaxMap).min;
145
183
  }
146
- if ((0, conditionalFormatting_1.isConditionalFormattingConfigWithSingleColor)(conditionalFormattingConfig)) {
147
- return conditionalFormattingConfig.color;
184
+ else {
185
+ min = config.rule.min;
148
186
  }
149
- return (0, assertUnreachable_1.default)(conditionalFormattingConfig, 'Unknown conditional formatting config');
187
+ if (config.rule.max === 'auto') {
188
+ max = targetFieldId
189
+ ? minMaxMap[targetFieldId].max
190
+ : (0, exports.getMinMaxFromMinMaxMap)(minMaxMap).max;
191
+ }
192
+ else {
193
+ max = config.rule.max;
194
+ }
195
+ return getColorFromRange(convertedValue, config.color, { min, max });
196
+ };
197
+ exports.getConditionalFormattingColorWithColorRange = getConditionalFormattingColorWithColorRange;
198
+ const getConditionalFormattingColorWithSingleColor = ({ config, }) => config.color;
199
+ exports.getConditionalFormattingColorWithSingleColor = getConditionalFormattingColorWithSingleColor;
200
+ const getConditionalFormattingColor = ({ field, value, config, minMaxMap, getColorFromRange, }) => {
201
+ if (!config)
202
+ return undefined;
203
+ if ((0, conditionalFormatting_1.isConditionalFormattingConfigWithSingleColor)(config)) {
204
+ return (0, exports.getConditionalFormattingColorWithSingleColor)({ config });
205
+ }
206
+ return (0, exports.getConditionalFormattingColorWithColorRange)({
207
+ field,
208
+ value,
209
+ config,
210
+ minMaxMap,
211
+ getColorFromRange,
212
+ });
150
213
  };
151
214
  exports.getConditionalFormattingColor = getConditionalFormattingColor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/common",
3
- "version": "0.1477.4",
3
+ "version": "0.1478.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [