@quillsql/react 2.6.2 → 2.6.3

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.
Files changed (56) hide show
  1. package/lib/AddToDashboardModal.js +136 -243
  2. package/lib/AddToDashboardModal.js.map +1 -1
  3. package/lib/Chart.js +106 -139
  4. package/lib/Chart.js.map +1 -1
  5. package/lib/ChartBuilder.d.ts +36 -0
  6. package/lib/ChartBuilder.js +612 -0
  7. package/lib/ChartBuilder.js.map +1 -0
  8. package/lib/ChartEditor.d.ts +20 -0
  9. package/lib/ChartEditor.js +75 -0
  10. package/lib/ChartEditor.js.map +1 -0
  11. package/lib/Dashboard.d.ts +1 -0
  12. package/lib/Dashboard.js +37 -66
  13. package/lib/Dashboard.js.map +1 -1
  14. package/lib/DateRangePicker/dateRangePickerUtils.d.ts +1 -0
  15. package/lib/DateRangePicker/dateRangePickerUtils.js +6 -1
  16. package/lib/DateRangePicker/dateRangePickerUtils.js.map +1 -1
  17. package/lib/QuillProvider.d.ts +1 -0
  18. package/lib/QuillProvider.js +1 -0
  19. package/lib/QuillProvider.js.map +1 -1
  20. package/lib/ReportBuilder.d.ts +24 -34
  21. package/lib/ReportBuilder.js +248 -893
  22. package/lib/ReportBuilder.js.map +1 -1
  23. package/lib/SQLEditor.d.ts +5 -1
  24. package/lib/SQLEditor.js +91 -163
  25. package/lib/SQLEditor.js.map +1 -1
  26. package/lib/Table.js +56 -108
  27. package/lib/Table.js.map +1 -1
  28. package/lib/assets/XIcon.d.ts +4 -0
  29. package/lib/assets/XIcon.js +6 -0
  30. package/lib/assets/XIcon.js.map +1 -0
  31. package/lib/assets/index.d.ts +4 -0
  32. package/lib/assets/index.js +9 -1
  33. package/lib/assets/index.js.map +1 -1
  34. package/lib/components/QuillCard.d.ts +5 -2
  35. package/lib/components/QuillCard.js +43 -5
  36. package/lib/components/QuillCard.js.map +1 -1
  37. package/lib/components/UiComponents.d.ts +112 -0
  38. package/lib/components/UiComponents.js +255 -0
  39. package/lib/components/UiComponents.js.map +1 -0
  40. package/lib/hooks/useQuill.d.ts +1 -0
  41. package/lib/hooks/useQuill.js +15 -59
  42. package/lib/hooks/useQuill.js.map +1 -1
  43. package/lib/index.d.ts +2 -0
  44. package/lib/index.js +5 -1
  45. package/lib/index.js.map +1 -1
  46. package/lib/internals/ReportBuilder/PivotList.d.ts +27 -3
  47. package/lib/internals/ReportBuilder/PivotList.js +49 -39
  48. package/lib/internals/ReportBuilder/PivotList.js.map +1 -1
  49. package/lib/internals/ReportBuilder/PivotModal.d.ts +33 -3
  50. package/lib/internals/ReportBuilder/PivotModal.js +318 -226
  51. package/lib/internals/ReportBuilder/PivotModal.js.map +1 -1
  52. package/lib/internals/ReportBuilder/PivotModal.spec.js +19 -0
  53. package/lib/internals/ReportBuilder/PivotModal.spec.js.map +1 -1
  54. package/lib/utils/aggregate.js +1 -0
  55. package/lib/utils/aggregate.js.map +1 -1
  56. package/package.json +6 -3
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generatePivotTable = exports.PivotModal = void 0;
3
+ exports.generatePivotTable = exports.isDateField = exports.generatePivotTableYAxis = exports.PivotModal = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  // @ts-nocheck
6
6
  const react_1 = require("react");
@@ -10,6 +10,8 @@ const assets_1 = require("../../assets");
10
10
  const PivotList_1 = require("./PivotList");
11
11
  const date_fns_1 = require("date-fns");
12
12
  const Chart_1 = require("../../Chart");
13
+ const ChartBuilder_1 = require("../../ChartBuilder");
14
+ const QuillCard_1 = require("../../components/QuillCard");
13
15
  const QuillHover = () => {
14
16
  return ((0, jsx_runtime_1.jsx)("style", { children: `
15
17
  .quill-hover {
@@ -23,12 +25,8 @@ const QuillHover = () => {
23
25
  }
24
26
  ` }));
25
27
  };
