@quillsql/react 2.8.8 → 2.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AddToDashboardModal.js +146 -181
- package/dist/BarList.js +36 -44
- package/dist/Chart.d.ts +0 -5
- package/dist/Chart.d.ts.map +1 -1
- package/dist/Chart.js +94 -276
- package/dist/ChartBuilder.d.ts +1 -0
- package/dist/ChartBuilder.d.ts.map +1 -1
- package/dist/ChartBuilder.js +96 -93
- package/dist/ChartEditor.d.ts +2 -1
- package/dist/ChartEditor.d.ts.map +1 -1
- package/dist/ChartEditor.js +14 -21
- package/dist/Context.js +52 -57
- package/dist/Dashboard.d.ts.map +1 -1
- package/dist/Dashboard.js +181 -213
- package/dist/DateRangePicker/Calendar.js +41 -46
- package/dist/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/DateRangePicker/DateRangePicker.js +33 -62
- package/dist/DateRangePicker/DateRangePickerButton.js +14 -17
- package/dist/DateRangePicker/dateRangePickerUtils.js +76 -90
- package/dist/DateRangePicker/index.js +1 -9
- package/dist/PieChart.js +35 -70
- package/dist/QuillProvider.js +4 -7
- package/dist/ReportBuilder.js +120 -129
- package/dist/SQLEditor.d.ts +5 -1
- package/dist/SQLEditor.d.ts.map +1 -1
- package/dist/SQLEditor.js +82 -89
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +64 -66
- package/dist/TableChart.js +17 -45
- package/dist/assets/ArrowDownHeadIcon.js +3 -6
- package/dist/assets/ArrowDownIcon.js +3 -6
- package/dist/assets/ArrowDownRightIcon.js +3 -6
- package/dist/assets/ArrowLeftHeadIcon.js +3 -6
- package/dist/assets/ArrowRightHeadIcon.js +3 -6
- package/dist/assets/ArrowRightIcon.js +3 -6
- package/dist/assets/ArrowUpHeadIcon.js +3 -6
- package/dist/assets/ArrowUpIcon.js +3 -6
- package/dist/assets/ArrowUpRightIcon.js +3 -6
- package/dist/assets/CalendarIcon.js +3 -6
- package/dist/assets/CalendarNormalIcon.js +3 -6
- package/dist/assets/DoubleArrowLeftHeadIcon.js +3 -6
- package/dist/assets/DoubleArrowRightHeadIcon.js +3 -6
- package/dist/assets/ExclamationFilledIcon.js +3 -6
- package/dist/assets/FilterIcon.js +3 -6
- package/dist/assets/LoadingSpinner.js +3 -6
- package/dist/assets/RefreshIcon.js +3 -6
- package/dist/assets/SearchIcon.js +3 -6
- package/dist/assets/UpLeftArrowsIcon.js +3 -6
- package/dist/assets/XCircleIcon.js +3 -6
- package/dist/assets/XIcon.js +3 -6
- package/dist/assets/index.js +21 -49
- package/dist/components/Banner/index.d.ts +3 -0
- package/dist/components/Banner/index.d.ts.map +1 -0
- package/dist/components/Banner/index.js +24 -0
- package/dist/components/BigModal/BigModal.js +13 -39
- package/dist/components/Dropdown/Dropdown.js +24 -53
- package/dist/components/Dropdown/DropdownItem.js +9 -35
- package/dist/components/Dropdown/index.js +2 -11
- package/dist/components/Modal/Modal.js +13 -39
- package/dist/components/Modal/index.js +1 -9
- package/dist/components/QuillCard.js +8 -13
- package/dist/components/ReportBuilder/ColumnSelector.d.ts +19 -0
- package/dist/components/ReportBuilder/ColumnSelector.d.ts.map +1 -0
- package/dist/components/ReportBuilder/ColumnSelector.js +87 -0
- package/dist/components/SqlTextEditor.d.ts.map +1 -1
- package/dist/components/SqlTextEditor.js +30 -13
- package/dist/components/UiComponents.d.ts.map +1 -1
- package/dist/components/UiComponents.js +40 -53
- package/dist/components/selectUtils.js +6 -17
- package/dist/contexts/BaseColorContext.js +3 -6
- package/dist/contexts/HoveredValueContext.js +3 -6
- package/dist/contexts/RootStylesContext.js +3 -6
- package/dist/contexts/SelectedValueContext.js +3 -6
- package/dist/contexts/index.js +4 -15
- package/dist/hooks/index.js +4 -15
- package/dist/hooks/useDashboard.js +10 -15
- package/dist/hooks/useInternalState.js +3 -6
- package/dist/hooks/useOnClickOutside.js +3 -6
- package/dist/hooks/useOnWindowResize.js +4 -7
- package/dist/hooks/useQuill.js +11 -16
- package/dist/hooks/useSelectOnKeyDown.js +4 -7
- package/dist/index.js +13 -33
- package/dist/internals/ReportBuilder/PivotList.js +14 -20
- package/dist/internals/ReportBuilder/PivotModal.d.ts +2 -2
- package/dist/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/internals/ReportBuilder/PivotModal.js +116 -119
- package/dist/internals/ReportBuilder/PivotModal.spec.js +70 -73
- package/dist/lib/font.js +2 -6
- package/dist/lib/index.js +3 -20
- package/dist/lib/inputTypes.js +1 -3
- package/dist/lib/utils.js +8 -19
- package/dist/test-data/tables.d.ts +2 -0
- package/dist/test-data/tables.d.ts.map +1 -0
- package/dist/test-data/tables.js +621 -0
- package/dist/utils/aggregate.js +28 -35
- package/dist/utils/axisFormatter.d.ts +20 -0
- package/dist/utils/axisFormatter.d.ts.map +1 -0
- package/dist/utils/axisFormatter.js +185 -0
- package/dist/utils/colorToHex.js +1 -5
- package/dist/utils/dataFetcher.js +2 -8
- package/dist/utils/downloadCSV.js +1 -6
- package/dist/utils/schema.d.ts +22 -0
- package/dist/utils/schema.d.ts.map +1 -0
- package/dist/utils/schema.js +134 -0
- package/dist/utils/textFormatting.d.ts +4 -0
- package/dist/utils/textFormatting.d.ts.map +1 -0
- package/dist/utils/textFormatting.js +38 -0
- package/dist/utils/valueFormatter.d.ts +17 -0
- package/dist/utils/valueFormatter.d.ts.map +1 -0
- package/dist/utils/valueFormatter.js +166 -0
- package/dist/utils/valueFormatterCSV.d.ts +17 -0
- package/dist/utils/valueFormatterCSV.d.ts.map +1 -0
- package/dist/utils/valueFormatterCSV.js +90 -0
- package/package.json +1 -2
package/dist/utils/aggregate.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.aggregate = exports.aggregate2 = exports.whatIsProbablyTheType = void 0;
|
|
4
1
|
// @ts-nocheck
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import { getPostgresBasicType } from '../ReportBuilder';
|
|
3
|
+
import { COMPARISON_OPTIONS } from '../Dashboard';
|
|
4
|
+
import { add, sub, startOfWeek, startOfDay, startOfMonth, startOfYear, parse, } from 'date-fns';
|
|
8
5
|
function findTimePeriod(dateFilter) {
|
|
9
6
|
if (!dateFilter) {
|
|
10
7
|
return null;
|
|
@@ -53,7 +50,7 @@ function findTimePeriod(dateFilter) {
|
|
|
53
50
|
else
|
|
54
51
|
return 'year';
|
|
55
52
|
}
|
|
56
|
-
function whatIsProbablyTheType(data, fieldName) {
|
|
53
|
+
export function whatIsProbablyTheType(data, fieldName) {
|
|
57
54
|
const counts = {
|
|
58
55
|
date: 0,
|
|
59
56
|
number: 0,
|
|
@@ -87,15 +84,14 @@ function whatIsProbablyTheType(data, fieldName) {
|
|
|
87
84
|
const maxType = Object.keys(counts).reduce((a, b) => counts[a] > counts[b] ? a : b);
|
|
88
85
|
return maxType;
|
|
89
86
|
}
|
|
90
|
-
|
|
91
|
-
function aggregate2(dashboardItem, bucketFields, dateFilter) {
|
|
87
|
+
export function aggregate2(dashboardItem, bucketFields, dateFilter) {
|
|
92
88
|
const timePeriod = findTimePeriod(dateFilter);
|
|
93
89
|
const rows = dashboardItem.rows;
|
|
94
90
|
const xAxisLabel = timePeriod;
|
|
95
91
|
const xAxisField = timePeriod;
|
|
96
92
|
if (!bucketFields.length || !rows.length)
|
|
97
93
|
return { ...dashboardItem, bucketedRows: [] };
|
|
98
|
-
if (
|
|
94
|
+
if (getPostgresBasicType(dashboardItem.fields.find(field => field.name === bucketFields[0].field)) === 'string') {
|
|
99
95
|
const stringField = bucketFields[0].field;
|
|
100
96
|
const aggregation = {};
|
|
101
97
|
// let aggregatedArray;
|
|
@@ -126,7 +122,7 @@ function aggregate2(dashboardItem, bucketFields, dateFilter) {
|
|
|
126
122
|
bucketedRows: aggregatedArray,
|
|
127
123
|
};
|
|
128
124
|
}
|
|
129
|
-
else if (
|
|
125
|
+
else if (getPostgresBasicType(dashboardItem.fields.find(field => field.name === bucketFields[0].field)) === 'date') {
|
|
130
126
|
const dateField = bucketFields[0].field;
|
|
131
127
|
let xAxisFormat;
|
|
132
128
|
switch (timePeriod) {
|
|
@@ -200,8 +196,7 @@ function aggregate2(dashboardItem, bucketFields, dateFilter) {
|
|
|
200
196
|
return dashboardItem;
|
|
201
197
|
}
|
|
202
198
|
}
|
|
203
|
-
|
|
204
|
-
function aggregate(dashboardItem, bucketFields, dateFilter) {
|
|
199
|
+
export function aggregate(dashboardItem, bucketFields, dateFilter) {
|
|
205
200
|
const timePeriod = dateFilter && Object.keys(dateFilter).length
|
|
206
201
|
? findTimePeriod(dateFilter)
|
|
207
202
|
: 'month';
|
|
@@ -216,7 +211,7 @@ function aggregate(dashboardItem, bucketFields, dateFilter) {
|
|
|
216
211
|
//TODO: allow comparison for nonbucketed
|
|
217
212
|
return { ...dashboardItem, bucketedRows: [] };
|
|
218
213
|
}
|
|
219
|
-
if (
|
|
214
|
+
if (getPostgresBasicType(dashboardItem.fields.find(field => field.name === bucketFields[0].field)) === 'string') {
|
|
220
215
|
const stringField = bucketFields[0].field;
|
|
221
216
|
const aggregation = {};
|
|
222
217
|
rows.forEach(row => {
|
|
@@ -245,7 +240,7 @@ function aggregate(dashboardItem, bucketFields, dateFilter) {
|
|
|
245
240
|
bucketedRows: aggregatedArray,
|
|
246
241
|
};
|
|
247
242
|
}
|
|
248
|
-
else if (
|
|
243
|
+
else if (getPostgresBasicType(dashboardItem.fields.find(field => field.name === bucketFields[0].field)) === 'date') {
|
|
249
244
|
const dateField = bucketFields[0].field;
|
|
250
245
|
let interval;
|
|
251
246
|
let xAxisFormat;
|
|
@@ -273,19 +268,19 @@ function aggregate(dashboardItem, bucketFields, dateFilter) {
|
|
|
273
268
|
let formattedDate;
|
|
274
269
|
switch (timePeriod) {
|
|
275
270
|
case 'day': {
|
|
276
|
-
formattedDate =
|
|
271
|
+
formattedDate = startOfDay(firstEntryDate);
|
|
277
272
|
break;
|
|
278
273
|
}
|
|
279
274
|
case 'week': {
|
|
280
|
-
formattedDate =
|
|
275
|
+
formattedDate = startOfWeek(firstEntryDate, { weekStartsOn: 1 });
|
|
281
276
|
break;
|
|
282
277
|
}
|
|
283
278
|
case 'month': {
|
|
284
|
-
formattedDate =
|
|
279
|
+
formattedDate = startOfMonth(firstEntryDate);
|
|
285
280
|
break;
|
|
286
281
|
}
|
|
287
282
|
case 'year': {
|
|
288
|
-
formattedDate =
|
|
283
|
+
formattedDate = startOfYear(firstEntryDate);
|
|
289
284
|
break;
|
|
290
285
|
}
|
|
291
286
|
default:
|
|
@@ -298,27 +293,27 @@ function aggregate(dashboardItem, bucketFields, dateFilter) {
|
|
|
298
293
|
dashboardItem.yAxisFields.forEach(yAxisField => {
|
|
299
294
|
aggregation[iteratedDate][yAxisField.field] = 0;
|
|
300
295
|
});
|
|
301
|
-
iteratedDate =
|
|
296
|
+
iteratedDate = add(iteratedDate, interval);
|
|
302
297
|
}
|
|
303
298
|
// TODO MAKE WORK WITH MULTIPLE Y AXIS FIELDS
|
|
304
299
|
rows.forEach(row => {
|
|
305
|
-
const date =
|
|
300
|
+
const date = parse(row[dateField], 'yyyy-MM-dd', new Date());
|
|
306
301
|
let formattedDate;
|
|
307
302
|
switch (timePeriod) {
|
|
308
303
|
case 'day': {
|
|
309
|
-
formattedDate =
|
|
304
|
+
formattedDate = startOfDay(date);
|
|
310
305
|
break;
|
|
311
306
|
}
|
|
312
307
|
case 'week': {
|
|
313
|
-
formattedDate =
|
|
308
|
+
formattedDate = startOfWeek(date, { weekStartsOn: 1 });
|
|
314
309
|
break;
|
|
315
310
|
}
|
|
316
311
|
case 'month': {
|
|
317
|
-
formattedDate =
|
|
312
|
+
formattedDate = startOfMonth(date);
|
|
318
313
|
break;
|
|
319
314
|
}
|
|
320
315
|
case 'year': {
|
|
321
|
-
formattedDate =
|
|
316
|
+
formattedDate = startOfYear(date);
|
|
322
317
|
break;
|
|
323
318
|
}
|
|
324
319
|
default:
|
|
@@ -348,35 +343,35 @@ function aggregate(dashboardItem, bucketFields, dateFilter) {
|
|
|
348
343
|
dateFilter.comparison &&
|
|
349
344
|
dateFilter.comparisonRange.value !== 'NO_COMPARISON' &&
|
|
350
345
|
dashboardItem.compareRows) {
|
|
351
|
-
const offset =
|
|
346
|
+
const offset = COMPARISON_OPTIONS.find(option => {
|
|
352
347
|
return option.value === dateFilter.comparisonRange.value;
|
|
353
348
|
})?.offset;
|
|
354
349
|
aggregatedArray.forEach(row => {
|
|
355
350
|
dashboardItem.yAxisFields.forEach(yAxisField => {
|
|
356
351
|
row[yAxisField.field + '2'] = 0;
|
|
357
352
|
});
|
|
358
|
-
row[xAxisField + '2'] =
|
|
353
|
+
row[xAxisField + '2'] = sub(new Date(row[timePeriod]), offset).toISOString();
|
|
359
354
|
});
|
|
360
355
|
compareRows.sort((a, b) => new Date(a[dateField]) - new Date(b[dateField]));
|
|
361
356
|
compareRows.forEach((row, index) => {
|
|
362
|
-
let date =
|
|
363
|
-
date =
|
|
357
|
+
let date = parse(row[dateField], 'yyyy-MM-dd', new Date());
|
|
358
|
+
date = add(date, offset);
|
|
364
359
|
let formattedDate;
|
|
365
360
|
switch (timePeriod) {
|
|
366
361
|
case 'day': {
|
|
367
|
-
formattedDate =
|
|
362
|
+
formattedDate = startOfDay(date);
|
|
368
363
|
break;
|
|
369
364
|
}
|
|
370
365
|
case 'week': {
|
|
371
|
-
formattedDate =
|
|
366
|
+
formattedDate = startOfWeek(date, { weekStartsOn: 1 });
|
|
372
367
|
break;
|
|
373
368
|
}
|
|
374
369
|
case 'month': {
|
|
375
|
-
formattedDate =
|
|
370
|
+
formattedDate = startOfMonth(date);
|
|
376
371
|
break;
|
|
377
372
|
}
|
|
378
373
|
case 'year': {
|
|
379
|
-
formattedDate =
|
|
374
|
+
formattedDate = startOfYear(date);
|
|
380
375
|
break;
|
|
381
376
|
}
|
|
382
377
|
default:
|
|
@@ -426,5 +421,3 @@ function aggregate(dashboardItem, bucketFields, dateFilter) {
|
|
|
426
421
|
return dashboardItem;
|
|
427
422
|
}
|
|
428
423
|
}
|
|
429
|
-
exports.aggregate = aggregate;
|
|
430
|
-
//# sourceMappingURL=aggregate.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type Field = {
|
|
2
|
+
_id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
field: string;
|
|
5
|
+
format: 'percent';
|
|
6
|
+
};
|
|
7
|
+
type Props = {
|
|
8
|
+
value: string | number | boolean | undefined | null;
|
|
9
|
+
field: string | undefined | null;
|
|
10
|
+
fields: Field[];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Pretty-prints the given values to their nice-looking string form.
|
|
14
|
+
*
|
|
15
|
+
* The axis formatter will print a shorter version of the valueFormatter, which
|
|
16
|
+
* fits nicely along the X or Y axes.
|
|
17
|
+
*/
|
|
18
|
+
export declare const axisFormatter: ({ value, field, fields, }: Props) => string | number | boolean;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=axisFormatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"axisFormatter.d.ts","sourceRoot":"","sources":["../../src/utils/axisFormatter.ts"],"names":[],"mappings":"AAGA,KAAK,KAAK,GAAG;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IACpD,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,8BAIvB,KAAK,KAAG,MAAM,GAAG,MAAM,GAAG,OA+B5B,CAAC"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { endOfWeek, format, getWeek, isValid, startOfWeek } from 'date-fns';
|
|
2
|
+
import { utcToZonedTime } from 'date-fns-tz';
|
|
3
|
+
/**
|
|
4
|
+
* Pretty-prints the given values to their nice-looking string form.
|
|
5
|
+
*
|
|
6
|
+
* The axis formatter will print a shorter version of the valueFormatter, which
|
|
7
|
+
* fits nicely along the X or Y axes.
|
|
8
|
+
*/
|
|
9
|
+
export const axisFormatter = ({ value, field, fields, }) => {
|
|
10
|
+
if (field === undefined || field === null)
|
|
11
|
+
return '';
|
|
12
|
+
if (value === undefined || value === null)
|
|
13
|
+
return '';
|
|
14
|
+
const fieldInfo = fields.find((f) => f.field === field);
|
|
15
|
+
if (!fieldInfo)
|
|
16
|
+
return '';
|
|
17
|
+
const HANDLERS = {
|
|
18
|
+
percent: formatPercent,
|
|
19
|
+
dollar_amount: formatDollarAmount,
|
|
20
|
+
dollar_cents: formatDollarCents,
|
|
21
|
+
whole_number: formatWholeNumber,
|
|
22
|
+
one_decimal_place: formatOneDecimalPlace,
|
|
23
|
+
two_decimal_places: formatTwoDecimalPlaces,
|
|
24
|
+
string: formatString,
|
|
25
|
+
yyyy: format_YYYY,
|
|
26
|
+
MMM_yyyy: format_MMM_yyyy,
|
|
27
|
+
MMM_dd_yyyy: format_MMM_dd_yyyy,
|
|
28
|
+
hh_ap_pm: format_hh_ap_pm,
|
|
29
|
+
'MMM_dd-MMM_dd': format_MMM_dd_MMM_dd,
|
|
30
|
+
'MMM_dd_hh:mm_ap_pm': format_MMM_dd_hh_mm_ap_pm,
|
|
31
|
+
'wo, yyyy': format_wo_yyyy,
|
|
32
|
+
};
|
|
33
|
+
// try to handle this value using the associated formatType handler
|
|
34
|
+
const formatType = fieldInfo.format;
|
|
35
|
+
if (Object.keys(HANDLERS).includes(formatType)) {
|
|
36
|
+
return HANDLERS[formatType](value);
|
|
37
|
+
}
|
|
38
|
+
return value.toString(); // by default make this value a string
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* HELPER FUNCTION DEFINITIONS
|
|
42
|
+
**/
|
|
43
|
+
/**
|
|
44
|
+
* Formats the value as a string using the built-in converstion.
|
|
45
|
+
*/
|
|
46
|
+
const formatString = (value) => value.toString();
|
|
47
|
+
/**
|
|
48
|
+
* Formats the value as a (rounded) currency amount in dollars.
|
|
49
|
+
*
|
|
50
|
+
* eg. @example format(1234.567) => "$1.2K"
|
|
51
|
+
*/
|
|
52
|
+
const formatDollarAmount = (value) => {
|
|
53
|
+
const formatter = new Intl.NumberFormat('en-US', {
|
|
54
|
+
style: 'currency',
|
|
55
|
+
currency: 'USD',
|
|
56
|
+
minimumSignificantDigits: 2,
|
|
57
|
+
maximumSignificantDigits: 2,
|
|
58
|
+
notation: 'compact',
|
|
59
|
+
compactDisplay: 'short',
|
|
60
|
+
});
|
|
61
|
+
return formatter.format(Number(value ?? 0));
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Formats the value as a (rounded) currency amount in dollars and cents.
|
|
65
|
+
*
|
|
66
|
+
* @example format(1234.567) => "$1.2K"
|
|
67
|
+
*/
|
|
68
|
+
const formatDollarCents = (value) => {
|
|
69
|
+
const formatter = new Intl.NumberFormat('en-US', {
|
|
70
|
+
style: 'currency',
|
|
71
|
+
currency: 'USD',
|
|
72
|
+
minimumSignificantDigits: 2,
|
|
73
|
+
maximumSignificantDigits: 2,
|
|
74
|
+
notation: 'compact',
|
|
75
|
+
compactDisplay: 'short',
|
|
76
|
+
});
|
|
77
|
+
return formatter.format(Number(value ?? 0));
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Formats the value as a (rounded) integer.
|
|
81
|
+
*
|
|
82
|
+
* @example format(1234.567) => "1.2K"
|
|
83
|
+
*/
|
|
84
|
+
const formatWholeNumber = (value) => {
|
|
85
|
+
const formatter = new Intl.NumberFormat('en-US', {
|
|
86
|
+
minimumSignificantDigits: 2,
|
|
87
|
+
maximumSignificantDigits: 2,
|
|
88
|
+
notation: 'compact',
|
|
89
|
+
compactDisplay: 'short',
|
|
90
|
+
});
|
|
91
|
+
return formatter.format(Number(value));
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Formats the value as a number rounded to exactly one decimal place.
|
|
95
|
+
*
|
|
96
|
+
* @example format(1234.567) => "1.2K"
|
|
97
|
+
* @example format(123.456) => "1,234.6"
|
|
98
|
+
*/
|
|
99
|
+
const formatOneDecimalPlace = (value) => {
|
|
100
|
+
const formatter = new Intl.NumberFormat('en-US', {
|
|
101
|
+
minimumFractionDigits: 1,
|
|
102
|
+
maximumFractionDigits: 1,
|
|
103
|
+
notation: 'compact',
|
|
104
|
+
compactDisplay: 'short',
|
|
105
|
+
});
|
|
106
|
+
return formatter.format(Number(value));
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Formats the value as a number rounded to exactly two decimal places.
|
|
110
|
+
*
|
|
111
|
+
* @example format(1234.567) => "1.23K"
|
|
112
|
+
* @example format(123.456) => "123.46"
|
|
113
|
+
*/
|
|
114
|
+
const formatTwoDecimalPlaces = (value) => {
|
|
115
|
+
const formatter = new Intl.NumberFormat('en-US', {
|
|
116
|
+
minimumFractionDigits: 2,
|
|
117
|
+
maximumFractionDigits: 2,
|
|
118
|
+
notation: 'compact',
|
|
119
|
+
compactDisplay: 'short',
|
|
120
|
+
});
|
|
121
|
+
return formatter.format(Number(value));
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Formats the value as a percentage.
|
|
125
|
+
*
|
|
126
|
+
* @example format(0.1234) => "12%"
|
|
127
|
+
* @example format(0.99) => "99%"
|
|
128
|
+
*
|
|
129
|
+
* NOTE: This function expects that the value is already a percentage value, and
|
|
130
|
+
* does not try to guess whether the percentage is represented as a whole number
|
|
131
|
+
* or a decimal.
|
|
132
|
+
*
|
|
133
|
+
* @example format(1234.567) => "120K%"
|
|
134
|
+
* @example format(99) => "9.9K%"
|
|
135
|
+
*/
|
|
136
|
+
const formatPercent = (value) => {
|
|
137
|
+
const formatter = new Intl.NumberFormat('en-US', {
|
|
138
|
+
style: 'percent',
|
|
139
|
+
minimumSignificantDigits: 2,
|
|
140
|
+
maximumSignificantDigits: 2,
|
|
141
|
+
notation: 'compact',
|
|
142
|
+
compactDisplay: 'short',
|
|
143
|
+
});
|
|
144
|
+
return formatter.format(Number(value));
|
|
145
|
+
};
|
|
146
|
+
// Converts the value to a UTC date with the given format string. If the
|
|
147
|
+
// resulting date is invalid, it returns "Invalid date".
|
|
148
|
+
const _getUTCDateHelper = (value, fmt) => {
|
|
149
|
+
const utcDate = utcToZonedTime(new Date(value), 'UTC');
|
|
150
|
+
if (!isValid(utcDate))
|
|
151
|
+
return 'Invalid date';
|
|
152
|
+
return format(utcDate, fmt);
|
|
153
|
+
};
|
|
154
|
+
const format_YYYY = (value) => _getUTCDateHelper(value, 'yyyy');
|
|
155
|
+
const format_MMM_yyyy = (value) => _getUTCDateHelper(value, 'MMM yyyy');
|
|
156
|
+
const format_hh_ap_pm = (value) => _getUTCDateHelper(value, 'hh:mm aa');
|
|
157
|
+
const format_MMM_dd_yyyy = (value) => _getUTCDateHelper(value, 'dd MMM yyyy');
|
|
158
|
+
const format_MMM_dd_MMM_dd = (value) => {
|
|
159
|
+
const utcDate = utcToZonedTime(new Date(value), 'UTC');
|
|
160
|
+
if (!isValid(utcDate))
|
|
161
|
+
return 'Invalid date';
|
|
162
|
+
const monday = startOfWeek(utcDate, { weekStartsOn: 1 });
|
|
163
|
+
const sunday = endOfWeek(utcDate, { weekStartsOn: 1 });
|
|
164
|
+
// Check if start and end are in the same month
|
|
165
|
+
if (format(monday, 'MMM') === format(sunday, 'MMM')) {
|
|
166
|
+
return `${format(monday, 'MMM dd')} - ${format(sunday, 'dd')}`;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
return `${format(monday, 'MMM dd')} - ${format(sunday, 'MMM dd')}`;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
const format_MMM_dd_hh_mm_ap_pm = (value) => {
|
|
173
|
+
const utcDate = utcToZonedTime(new Date(value), 'UTC');
|
|
174
|
+
if (!isValid(utcDate))
|
|
175
|
+
return 'Invalid date';
|
|
176
|
+
const formatStr = utcDate.getMinutes() === 0 ? 'MMM do h a' : 'MMM do h:mm a';
|
|
177
|
+
const res = format(utcDate, formatStr);
|
|
178
|
+
return res.slice(0, -2) + res.slice(-2).toLowerCase();
|
|
179
|
+
};
|
|
180
|
+
const format_wo_yyyy = (value) => {
|
|
181
|
+
const utcDate = utcToZonedTime(new Date(value), 'UTC');
|
|
182
|
+
if (!isValid(utcDate))
|
|
183
|
+
return 'Invalid date';
|
|
184
|
+
return `${getWeek(utcDate)},${utcDate.getFullYear()}`;
|
|
185
|
+
};
|
package/dist/utils/colorToHex.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.COLOR_TO_HEX = void 0;
|
|
4
|
-
exports.COLOR_TO_HEX = {
|
|
1
|
+
export const COLOR_TO_HEX = {
|
|
5
2
|
aliceblue: '#f0f8ff',
|
|
6
3
|
antiquewhite: '#faebd7',
|
|
7
4
|
aqua: '#00ffff',
|
|
@@ -144,4 +141,3 @@ exports.COLOR_TO_HEX = {
|
|
|
144
141
|
yellow: '#ffff00',
|
|
145
142
|
yellowgreen: '#9acd32',
|
|
146
143
|
};
|
|
147
|
-
//# sourceMappingURL=colorToHex.js.map
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDataFromCloud = exports.getData = void 0;
|
|
4
1
|
// this function gets the data either from the self hosted endpoint or
|
|
5
2
|
// our cloud server
|
|
6
|
-
async function getData(client, cloudQueryEndpoint, noCred, hostedRequestBody, cloudRequestBody, method = 'POST') {
|
|
3
|
+
export async function getData(client, cloudQueryEndpoint, noCred, hostedRequestBody, cloudRequestBody, method = 'POST') {
|
|
7
4
|
if (client.queryEndpoint) {
|
|
8
5
|
// self hosted
|
|
9
6
|
const resp = await fetch(client.queryEndpoint, {
|
|
@@ -29,8 +26,7 @@ async function getData(client, cloudQueryEndpoint, noCred, hostedRequestBody, cl
|
|
|
29
26
|
return await getDataFromCloud(client, cloudQueryEndpoint, cloudRequestBody, method);
|
|
30
27
|
}
|
|
31
28
|
}
|
|
32
|
-
|
|
33
|
-
async function getDataFromCloud(client, cloudQueryEndpoint, cloudRequestBody, method = 'POST') {
|
|
29
|
+
export async function getDataFromCloud(client, cloudQueryEndpoint, cloudRequestBody, method = 'POST') {
|
|
34
30
|
const environment = client?.environment;
|
|
35
31
|
const resp = await fetch(`https://quill-344421.uc.r.appspot.com/${cloudQueryEndpoint}`,
|
|
36
32
|
// `http://localhost:8080/${cloudQueryEndpoint}`,
|
|
@@ -60,5 +56,3 @@ async function getDataFromCloud(client, cloudQueryEndpoint, cloudRequestBody, me
|
|
|
60
56
|
return null;
|
|
61
57
|
}
|
|
62
58
|
}
|
|
63
|
-
exports.getDataFromCloud = getDataFromCloud;
|
|
64
|
-
//# sourceMappingURL=dataFetcher.js.map
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.downloadCSV = void 0;
|
|
4
1
|
// @ts-nocheck
|
|
5
|
-
function downloadCSV(rows, filename) {
|
|
2
|
+
export function downloadCSV(rows, filename) {
|
|
6
3
|
const json = rows;
|
|
7
4
|
const fields = Object.keys(json[0]);
|
|
8
5
|
const csvRows = [];
|
|
@@ -25,5 +22,3 @@ function downloadCSV(rows, filename) {
|
|
|
25
22
|
downloadLink.click();
|
|
26
23
|
document.body.removeChild(downloadLink);
|
|
27
24
|
}
|
|
28
|
-
exports.downloadCSV = downloadCSV;
|
|
29
|
-
//# sourceMappingURL=downloadCSV.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface TableInfo {
|
|
2
|
+
displayName: string;
|
|
3
|
+
columns: {
|
|
4
|
+
name: string;
|
|
5
|
+
label: string;
|
|
6
|
+
fieldType: string;
|
|
7
|
+
}[];
|
|
8
|
+
}
|
|
9
|
+
export interface ColumnSelectorInfo {
|
|
10
|
+
name: string;
|
|
11
|
+
selected: boolean;
|
|
12
|
+
presentTables: string[];
|
|
13
|
+
selectable: boolean;
|
|
14
|
+
tableName: string;
|
|
15
|
+
displayName: string;
|
|
16
|
+
textFiltered: boolean;
|
|
17
|
+
fieldType: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function formatColumnData(tableInfo: TableInfo[], selectedTable: any, customerFieldName: string): ColumnSelectorInfo[];
|
|
20
|
+
export declare function columnGrouping(tableInfo: TableInfo[]): any[];
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"AAGA,UAAU,SAAS;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/D;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,SAAS,EAAE,EACtB,aAAa,EAAE,GAAG,EAClB,iBAAiB,EAAE,MAAM,GACxB,kBAAkB,EAAE,CA0CtB;AAGD,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,GAAG,EAAE,CAmG5D"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { deSnakeOrCamelCase, singularize } from './textFormatting';
|
|
2
|
+
export function formatColumnData(tableInfo, selectedTable, customerFieldName) {
|
|
3
|
+
const initialState = [];
|
|
4
|
+
const formattedData = tableInfo.reduce((allColumnDetails, table) => {
|
|
5
|
+
let setSelected = false;
|
|
6
|
+
if (selectedTable.displayName === table.displayName) {
|
|
7
|
+
setSelected = true;
|
|
8
|
+
}
|
|
9
|
+
table.columns.forEach((column) => {
|
|
10
|
+
if (column.name === customerFieldName) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
let formattedDisplayName = '';
|
|
14
|
+
console.log(column.name);
|
|
15
|
+
if (column.name.endsWith('_id')) {
|
|
16
|
+
formattedDisplayName = singularize(deSnakeOrCamelCase(column.name));
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
formattedDisplayName =
|
|
20
|
+
singularize(deSnakeOrCamelCase(table.displayName)) +
|
|
21
|
+
' ' +
|
|
22
|
+
deSnakeOrCamelCase(column.name);
|
|
23
|
+
}
|
|
24
|
+
const presentColumn = allColumnDetails.find((columnDetail) => columnDetail.displayName === formattedDisplayName);
|
|
25
|
+
if (presentColumn) {
|
|
26
|
+
presentColumn.presentTables.push(table.displayName);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
allColumnDetails.push({
|
|
30
|
+
name: column.name,
|
|
31
|
+
selected: setSelected,
|
|
32
|
+
presentTables: [table.displayName],
|
|
33
|
+
selectable: setSelected,
|
|
34
|
+
tableName: table.displayName,
|
|
35
|
+
displayName: formattedDisplayName,
|
|
36
|
+
textFiltered: true,
|
|
37
|
+
fieldType: column.fieldType,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return allColumnDetails;
|
|
42
|
+
}, initialState);
|
|
43
|
+
return formattedData;
|
|
44
|
+
}
|
|
45
|
+
// THIS FUNCTION IS A CURRENTLY NOT IN USE BUT IS A STRONG EXAMPLE OF AUTOMATED JOINS
|
|
46
|
+
export function columnGrouping(tableInfo) {
|
|
47
|
+
const tableMap = {};
|
|
48
|
+
tableInfo.forEach((table) => {
|
|
49
|
+
tableMap[table.displayName] = [];
|
|
50
|
+
});
|
|
51
|
+
tableInfo.forEach((table) => {
|
|
52
|
+
tableMap[table.displayName]?.push(table.displayName);
|
|
53
|
+
table.columns.forEach((column) => {
|
|
54
|
+
if (column.name.endsWith('_id')) {
|
|
55
|
+
const otherTable = column.name.replace('_id', '') + 's';
|
|
56
|
+
const possibleTable = column.name.replace('_id', '');
|
|
57
|
+
if (tableMap[table.displayName]) {
|
|
58
|
+
tableMap[table.displayName]?.push(otherTable);
|
|
59
|
+
tableMap[table.displayName]?.push(possibleTable);
|
|
60
|
+
tableMap[otherTable]?.push(table.displayName);
|
|
61
|
+
tableMap[possibleTable]?.push(table.displayName);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
function dfs(tableName, visited, group) {
|
|
67
|
+
group.push(tableName);
|
|
68
|
+
visited[tableName] = true;
|
|
69
|
+
tableMap[tableName]?.forEach((table) => {
|
|
70
|
+
if (!visited[table]) {
|
|
71
|
+
dfs(table, visited, group);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// perform a depth first search to create a grouping of tables that can be selected all together
|
|
76
|
+
const visited = {};
|
|
77
|
+
const groups = [];
|
|
78
|
+
const tableNames = Object.keys(tableMap);
|
|
79
|
+
let i = 0;
|
|
80
|
+
tableNames.forEach((table) => {
|
|
81
|
+
if (!visited[table]) {
|
|
82
|
+
groups.push([]);
|
|
83
|
+
dfs(table, visited, groups[i]);
|
|
84
|
+
i++;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const formattedGroups = groups.map((tableGroup) => {
|
|
88
|
+
// loop through all the columns in each table and add them to columnsFormatted
|
|
89
|
+
// if the coulmn name isn't a foreign key then format the name to be more readable. example User.id -> User Id
|
|
90
|
+
// if the column is a foreign key then format the name to be like the following. example user_id -> User Id
|
|
91
|
+
const formattedColumns = tableGroup.map((table) => {
|
|
92
|
+
const curTableInfo = tableInfo.find((tableInfo) => tableInfo.displayName === table);
|
|
93
|
+
if (curTableInfo) {
|
|
94
|
+
const columns = curTableInfo.columns.map((column) => {
|
|
95
|
+
if (column.name.endsWith('_id')) {
|
|
96
|
+
return {
|
|
97
|
+
displayName: singularize(deSnakeOrCamelCase(column.name)),
|
|
98
|
+
tableName: curTableInfo.displayName,
|
|
99
|
+
name: column.name,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
displayName: singularize(deSnakeOrCamelCase(table)) +
|
|
104
|
+
' ' +
|
|
105
|
+
deSnakeOrCamelCase(column.name),
|
|
106
|
+
tableName: curTableInfo.displayName,
|
|
107
|
+
name: column.name,
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
return columns;
|
|
111
|
+
}
|
|
112
|
+
return [];
|
|
113
|
+
});
|
|
114
|
+
// if there are multiple objects with the same name then flatten the array and remove duplicates by name
|
|
115
|
+
const formattedColumnsFlat = formattedColumns.flat().filter((column, i) => {
|
|
116
|
+
return (formattedColumns
|
|
117
|
+
.flat()
|
|
118
|
+
.findIndex((c) => c.displayName === column.displayName) === i);
|
|
119
|
+
});
|
|
120
|
+
const formattedColumnsFlatNames = formattedColumnsFlat.map((column) => {
|
|
121
|
+
return {
|
|
122
|
+
displayName: column.displayName,
|
|
123
|
+
selected: false,
|
|
124
|
+
group: tableGroup.join('_'),
|
|
125
|
+
selectable: true,
|
|
126
|
+
tableName: column.tableName,
|
|
127
|
+
name: column.name,
|
|
128
|
+
textFiltered: true,
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
return formattedColumnsFlatNames;
|
|
132
|
+
});
|
|
133
|
+
return formattedGroups.flat();
|
|
134
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textFormatting.d.ts","sourceRoot":"","sources":["../../src/utils/textFormatting.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAGD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO/C;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAsBxD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function capitalize(str) {
|
|
2
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
3
|
+
}
|
|
4
|
+
// create a function that removes pluralization
|
|
5
|
+
export function singularize(str) {
|
|
6
|
+
if (str.endsWith('ies')) {
|
|
7
|
+
return str.slice(0, str.length - 3) + 'y';
|
|
8
|
+
}
|
|
9
|
+
else if (str.endsWith('s')) {
|
|
10
|
+
return str.slice(0, str.length - 1);
|
|
11
|
+
}
|
|
12
|
+
return str;
|
|
13
|
+
}
|
|
14
|
+
export function deSnakeOrCamelCase(value) {
|
|
15
|
+
if (value.toLowerCase() === 'id') {
|
|
16
|
+
return 'ID';
|
|
17
|
+
}
|
|
18
|
+
let splitVals = [];
|
|
19
|
+
if (/_/.test(value)) {
|
|
20
|
+
splitVals = value.split('_');
|
|
21
|
+
}
|
|
22
|
+
else if (/[a-z][A-Z]/.test(value)) {
|
|
23
|
+
splitVals = value.split(/(?=[A-Z])/);
|
|
24
|
+
}
|
|
25
|
+
if (splitVals.length > 0) {
|
|
26
|
+
splitVals.forEach((val, index) => {
|
|
27
|
+
console.log(val);
|
|
28
|
+
if (val.toLowerCase() === 'id') {
|
|
29
|
+
splitVals[index] = 'ID';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
splitVals[index] = capitalize(val);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return splitVals.join(' ');
|
|
36
|
+
}
|
|
37
|
+
return capitalize(value);
|
|
38
|
+
}
|