26
- const PivotModal = ({ selectedTable, SelectComponent, ButtonComponent, ModalComponent, ModalTriggerComponent, selectedPivotIndex, setSelectedPivotIndex, removePivot, selectPivot, data, columns, theme, dateRange, }) => {
27
- const [isOpen, setIsOpen] = (0, react_1.useState)(false);
28
- const [showUpdatePivot, setShowUpdatePivot] = (0, react_1.useState)(false);
29
- const [isLoading, setIsLoading] = (0, react_1.useState)(true);
30
- const [recommendedPivots, setRecommendedPivots] = (0, react_1.useState)([]);
31
- const [createdPivots, setCreatedPivots] = (0, react_1.useState)([]);
28
+ const PivotModal = ({ pivotRowField, setPivotRowField, pivotColumnField, setPivotColumnField, pivotValueField, setPivotValueField, pivotAggregation, setPivotAggregation, popUpTitle, setPopUpTitle, selectedTable, SelectComponent, ButtonComponent, PopoverComponent, HeaderComponent, LabelComponent, TextComponent, selectedPivotIndex, setSelectedPivotIndex, removePivot, selectPivot, showUpdatePivot, setShowUpdatePivot, data, columns, theme, isOpen, setIsOpen, dateRange, createdPivots, setCreatedPivots, recommendedPivots, setRecommendedPivots, triggerButtonText = 'Pivot', showPivotEditButton = false, showEditOnPivotClick = true, selectPivotOnEdit = false, showTrigger = true, rightAlign = false, parentRef, }) => {
29
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
32
30
  // for testing
33
31
  // const [createdPivots, setCreatedPivots] = useState<Pivot[]>([
34
32
  // {
@@ -61,30 +59,84 @@ const PivotModal = ({ selectedTable, SelectComponent, ButtonComponent, ModalComp
61
59
  // ]);
62
60
  const [pivotUpdateIndex, setPivotUpdateIndex] = (0, react_1.useState)(null);
63
61
  const [selectedPivotType, setSelectedPivotType] = (0, react_1.useState)('recommended');
64
- const [pivotRowField, setPivotRowField] = (0, react_1.useState)(undefined);
65
- const [pivotColumnField, setPivotColumnField] = (0, react_1.useState)(undefined);
66
- const [pivotValueField, setPivotValueField] = (0, react_1.useState)(undefined);
67
- const [pivotAggregation, setPivotAggregation] = (0, react_1.useState)(undefined);
68
62
  const [errors, setErrors] = (0, react_1.useState)([]);
69
63
  const [client] = (0, react_1.useContext)(Context_1.ClientContext);
64
+ const [divWidth, setDivWidth] = (0, react_1.useState)(0);
65
+ const editModalRef = (0, react_1.useRef)();
66
+ const calculateWidth = () => {
67
+ return editModalRef.current.offsetWidth;
68
+ };
69
+ (0, react_1.useEffect)(() => {
70
+ // Measure the width of the div and update state
71
+ if (editModalRef.current) {
72
+ setDivWidth(calculateWidth());
73
+ }
74
+ // Optional: Handle window resize
75
+ const handleResize = () => {
76
+ if (editModalRef.current) {
77
+ setDivWidth(calculateWidth());
78
+ }
79
+ };
80
+ window.addEventListener('resize', handleResize);
81
+ // Cleanup listener
82
+ return () => {
83
+ window.removeEventListener('resize', handleResize);
84
+ };
85
+ }, []);
86
+ (0, react_1.useEffect)(() => {
87
+ // Measure the width of the div and update state
88
+ if (editModalRef.current) {
89
+ setDivWidth(calculateWidth());
90
+ }
91
+ }, [editModalRef.current, showUpdatePivot]);
92
+ (0, react_1.useEffect)(() => {
93
+ setSelectedPivotIndex(-1);
94
+ setPivotUpdateIndex(null);
95
+ setSelectedPivotType(undefined);
96
+ setPivotRowField(undefined);
97
+ setPivotColumnField(undefined);
98
+ setPivotValueField(undefined);
99
+ setPivotAggregation(undefined);
100
+ setIsOpen(false);
101
+ setErrors([]);
102
+ }, [selectedTable]);
70
103
  const columnsToShow = (0, react_1.useMemo)(() => {
71
- return selectedTable.columns.reduce(function (map, col) {
104
+ return (selectedTable?.columns || []).reduce((map, col) => {
72
105
  // only use columns shown in the report builder's table
73
- if (columns.find(column => column.field === col.name)) {
106
+ // also filter out id
107
+ if (col.name !== 'id' &&
108
+ !col.name.endsWith('_id') &&
109
+ columns.find(column => column.field === col.name)) {
74
110
  map[col.name] = col.fieldType;
75
111
  }
76
112
  return map;
77
113
  }, {});
78
114
  }, [selectedTable, columns]);
115
+ const selectedPivotTable = (0, react_1.useMemo)(() => {
116
+ if (selectedPivotIndex === -1) {
117
+ return null;
118
+ }
119
+ const pivot = createdPivots[selectedPivotIndex];
120
+ const { rows, columns } = generatePivotTable(pivot, data, dateRange);
121
+ return {
122
+ pivot: pivot,
123
+ rows: rows,
124
+ columns: columns,
125
+ };
126
+ }, [selectedPivotIndex, data, dateRange, createdPivots]);
79
127
  const columnSelectOptions = (0, react_1.useMemo)(() => {
80
128
  return [
81
- { label: '', value: null },
129
+ { label: 'Select', value: '' },
82
130
  ...Object.keys(columnsToShow).map(key => {
83
131
  return { label: key, value: key };
84
132
  }),
85
133
  ];
86
134
  }, [columnsToShow]);
87
135
  const onSelectRecommendedPivot = (pivot, index) => {
136
+ if (showEditOnPivotClick) {
137
+ onEditPivot(pivot, index);
138
+ return;
139
+ }
88
140
  if (index === selectedPivotIndex && selectedPivotType === 'recommended') {
89
141
  removePivot();
90
142
  }
@@ -95,16 +147,10 @@ const PivotModal = ({ selectedTable, SelectComponent, ButtonComponent, ModalComp
95
147
  setIsOpen(false);
96
148
  };
97
149
  const onSelectCreatedPivot = (pivot, index) => {
98
- if (index === selectedPivotIndex &&
99
- selectedPivotType === 'created' &&
100
- pivotUpdateIndex === null) {
101
- removePivot();
102
- }
103
- else {
104
- selectPivot(pivot, index);
105
- setSelectedPivotType('created');
106
- }
150
+ selectPivot(pivot, index);
151
+ setSelectedPivotType('created');
107
152
  setIsOpen(false);
153
+ setPopUpTitle('Add Pivot');
108
154
  };
109
155
  const onEditPivot = (pivot, index) => {
110
156
  setPivotRowField(pivot.rowField);
@@ -118,22 +164,29 @@ const PivotModal = ({ selectedTable, SelectComponent, ButtonComponent, ModalComp
118
164
  onEditPivot(pivot, null);
119
165
  };
120
166
  const refreshPivots = (0, react_1.useCallback)(async () => {
167
+ if (isLoading || Object.keys(columnsToShow).length === 0) {
168
+ return;
169
+ }
121
170
  setIsLoading(true);
122
171
  const cloudBody = {
123
172
  tableSchema: Object.keys(columnsToShow).reduce(function (map, col) {
124
- map[col] = columnsToShow[col];
173
+ // stop ai from seeing date fields. this is meant to stop the ai
174
+ // pivot tables from extracting month and year from the date
175
+ const fieldType = isDateField(columnsToShow[col])
176
+ ? 'string'
177
+ : columnsToShow[col];
178
+ map[col] = fieldType;
125
179
  return map;
126
180
  }, {}),
127
181
  };
128
182
  try {
129
183
  const resp = await (0, dataFetcher_1.getDataFromCloud)(client, 'pivotai', cloudBody);
130
- const recommendedPivots = JSON.parse(resp?.data?.choices?.[0]?.message?.content).pivotTables;
184
+ const recommendedPivots = resp?.data?.pivotTables || [];
131
185
  // for testing if needed
132
186
  // const recommendedPivots = [
133
187
  // {
134
- // title: 'Total Amount by Merchant and Category',
188
+ // title: 'Total Amount by Merchant',
135
189
  // rowField: 'merchant',
136
- // columnField: 'category',
137
190
  // valueField: 'amount',
138
191
  // aggregationType: 'sum',
139
192
  // },
@@ -152,16 +205,16 @@ const PivotModal = ({ selectedTable, SelectComponent, ButtonComponent, ModalComp
152
205
  // aggregationType: 'count',
153
206
  // },
154
207
  // {
155
- // title: 'Total Amount by Merchant and Customer',
208
+ // title: 'Total Amount by Merchant and Category',
156
209
  // rowField: 'merchant',
157
- // columnField: 'customer_id',
210
+ // columnField: 'category',
158
211
  // valueField: 'amount',
159
212
  // aggregationType: 'sum',
160
213
  // },
161
214
  // {
162
- // title: 'Average Amount by Date and Category',
163
- // rowField: 'created_at',
164
- // columnField: 'category',
215
+ // title: 'Average Amount by Category and Date',
216
+ // rowField: 'category',
217
+ // columnField: 'created_at',
165
218
  // valueField: 'amount',
166
219
  // aggregationType: 'average',
167
220
  // },
@@ -173,7 +226,9 @@ const PivotModal = ({ selectedTable, SelectComponent, ButtonComponent, ModalComp
173
226
  // aggregationType: 'count',
174
227
  // },
175
228
  // ];
176
- setRecommendedPivots(recommendedPivots.map(pivot => {
229
+ setRecommendedPivots(recommendedPivots
230
+ .filter(pivot => pivot.rowField != '')
231
+ .map(pivot => {
177
232
  return {
178
233
  ...pivot,
179
234
  rowFieldType: columnsToShow[pivot.rowField],
@@ -187,7 +242,12 @@ const PivotModal = ({ selectedTable, SelectComponent, ButtonComponent, ModalComp
187
242
  console.error('Failed parsing pivotai response', e);
188
243
  }
189
244
  setIsLoading(false);
190
- }, [selectedTable, data, columnsToShow]);
245
+ }, [selectedTable, data, columnsToShow, isLoading]);
246
+ (0, react_1.useEffect)(() => {
247
+ if (recommendedPivots.length === 0) {
248
+ refreshPivots();
249
+ }
250
+ }, [refreshPivots]);
191
251
  const recommendedPivotTables = (0, react_1.useMemo)(() => {
192
252
  const pts = recommendedPivots.map(p => {
193
253
  const { rows, columns } = generatePivotTable(p, data, dateRange);
@@ -202,192 +262,217 @@ const PivotModal = ({ selectedTable, SelectComponent, ButtonComponent, ModalComp
202
262
  });
203
263
  return pts;
204
264
  }, [createdPivots, data]);
265
+ const samplePivotTable = (0, react_1.useMemo)(() => {
266
+ if (!pivotAggregation || !pivotRowField) {
267
+ return null;
268
+ }
269
+ const pivot = {
270
+ rowField: pivotRowField || '',
271
+ rowFieldType: columnsToShow[pivotRowField || ''],
272
+ columnField: pivotColumnField,
273
+ columnFieldType: columnsToShow[pivotColumnField || ''],
274
+ valueField: pivotValueField || '',
275
+ aggregationType: pivotAggregation || '',
276
+ };
277
+ const { rows, columns } = generatePivotTable(pivot, data, dateRange);
278
+ return { pivot: pivot, rows, columns };
279
+ }, [
280
+ pivotAggregation,
281
+ pivotValueField,
282
+ pivotRowField,
283
+ pivotColumnField,
284
+ columnsToShow,
285
+ ]);
205
286
  return ((0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', flexDirection: 'column' }, children: (0, jsx_runtime_1.jsxs)("div", { style: {
206
287
  position: 'relative',
207
288
  display: 'inline-block',
208
289
  textAlign: 'left',
209
- }, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
290
+ }, children: [(0, jsx_runtime_1.jsx)("div", { style: {
210
291
  display: 'flex',
211
292
  flexDirection: 'row',
212
293
  alignItems: 'center',
213
- }, children: [selectedPivotIndex !== -1 && ((0, jsx_runtime_1.jsx)("span", { style: {
214
- height: 10,
215
- width: 10,
216
- backgroundColor: theme.primaryButtonColor,
217
- borderRadius: '50%',
218
- position: 'absolute',
219
- top: -2,
220
- right: -2,
221
- } })), (0, jsx_runtime_1.jsx)(ModalTriggerComponent, { onClick: () => {
222
- // table is not loaded yet, so pivot button is not clickable
223
- if (Object.keys(columnsToShow).length === 0) {
224
- return;
225
- }
226
- if (!isOpen && recommendedPivots.length === 0) {
227
- refreshPivots();
228
- }
229
- setIsOpen(isOpen => !isOpen);
230
- setShowUpdatePivot(false);
231
- }, label: "Pivot", Icon: assets_1.UpLeftArrowsIcon })] }), (0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: isOpen, onClose: () => {
232
- setIsOpen(false);
294
+ }, children: selectedPivotIndex !== -1 && ((0, jsx_runtime_1.jsx)("span", { style: {
295
+ height: 10,
296
+ width: 10,
297
+ backgroundColor: theme.primaryButtonColor,
298
+ borderRadius: '50%',
299
+ position: 'absolute',
300
+ top: -2,
301
+ right: -2,
302
+ } })) }), (0, jsx_runtime_1.jsx)(PopoverComponent, { onClose: () => {
233
303
  setShowUpdatePivot(false);
234
- }, title: "Add pivot", children: showUpdatePivot ? ((0, jsx_runtime_1.jsxs)("div", { style: {
235
- backgroundColor: 'rgb(255, 255, 255)',
236
- display: 'flex',
237
- flexDirection: 'column',
238
- }, children: [(0, jsx_runtime_1.jsx)("div", { style: {
239
- fontSize: 14,
240
- marginBottom: '6px',
241
- fontWeight: '600',
242
- color: theme.secondaryTextColor,
243
- fontFamily: theme?.fontFamily,
244
- }, children: "Create pivot" }), (0, jsx_runtime_1.jsxs)("div", { style: {
245
- display: 'flex',
246
- flexDirection: 'column',
247
- gap: 5,
248
- alignItems: 'center',
249
- justifyContent: 'space-between',
250
- }, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
251
- display: 'flex',
252
- flexDirection: 'row',
253
- gap: 10,
254
- marginBottom: 5,
255
- }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { style: {
256
- fontSize: 14,
257
- marginBottom: '6px',
258
- fontWeight: '600',
259
- color: theme.secondaryTextColor,
260
- fontFamily: theme?.fontFamily,
261
- }, children: "Row Field" }), (0, jsx_runtime_1.jsx)(SelectComponent, { id: "pivot-row-field", value: pivotRowField, onChange: e => {
262
- setPivotRowField(e);
263
- }, options: columnSelectOptions })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { style: {
264
- fontSize: 14,
265
- marginBottom: '6px',
266
- fontWeight: '600',
267
- color: theme.secondaryTextColor,
268
- fontFamily: theme?.fontFamily,
269
- }, children: "Column Field" }), (0, jsx_runtime_1.jsx)(SelectComponent, { id: "pivot-row-field", value: pivotColumnField, onChange: e => {
270
- setPivotColumnField(e);
271
- }, options: columnSelectOptions })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: {
272
- display: 'flex',
273
- flexDirection: 'row',
274
- gap: 10,
304
+ setPopUpTitle('Add Pivot');
305
+ }, style: rightAlign ? { right: 0 } : {}, parentRef: parentRef, showTrigger: showTrigger, label: triggerButtonText, isOpen: isOpen, setIsOpen: setIsOpen, onClick: () => {
306
+ // table is not loaded yet, so pivot button is not clickable
307
+ if (Object.keys(columnsToShow).length === 0) {
308
+ return;
309
+ }
310
+ if (!isOpen && recommendedPivots.length === 0) {
311
+ refreshPivots();
312
+ }
313
+ setShowUpdatePivot(false);
314
+ }, children: (0, jsx_runtime_1.jsx)("div", { children: showUpdatePivot ? ((0, jsx_runtime_1.jsxs)("div", { className: "ref-in-use", ref: editModalRef, style: {
315
+ backgroundColor: 'rgb(255, 255, 255)',
316
+ display: 'flex',
317
+ flexDirection: 'column',
318
+ }, children: [(0, jsx_runtime_1.jsx)(HeaderComponent, { children: popUpTitle }), (0, jsx_runtime_1.jsx)("div", { style: { height: 12 } }), (0, jsx_runtime_1.jsx)("div", { style: { width: divWidth }, children: samplePivotTable ? ((0, jsx_runtime_1.jsx)("div", { style: {
275
319
  marginBottom: 20,
276
- }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { style: {
277
- fontSize: 14,
278
- marginBottom: '6px',
279
- fontWeight: '600',
280
- color: theme.secondaryTextColor,
281
- fontFamily: theme?.fontFamily,
282
- }, children: "Value Field" }), (0, jsx_runtime_1.jsx)(SelectComponent, { id: "pivot-row-field", value: pivotValueField, onChange: e => {
283
- setPivotValueField(e);
284
- }, options: columnSelectOptions })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { style: {
285
- fontSize: 14,
286
- marginBottom: '6px',
287
- fontWeight: '600',
288
- color: theme.secondaryTextColor,
289
- fontFamily: theme?.fontFamily,
290
- }, children: "Aggregation Type" }), (0, jsx_runtime_1.jsx)(SelectComponent, { id: "pivot-row-field", value: pivotAggregation, onChange: e => {
291
- setPivotAggregation(e);
292
- }, options: [null, 'sum', 'average', 'count'].map(option => {
293
- return { label: option, value: option };
294
- }) })] })] })] }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(ButtonComponent, { id: "custom-button", onClick: () => {
295
- const errors = [];
296
- if (!pivotRowField) {
297
- errors.push('Row field cannot be empty');
298
- }
299
- if (!pivotValueField) {
300
- errors.push('Value field cannot be empty');
301
- }
302
- if (!pivotAggregation) {
303
- errors.push('Aggregation cannot be empty');
304
- }
305
- if (errors.length === 0) {
306
- const pivot = {
307
- rowField: pivotRowField || '',
308
- rowFieldType: columnsToShow[pivotRowField || ''],
309
- columnField: pivotColumnField,
310
- columnFieldType: columnsToShow[pivotColumnField || ''],
311
- valueField: pivotValueField || '',
312
- aggregationType: pivotAggregation || '',
313
- };
314
- pivot.title = generatePivotTitle(pivot);
315
- if (pivotUpdateIndex !== null) {
316
- createdPivots.splice(pivotUpdateIndex, 1, pivot);
317
- setCreatedPivots([...createdPivots]);
318
- onSelectCreatedPivot(pivot, pivotUpdateIndex);
319
- setPivotUpdateIndex(null);
320
+ minHeight: 160,
321
+ }, children: (0, jsx_runtime_1.jsx)(PivotList_1.PivotCard, { pivotTable: samplePivotTable, theme: theme, index: 0, onSelectPivot: () => { }, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent: ButtonComponent, showEdit: false, clickable: false, minHeight: 140, LabelComponent: LabelComponent, TextComponent: TextComponent, HeaderComponent: HeaderComponent }) })) : ((0, jsx_runtime_1.jsx)("div", { style: { marginBottom: 20, maxWidth: 470 }, children: (0, jsx_runtime_1.jsx)(QuillCard_1.QuillCard, { theme: theme, clickable: false, children: (0, jsx_runtime_1.jsx)("div", { style: {
322
+ color: theme.secondaryTextColor,
323
+ }, children: "Select a row field and aggregation type to see a preview" }) }) })) }), (0, jsx_runtime_1.jsxs)("div", { style: {
324
+ display: 'flex',
325
+ flexDirection: 'column',
326
+ gap: 10,
327
+ alignItems: 'center',
328
+ justifyContent: 'space-between',
329
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
330
+ display: 'flex',
331
+ flexDirection: 'row',
332
+ gap: 20,
333
+ marginBottom: 5,
334
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(LabelComponent, { children: "Row Field" }), (0, jsx_runtime_1.jsx)(SelectComponent, { label: 'Row Field', id: "pivot-row-field", value: pivotRowField, onChange: e => {
335
+ setPivotRowField(e === '' ? undefined : e);
336
+ }, options: columnSelectOptions, theme: theme })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(LabelComponent, { children: "Column Field" }), (0, jsx_runtime_1.jsx)(SelectComponent, { label: 'Column Field', id: "pivot-row-field", value: pivotColumnField, onChange: e => {
337
+ setPivotColumnField(e === '' ? undefined : e);
338
+ }, options: columnSelectOptions, theme: theme })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: {
339
+ display: 'flex',
340
+ flexDirection: 'row',
341
+ gap: 20,
342
+ marginBottom: 20,
343
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(LabelComponent, { children: "Value Field" }), (0, jsx_runtime_1.jsx)(SelectComponent, { label: 'Value Field', id: "pivot-row-field", value: pivotValueField, onChange: e => {
344
+ setPivotValueField(e === '' ? undefined : e);
345
+ }, options: pivotAggregation === 'count'
346
+ ? columnSelectOptions
347
+ : columnSelectOptions.filter(option => {
348
+ return (option.value === '' ||
349
+ ChartBuilder_1.numberFormatOptions.includes(columns.find(col => col.field === option.value)?.format));
350
+ }), theme: theme })] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(LabelComponent, { children: "Aggregation Type" }), (0, jsx_runtime_1.jsx)(SelectComponent, { label: 'Aggregation Type', id: "pivot-row-field", value: pivotAggregation, theme: theme, onChange: e => {
351
+ if (e !== 'count' &&
352
+ pivotValueField &&
353
+ !ChartBuilder_1.numberFormatOptions.includes(columns.find(col => col.field === pivotValueField)
354
+ ?.format)) {
355
+ setPivotValueField(null);
356
+ }
357
+ setPivotAggregation(e === '' ? undefined : e);
358
+ }, options: ['', 'sum', 'average', 'count'].map(option => {
359
+ return { label: option || 'Select', value: option };
360
+ }) })] })] })] }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(ButtonComponent, { id: "custom-button", onClick: () => {
361
+ const errors = [];
362
+ if (!pivotRowField) {
363
+ errors.push('Row field cannot be empty');
320
364
  }
321
- else {
322
- onSelectCreatedPivot(pivot, createdPivots.length);
323
- setCreatedPivots([...createdPivots, pivot]);
365
+ if (!pivotValueField && pivotAggregation !== 'count') {
366
+ errors.push("Value field cannot be empty when aggregation is not 'count'");
324
367
  }
325
- setIsOpen(false);
326
- }
327
- setErrors(errors);
328
- }, label: pivotUpdateIndex !== null ? 'Edit Pivot' : 'Create Pivot' }) }), (0, jsx_runtime_1.jsx)("div", { children: errors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { style: {
329
- fontSize: 14,
330
- marginBottom: '6px',
331
- marginTop: '12px',
332
- fontWeight: '600',
333
- color: theme.secondaryTextColor,
334
- }, children: "Pivot Errors" }), errors.map((error, index) => ((0, jsx_runtime_1.jsx)("div", { style: {
335
- borderRadius: 8,
336
- backgroundColor: '#FF9494',
337
- paddingLeft: '12px',
338
- paddingRight: '8px',
339
- height: 30,
368
+ if (!pivotAggregation) {
369
+ errors.push('Aggregation cannot be empty');
370
+ }
371
+ if (errors.length === 0) {
372
+ const pivot = {
373
+ rowField: pivotRowField || '',
374
+ rowFieldType: columnsToShow[pivotRowField || ''],
375
+ columnField: pivotColumnField,
376
+ columnFieldType: columnsToShow[pivotColumnField || ''],
377
+ valueField: pivotValueField || '',
378
+ aggregationType: pivotAggregation || '',
379
+ };
380
+ pivot.title = generatePivotTitle(pivot);
381
+ setIsOpen(false);
382
+ setCreatedPivots([pivot]);
383
+ onSelectCreatedPivot(pivot, 0);
384
+ setPopUpTitle('Add Pivot');
385
+ }
386
+ setErrors(errors);
387
+ }, label: popUpTitle }) }), (0, jsx_runtime_1.jsx)("div", { children: errors.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { style: {
388
+ fontSize: 14,
389
+ marginBottom: '6px',
390
+ marginTop: '12px',
391
+ fontWeight: '600',
392
+ color: theme.secondaryTextColor,
393
+ }, children: "Pivot Errors" }), errors.map((error, index) => ((0, jsx_runtime_1.jsx)("div", { style: {
394
+ borderRadius: 8,
395
+ backgroundColor: '#FF9494',
396
+ paddingLeft: '12px',
397
+ paddingRight: '8px',
398
+ height: 30,
399
+ display: 'flex',
400
+ alignItems: 'center',
401
+ fontSize: 13,
402
+ fontWeight: 'bold',
403
+ fontFamily: theme?.fontFamily,
404
+ color: 'white',
405
+ marginBottom: 5,
406
+ }, children: error }, index)))] })) })] })) : ((0, jsx_runtime_1.jsx)("div", { style: {
407
+ display: 'flex',
408
+ flexDirection: 'column',
409
+ fontFamily: theme?.fontFamily,
410
+ color: theme?.primaryTextColor,
411
+ width: selectedPivotTable ? 500 : 600,
412
+ maxHeight: 600,
413
+ overflowY: 'scroll',
414
+ }, children: selectedPivotIndex >= 0 ? ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("div", { onClick: () => {
415
+ setPopUpTitle('Edit Pivot');
416
+ onEditPivot(createdPivots[0], 0);
417
+ }, children: (0, jsx_runtime_1.jsx)(PivotList_1.PivotCard, { pivotTable: {
418
+ pivot: selectedPivotTable?.pivot,
419
+ rows: selectedPivotTable?.rows,
420
+ columns: selectedPivotTable?.columns,
421
+ }, theme: theme, index: 0, onSelectPivot: () => { }, selectedPivotIndex: -1, onEditPivot: () => { }, ButtonComponent: ButtonComponent, showEdit: false, onClose: () => {
422
+ removePivot();
423
+ }, clickable: true, minHeight: 180, LabelComponent: LabelComponent, TextComponent: TextComponent, HeaderComponent: HeaderComponent }) }) })) : ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', flexDirection: 'column' }, children: [(0, jsx_runtime_1.jsx)("div", { style: {
424
+ fontWeight: '600',
425
+ marginBottom: 5,
426
+ fontSize: 18,
427
+ }, children: "Recommended Pivots" }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsxs)("div", { onClick: refreshPivots, style: {
428
+ color: theme?.secondaryTextColor,
429
+ cursor: 'pointer',
430
+ marginTop: 0,
431
+ marginBottom: 12,
340
432
  display: 'flex',
433
+ flexDirection: 'row',
341
434
  alignItems: 'center',
342
- fontSize: 13,
343
- fontWeight: 'bold',
344
- fontFamily: theme?.fontFamily,
345
- color: 'white',
346
- marginBottom: 5,
347
- }, children: error }, index)))] })) })] })) : ((0, jsx_runtime_1.jsx)("div", { style: {
348
- display: 'flex',
349
- flexDirection: 'column',
350
- fontFamily: theme?.fontFamily,
351
- color: theme?.primaryTextColor,
352
- width: 700,
353
- }, children: (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', flexDirection: 'column' }, children: [(0, jsx_runtime_1.jsx)("div", { style: {
354
- fontWeight: '600',
355
- marginBottom: 5,
356
- fontSize: 18,
357
- }, children: "Recommended Pivots" }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsxs)("div", { onClick: refreshPivots, style: {
358
- color: theme?.secondaryTextColor,
359
- cursor: 'pointer',
360
- marginTop: 0,
361
- marginBottom: 12,
362
- marginLeft: -8,
435
+ width: 'min-content',
436
+ fontSize: 14,
437
+ paddingLeft: 8,
438
+ paddingRight: 6,
439
+ paddingTop: 6,
440
+ paddingBottom: 6,
441
+ borderRadius: 5,
442
+ }, className: "quill-hover", children: [(0, jsx_runtime_1.jsx)(QuillHover, {}), (0, jsx_runtime_1.jsx)(assets_1.RefreshIcon, { style: { marginRight: 5 } }), "Refresh"] }) }), isLoading ? ((0, jsx_runtime_1.jsxs)("div", { style: {
443
+ background: theme.backgroundColor,
444
+ width: 250,
445
+ minWidth: 250,
446
+ height: '100%',
447
+ paddingLeft: 20,
448
+ paddingRight: 30,
449
+ paddingTop: 40,
363
450
  display: 'flex',
364
- flexDirection: 'row',
365
- alignItems: 'center',
366
- fontSize: 14,
367
- maxWidth: 90,
368
- paddingLeft: 8,
369
- paddingRight: 6,
370
- paddingTop: 6,
371
- paddingBottom: 6,
372
- borderRadius: 5,
373
- }, className: "quill-hover", children: [(0, jsx_runtime_1.jsx)(QuillHover, {}), (0, jsx_runtime_1.jsx)(assets_1.RefreshIcon, { style: { marginRight: 5 } }), "Refresh"] }) }), isLoading ? ((0, jsx_runtime_1.jsxs)("div", { style: {
374
- background: theme.backgroundColor,
375
- width: 250,
376
- minWidth: 250,
377
- height: '100%',
378
- paddingLeft: 20,
379
- paddingRight: 30,
380
- paddingTop: 40,
381
- display: 'flex',
382
- margin: '0px auto',
383
- justifyContent: 'center',
384
- }, children: [(0, jsx_runtime_1.jsx)("div", { style: { height: 100 } }), (0, jsx_runtime_1.jsxs)("svg", { width: "24", height: "24", children: [(0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "9.375", strokeWidth: "3.75", strokeDasharray: "calc(2 * 3.14 * 9.375 / 3) calc(2 * 3.14 * 9.375 * 2 / 3)", strokeDashoffset: "calc(2 * 3.14 * 9.375 / 6)", stroke: theme?.primaryTextColor || '#364153', fill: "none", transform: "rotate(-90 12 12)", children: (0, jsx_runtime_1.jsx)("animateTransform", { attributeName: "transform", attributeType: "XML", type: "rotate", from: "-180 12 12", to: "180 12 12", dur: "0.8s", repeatCount: "indefinite" }) }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "9.375", strokeWidth: "3.75", strokeDasharray: "calc(2 * 3.14 * 9.375 / 3) calc(2 * 3.14 * 9.375 * 1 / 3)", strokeDashoffset: "calc(2 * 3.14 * 9.375 / 3) calc(2 * 3.14 * 9.375 * 2 / 3)", stroke: '#ADB1B9', fill: "none", transform: "rotate(90 12 12)", children: (0, jsx_runtime_1.jsx)("animateTransform", { attributeName: "transform", attributeType: "XML", type: "rotate", from: "0 12 12", to: "360 12 12", dur: "0.8s", repeatCount: "indefinite" }) })] })] })) : ((0, jsx_runtime_1.jsx)(PivotList_1.PivotList, { pivotTables: recommendedPivotTables, theme: theme, onSelectPivot: onSelectRecommendedPivot, selectedPivotIndex: selectedPivotType === 'recommended'
385
- ? selectedPivotIndex
386
- : -1, ButtonComponent: ButtonComponent, onEditPivot: onEditRecommendedPivot }))] }) })) })] }) }));
451
+ margin: '0px auto',
452
+ justifyContent: 'center',
453
+ }, children: [(0, jsx_runtime_1.jsx)("div", { style: { height: 100 } }), (0, jsx_runtime_1.jsxs)("svg", { width: "24", height: "24", children: [(0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "9.375", strokeWidth: "3.75", strokeDasharray: "calc(2 * 3.14 * 9.375 / 3) calc(2 * 3.14 * 9.375 * 2 / 3)", strokeDashoffset: "calc(2 * 3.14 * 9.375 / 6)", stroke: theme?.primaryTextColor || '#364153', fill: "none", transform: "rotate(-90 12 12)", children: (0, jsx_runtime_1.jsx)("animateTransform", { attributeName: "transform", attributeType: "XML", type: "rotate", from: "-180 12 12", to: "180 12 12", dur: "0.8s", repeatCount: "indefinite" }) }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "9.375", strokeWidth: "3.75", strokeDasharray: "calc(2 * 3.14 * 9.375 / 3) calc(2 * 3.14 * 9.375 * 1 / 3)", strokeDashoffset: "calc(2 * 3.14 * 9.375 / 3) calc(2 * 3.14 * 9.375 * 2 / 3)", stroke: '#ADB1B9', fill: "none", transform: "rotate(90 12 12)", children: (0, jsx_runtime_1.jsx)("animateTransform", { attributeName: "transform", attributeType: "XML", type: "rotate", from: "0 12 12", to: "360 12 12", dur: "0.8s", repeatCount: "indefinite" }) })] })] })) : ((0, jsx_runtime_1.jsxs)("div", { children: [recommendedPivotTables.length == 0 && ((0, jsx_runtime_1.jsx)("div", { style: { marginBottom: 20 }, children: "There are currently no recommended pivots available." })), (0, jsx_runtime_1.jsx)(PivotList_1.PivotList, { recommendedPivotTables: recommendedPivotTables, createdPivotTables: createdPivotTables, theme: theme, onSelectRecommendedPivot: onSelectRecommendedPivot, onSelectCreatedPivot: onSelectCreatedPivot, selectedPivotIndex: selectedPivotIndex, selectedPivotType: selectedPivotType, ButtonComponent: ButtonComponent, HeaderComponent: HeaderComponent, onEditRecommendedPivot: onEditRecommendedPivot, onEditCreatedPivot: onEditPivot, showCreatePivot: true, showPivotEditButton: showPivotEditButton, LabelComponent: LabelComponent, TextComponent: TextComponent })] }))] })) })) }) })] }) }));
387
454
  };
388
455
  exports.PivotModal = PivotModal;
456
+ function generatePivotTableYAxis(pivot, pivotColumns, format) {
457
+ return pivot.columnField
458
+ ? pivotColumns.slice(1).map(col => {
459
+ return {
460
+ field: col.field,
461
+ label: col.label,
462
+ format: format,
463
+ };
464
+ })
465
+ : [
466
+ {
467
+ field: pivot.valueField,
468
+ label: '',
469
+ format: format,
470
+ },
471
+ ];
472
+ }
473
+ exports.generatePivotTableYAxis = generatePivotTableYAxis;
389
474
  function generatePivotTitle(pivot) {
390
- return `${pivot.aggregationType} of ${pivot.valueField} by ${pivot.rowField}${pivot.columnField ? ` and ${pivot.columnField}` : ''}`;
475
+ return (0, ChartBuilder_1.snakeCaseToTitleCase)(`${pivot.aggregationType} of ${pivot.valueField} by ${pivot.rowField}${pivot.columnField ? ` and ${pivot.columnField}` : ''}`);
391
476
  }
392
477
  function getDateBuckets(dateRange) {
393
478
  const dayDifference = (0, date_fns_1.differenceInDays)(new Date(dateRange[1]), new Date(dateRange[0]));
@@ -425,35 +510,43 @@ function getDateString(value, dateRange) {
425
510
  fields: [{ field: 'date', format }],
426
511
  });
427
512
  }
513
+ function isDateField(fieldType) {
514
+ return (fieldType === 'date' ||
515
+ fieldType === 'datetime' ||
516
+ fieldType === 'timestamp' ||
517
+ fieldType === 'timestamptz');
518
+ }
519
+ exports.isDateField = isDateField;
428
520
  function generatePivotTable(pivot, data, dateRange) {
429
521
  const pivotRows = [];
430
- const uniqueRows = pivot.rowFieldType === 'date'
522
+ const uniqueRows = isDateField(pivot.rowFieldType)
431
523
  ? getDateBuckets(dateRange)
432
524
  : [...new Set(data.map(item => item[pivot.rowField]))];
433
525
  // If columnField is not provided, we will not be using uniqueColumns
434
526
  const uniqueColumns = pivot.columnField
435
- ? pivot.columnFieldType === 'date'
527
+ ? isDateField(pivot.columnFieldType)
436
528
  ? getDateBuckets(dateRange)
437
529
  : [...new Set(data.map(item => item[pivot.columnField || '']))]
438
530
  : [pivot.valueField];
439
531
  uniqueRows.forEach((rowValue, rowIndex) => {
440
532
  const row = {
441
- [pivot.rowField]: pivot.rowFieldType === 'date'
533
+ [pivot.rowField]: isDateField(pivot.rowFieldType)
442
534
  ? getDateString(rowValue, dateRange)
443
535
  : rowValue,
444
536
  };
445
537
  uniqueColumns.forEach((colValue, colIndex) => {
446
538
  let filteredData;
447
539
  let value;
448
- const nextRowValue = pivot.rowFieldType === 'date'
540
+ const nextRowValue = isDateField(pivot.rowFieldType)
449
541
  ? uniqueRows[rowIndex + 1] || (0, date_fns_1.endOfDay)(dateRange[1])
450
542
  : null;
451
543
  if (pivot.columnField) {
452
- const nextColumnValue = pivot.columnFieldType === 'date'
544
+ const nextColumnValue = isDateField(pivot.columnFieldType)
453
545
  ? uniqueColumns[colIndex + 1] || (0, date_fns_1.endOfDay)(dateRange[1])
454
546
  : null;
455
547
  // If columnField is provided, filter by both rowField and columnField
456
- if (pivot.columnFieldType === 'date' && pivot.rowFieldType === 'date') {
548
+ if (isDateField(pivot.columnFieldType) &&
549
+ isDateField(pivot.rowFieldType)) {
457
550
  filteredData = data.filter((item) => {
458
551
  return ((0, date_fns_1.isWithinInterval)(new Date(item[pivot.rowField]), {
459
552
  start: rowValue,
@@ -465,8 +558,8 @@ function generatePivotTable(pivot, data, dateRange) {
465
558
  }));
466
559
  });
467
560
  }
468
- else if (pivot.columnFieldType === 'date' &&
469
- pivot.rowFieldType !== 'date') {
561
+ else if (isDateField(pivot.columnFieldType) &&
562
+ !isDateField(pivot.rowFieldType)) {
470
563
  filteredData = data.filter((item) => {
471
564
  return (item[pivot.rowField] === rowValue &&
472
565
  (0, date_fns_1.isWithinInterval)(new Date(item[pivot.columnField]), {
@@ -475,8 +568,8 @@ function generatePivotTable(pivot, data, dateRange) {
475
568
  }));
476
569
  });
477
570
  }
478
- else if (pivot.columnFieldType !== 'date' &&
479
- pivot.rowFieldType === 'date') {
571
+ else if (!isDateField(pivot.columnFieldType) &&
572
+ isDateField(pivot.rowFieldType)) {
480
573
  filteredData = data.filter((item) => {
481
574
  return ((0, date_fns_1.isWithinInterval)(new Date(item[pivot.rowField]), {
482
575
  start: rowValue,
@@ -493,15 +586,14 @@ function generatePivotTable(pivot, data, dateRange) {
493
586
  }
494
587
  else {
495
588
  // If columnField is not provided, filter by rowField only
496
- filteredData =
497
- pivot.rowFieldType === 'date'
498
- ? data.filter(item => {
499
- return (0, date_fns_1.isWithinInterval)(new Date(item[pivot.rowField]), {
500
- start: rowValue,
501
- end: (0, date_fns_1.subMilliseconds)(nextRowValue, 1),
502
- });
503
- })
504
- : data.filter(item => item[pivot.rowField] === rowValue);
589
+ filteredData = isDateField(pivot.rowFieldType)
590
+ ? data.filter(item => {
591
+ return (0, date_fns_1.isWithinInterval)(new Date(item[pivot.rowField]), {
592
+ start: rowValue,
593
+ end: (0, date_fns_1.subMilliseconds)(nextRowValue, 1),
594
+ });
595
+ })
596
+ : data.filter(item => item[pivot.rowField] === rowValue);
505
597
  }
506
598
  // Aggregation logic remains the same
507
599
  switch (pivot.aggregationType) {
@@ -522,9 +614,9 @@ function generatePivotTable(pivot, data, dateRange) {
522
614
  }
523
615
  // Set the value on the row
524
616
  // If columnField is not provided, colValue will be valueField
525
- row[pivot.columnFieldType === 'date'
617
+ row[isDateField(pivot.columnFieldType)
526
618
  ? getDateString(colValue, dateRange)
527
- : colValue] = value;
619
+ : colValue] = pivot.aggregationType === 'count' ? value : value.toFixed(2);
528
620
  });
529
621
  pivotRows.push(row);
530
622
  });
@@ -533,11 +625,11 @@ function generatePivotTable(pivot, data, dateRange) {
533
625
  return {
534
626
  rows: pivotRows,
535
627
  columns: uniqueColumns.map((column, index) => {
536
- const columnName = pivot.columnFieldType === 'date' && index > 0 // first row is rowField
628
+ const columnName = isDateField(pivot.columnFieldType) && index > 0 // first row is rowField
537
629
  ? getDateString(column, dateRange)
538
630
  : column;
539
631
  return {
540
- label: columnName,
632
+ label: (0, ChartBuilder_1.snakeCaseToTitleCase)(columnName),
541
633
  field: columnName,
542
634
  };
543
635
  }),