@quillsql/admin 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/cjs/Admin.d.ts +23 -73
  2. package/dist/cjs/Admin.d.ts.map +1 -1
  3. package/dist/cjs/Admin.js +221 -970
  4. package/dist/cjs/AdminProvider.d.ts +1 -12
  5. package/dist/cjs/AdminProvider.d.ts.map +1 -1
  6. package/dist/cjs/AdminProvider.js +24 -18
  7. package/dist/cjs/api/ConnectionClient.d.ts +11 -0
  8. package/dist/cjs/api/ConnectionClient.d.ts.map +1 -1
  9. package/dist/cjs/api/ConnectionClient.js +84 -10
  10. package/dist/cjs/components/DropDownMenu.js +1 -1
  11. package/dist/cjs/components/DropDownMenuWithLabel.d.ts.map +1 -1
  12. package/dist/cjs/components/DropDownMenuWithLabel.js +16 -54
  13. package/dist/cjs/components/OrgSelect.d.ts.map +1 -1
  14. package/dist/cjs/components/OrgSelect.js +10 -20
  15. package/dist/cjs/components/QuillSelect.d.ts +3 -0
  16. package/dist/cjs/components/QuillSelect.d.ts.map +1 -0
  17. package/dist/cjs/components/QuillSelect.js +137 -0
  18. package/dist/cjs/components/SegmentedControl.d.ts +7 -0
  19. package/dist/cjs/components/SegmentedControl.d.ts.map +1 -0
  20. package/dist/cjs/components/SegmentedControl.js +54 -0
  21. package/dist/cjs/components/UiComponents.d.ts +18 -29
  22. package/dist/cjs/components/UiComponents.d.ts.map +1 -1
  23. package/dist/cjs/components/UiComponents.js +40 -83
  24. package/dist/cjs/forms/client_onboard/ConnectSchema.d.ts +2 -1
  25. package/dist/cjs/forms/client_onboard/ConnectSchema.d.ts.map +1 -1
  26. package/dist/cjs/forms/client_onboard/ConnectSchema.js +143 -68
  27. package/dist/cjs/forms/client_onboard/CreateSqlViews.d.ts.map +1 -1
  28. package/dist/cjs/forms/client_onboard/CreateSqlViews.js +40 -11
  29. package/dist/cjs/forms/sql_views/CreateEditSqlView.d.ts +7 -4
  30. package/dist/cjs/forms/sql_views/CreateEditSqlView.d.ts.map +1 -1
  31. package/dist/cjs/forms/sql_views/CreateEditSqlView.js +36 -20
  32. package/dist/cjs/hooks/useOnClickOutside.d.ts +3 -0
  33. package/dist/cjs/hooks/useOnClickOutside.d.ts.map +1 -0
  34. package/dist/cjs/hooks/useOnClickOutside.js +20 -0
  35. package/dist/cjs/modals/EditFiltersModal.d.ts +17 -0
  36. package/dist/cjs/modals/EditFiltersModal.d.ts.map +1 -0
  37. package/dist/cjs/modals/EditFiltersModal.js +345 -0
  38. package/dist/cjs/modals/NewDashboardModal.d.ts +1 -3
  39. package/dist/cjs/modals/NewDashboardModal.d.ts.map +1 -1
  40. package/dist/cjs/modals/NewDashboardModal.js +63 -46
  41. package/dist/cjs/modals/PromoteDashModal.d.ts.map +1 -1
  42. package/dist/cjs/modals/PromoteDashModal.js +10 -3
  43. package/dist/cjs/modals/ReorderDashboardModal.d.ts.map +1 -1
  44. package/dist/cjs/modals/ReorderDashboardModal.js +202 -90
  45. package/dist/cjs/modals/index.d.ts +0 -1
  46. package/dist/cjs/modals/index.d.ts.map +1 -1
  47. package/dist/cjs/modals/index.js +1 -3
  48. package/dist/cjs/primitives/ButtonPrimitive.d.ts +3 -1
  49. package/dist/cjs/primitives/ButtonPrimitive.d.ts.map +1 -1
  50. package/dist/cjs/primitives/ButtonPrimitive.js +5 -3
  51. package/dist/cjs/primitives/ModalPrimitive.d.ts.map +1 -1
  52. package/dist/cjs/primitives/ModalPrimitive.js +1 -2
  53. package/dist/cjs/primitives/TogglePrimitive.js +5 -5
  54. package/dist/cjs/public_components/CreateEnvironment.d.ts.map +1 -1
  55. package/dist/cjs/public_components/CreateEnvironment.js +1 -1
  56. package/dist/cjs/public_components/DashboardBuilder.d.ts.map +1 -1
  57. package/dist/cjs/public_components/DashboardBuilder.js +127 -30
  58. package/dist/cjs/public_components/DashboardManager.d.ts.map +1 -1
  59. package/dist/cjs/public_components/DashboardManager.js +161 -193
  60. package/dist/cjs/public_components/SQLViewManager.d.ts.map +1 -1
  61. package/dist/cjs/public_components/SQLViewManager.js +92 -24
  62. package/dist/cjs/utils/constants.d.ts +4 -4
  63. package/dist/cjs/utils/constants.js +2 -2
  64. package/dist/cjs/utils/schema.d.ts +6 -0
  65. package/dist/cjs/utils/schema.d.ts.map +1 -1
  66. package/dist/cjs/utils/table.d.ts +1 -0
  67. package/dist/cjs/utils/table.d.ts.map +1 -1
  68. package/dist/cjs/utils/table.js +13 -0
  69. package/dist/cjs/utils/textProcessing.d.ts +2 -0
  70. package/dist/cjs/utils/textProcessing.d.ts.map +1 -0
  71. package/dist/cjs/utils/textProcessing.js +9 -0
  72. package/dist/esm/Admin.d.ts +23 -73
  73. package/dist/esm/Admin.d.ts.map +1 -1
  74. package/dist/esm/Admin.js +225 -964
  75. package/dist/esm/AdminProvider.d.ts +1 -12
  76. package/dist/esm/AdminProvider.d.ts.map +1 -1
  77. package/dist/esm/AdminProvider.js +25 -19
  78. package/dist/esm/api/ConnectionClient.d.ts +11 -0
  79. package/dist/esm/api/ConnectionClient.d.ts.map +1 -1
  80. package/dist/esm/api/ConnectionClient.js +82 -9
  81. package/dist/esm/components/DropDownMenu.js +1 -1
  82. package/dist/esm/components/DropDownMenuWithLabel.d.ts.map +1 -1
  83. package/dist/esm/components/DropDownMenuWithLabel.js +16 -54
  84. package/dist/esm/components/OrgSelect.d.ts.map +1 -1
  85. package/dist/esm/components/OrgSelect.js +6 -19
  86. package/dist/esm/components/QuillSelect.d.ts +3 -0
  87. package/dist/esm/components/QuillSelect.d.ts.map +1 -0
  88. package/dist/esm/components/QuillSelect.js +130 -0
  89. package/dist/esm/components/SegmentedControl.d.ts +7 -0
  90. package/dist/esm/components/SegmentedControl.d.ts.map +1 -0
  91. package/dist/esm/components/SegmentedControl.js +50 -0
  92. package/dist/esm/components/UiComponents.d.ts +18 -29
  93. package/dist/esm/components/UiComponents.d.ts.map +1 -1
  94. package/dist/esm/components/UiComponents.js +37 -82
  95. package/dist/esm/forms/client_onboard/ConnectSchema.d.ts +2 -1
  96. package/dist/esm/forms/client_onboard/ConnectSchema.d.ts.map +1 -1
  97. package/dist/esm/forms/client_onboard/ConnectSchema.js +145 -70
  98. package/dist/esm/forms/client_onboard/CreateSqlViews.d.ts.map +1 -1
  99. package/dist/esm/forms/client_onboard/CreateSqlViews.js +41 -12
  100. package/dist/esm/forms/sql_views/CreateEditSqlView.d.ts +7 -4
  101. package/dist/esm/forms/sql_views/CreateEditSqlView.d.ts.map +1 -1
  102. package/dist/esm/forms/sql_views/CreateEditSqlView.js +38 -22
  103. package/dist/esm/hooks/useOnClickOutside.d.ts +3 -0
  104. package/dist/esm/hooks/useOnClickOutside.d.ts.map +1 -0
  105. package/dist/esm/hooks/useOnClickOutside.js +18 -0
  106. package/dist/esm/modals/EditFiltersModal.d.ts +17 -0
  107. package/dist/esm/modals/EditFiltersModal.d.ts.map +1 -0
  108. package/dist/esm/modals/EditFiltersModal.js +338 -0
  109. package/dist/esm/modals/NewDashboardModal.d.ts +1 -3
  110. package/dist/esm/modals/NewDashboardModal.d.ts.map +1 -1
  111. package/dist/esm/modals/NewDashboardModal.js +63 -46
  112. package/dist/esm/modals/PromoteDashModal.d.ts.map +1 -1
  113. package/dist/esm/modals/PromoteDashModal.js +10 -3
  114. package/dist/esm/modals/ReorderDashboardModal.d.ts.map +1 -1
  115. package/dist/esm/modals/ReorderDashboardModal.js +201 -89
  116. package/dist/esm/modals/index.d.ts +0 -1
  117. package/dist/esm/modals/index.d.ts.map +1 -1
  118. package/dist/esm/modals/index.js +0 -1
  119. package/dist/esm/primitives/ButtonPrimitive.d.ts +3 -1
  120. package/dist/esm/primitives/ButtonPrimitive.d.ts.map +1 -1
  121. package/dist/esm/primitives/ButtonPrimitive.js +5 -3
  122. package/dist/esm/primitives/ModalPrimitive.d.ts.map +1 -1
  123. package/dist/esm/primitives/ModalPrimitive.js +1 -2
  124. package/dist/esm/primitives/TogglePrimitive.js +5 -5
  125. package/dist/esm/public_components/CreateEnvironment.d.ts.map +1 -1
  126. package/dist/esm/public_components/CreateEnvironment.js +1 -1
  127. package/dist/esm/public_components/DashboardBuilder.d.ts.map +1 -1
  128. package/dist/esm/public_components/DashboardBuilder.js +128 -31
  129. package/dist/esm/public_components/DashboardManager.d.ts.map +1 -1
  130. package/dist/esm/public_components/DashboardManager.js +163 -195
  131. package/dist/esm/public_components/SQLViewManager.d.ts.map +1 -1
  132. package/dist/esm/public_components/SQLViewManager.js +92 -24
  133. package/dist/esm/utils/constants.d.ts +4 -4
  134. package/dist/esm/utils/constants.js +2 -2
  135. package/dist/esm/utils/schema.d.ts +6 -0
  136. package/dist/esm/utils/schema.d.ts.map +1 -1
  137. package/dist/esm/utils/table.d.ts +1 -0
  138. package/dist/esm/utils/table.d.ts.map +1 -1
  139. package/dist/esm/utils/table.js +11 -1
  140. package/dist/esm/utils/textProcessing.d.ts +2 -0
  141. package/dist/esm/utils/textProcessing.d.ts.map +1 -0
  142. package/dist/esm/utils/textProcessing.js +5 -0
  143. package/package.json +1 -1
  144. package/dist/cjs/modals/EditDashboardsModal.d.ts +0 -20
  145. package/dist/cjs/modals/EditDashboardsModal.d.ts.map +0 -1
  146. package/dist/cjs/modals/EditDashboardsModal.js +0 -94
  147. package/dist/esm/modals/EditDashboardsModal.d.ts +0 -20
  148. package/dist/esm/modals/EditDashboardsModal.d.ts.map +0 -1
  149. package/dist/esm/modals/EditDashboardsModal.js +0 -91
package/dist/esm/Admin.js CHANGED
@@ -1,23 +1,20 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- // @ts-nocheck
3
- import { useState, useEffect } from 'react';
4
- import { QuillProvider, useQuill, Chart, ChartEditor, useDashboard, QuillTable, } from '@quillsql/react';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect, useRef, useCallback } from 'react';
3
+ import { QuillProvider, useQuill, ChartEditor, ReportBuilder, } from '@quillsql/react';
5
4
  import prismTheme from 'prism-react-renderer/themes/nightOwlLight';
6
5
  import Highlight, { defaultProps } from 'prism-react-renderer';
7
- import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, MeasuringStrategy, TouchSensor, } from '@dnd-kit/core';
8
- import InputLabel from './components/InputLabel';
9
- import CardSection from './components/CardSection';
10
- import { arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy, useSortable, defaultAnimateLayoutChanges, } from '@dnd-kit/sortable';
11
- import { CSS } from '@dnd-kit/utilities';
12
- import { OrgSelect, DashboardManager } from './components';
6
+ import { DashboardManager } from './components';
13
7
  import { AdminProvider, useAdmin } from './AdminProvider';
14
- import { ButtonPrimitive, HeaderPrimitive, ModalPrimitive, SecondaryButtonPrimitive, SelectPrimitive, TextInputPrimitive, } from './primitives';
8
+ import { HeaderPrimitive, ModalPrimitive, SelectPrimitive, TextInputPrimitive, } from './primitives';
9
+ import { MemoizedButton, MemoizedSecondaryButton, } from './components/UiComponents';
15
10
  import DashboardBuilder from './public_components/DashboardBuilder';
16
11
  import SQLViewManager from './public_components/SQLViewManager';
17
- import { InitialDateRangeOptions, QUILL_SERVER, defaultDateRange, } from './utils/constants';
18
- import TogglePrimitive from './primitives/TogglePrimitive';
12
+ import { QUILL_SERVER } from './utils/constants';
13
+ import { MemoizedModal } from './components/UiComponents';
14
+ import { SQLEditor } from '@quillsql/react';
15
+ import { hasColumnAlias } from './utils/table';
19
16
  // chartColors: ["#6269E9", "#E14F62"],
20
- const defaultTheme = {
17
+ export const defaultTheme = {
21
18
  fontFamily: 'Inter; Helvetica',
22
19
  backgroundColor: '#FFFFFF',
23
20
  primaryTextColor: '#364153',
@@ -25,392 +22,23 @@ const defaultTheme = {
25
22
  chartLabelFontFamily: 'Inter; Helvetica',
26
23
  chartLabelColor: '#666666',
27
24
  chartTickColor: '#CCCCCC',
25
+ chartColors: ['#6269E9', '#E14F62', '#55B5A6', '#E9A23B', '#D0ACCF'],
28
26
  borderColor: '#E5E7EB',
29
27
  primaryButtonColor: '#364153',
30
28
  borderWidth: 1,
31
- labelFontWeight: '500',
29
+ labelFontWeight: 500,
32
30
  fontSize: 14,
33
31
  };
34
- export function EditFiltersModal({ isOpen, dashboardData, selectedDashboard, client, setIsOpen, onSave, ModalComponent, TextInputComponent, ButtonComponent, HeaderComponent, SelectComponent, dashNames, setSelectedEditDashboard, SecondaryButtonComponent, openAddFilterModal, openEditOrderModal, }) {
35
- const { state, dispatch } = useAdmin();
36
- const [selectedDashboardName, setSelectedDashboardName] = useState(selectedDashboard);
37
- useEffect(() => {
38
- setSelectedDashboardName(selectedDashboard);
39
- }, [selectedDashboard]);
40
- const { data } = useDashboard(selectedDashboard);
41
- const [isDateComparison, setIsDateComparison] = useState(false);
42
- const [newFilters, setNewFilters] = useState([]);
43
- const [initialRange, setInitialRange] = useState(defaultDateRange);
44
- const [showDateFilter, setShowDateFilter] = useState(true);
45
- const [newDateFilter, setNewDateFilter] = useState(null);
46
- const [selectedTable, setSelectedTable] = useState(null);
47
- const [field, setField] = useState('');
48
- useEffect(() => {
49
- if (data && data.dateFilter) {
50
- setIsDateComparison(data.dateFilter.comparison);
51
- dispatch('SET_DATE_FILTER', data.dateFilter);
52
- }
53
- }, [data]);
54
- useEffect(() => {
55
- setIsDateComparison(!!state.dateFilter?.comparison ?? false);
56
- }, [state.dateFilter]);
57
- useEffect(() => {
58
- if (state.tables?.length) {
59
- const defaultTable = state.tables[0];
60
- const name = state.editDashboardData?.filters[0]?.table;
61
- const table = state.tables.find((t) => t.name === name) ?? defaultTable;
62
- setSelectedTable(table);
63
- setField(table.columns.map((elem) => elem.name)[0]);
64
- }
65
- }, [state.tables, state.editDashboardData]);
66
- useEffect(() => {
67
- if (dashboardData && dashboardData.filters) {
68
- setNewFilters(dashboardData.filters);
69
- }
70
- if (dashboardData && dashboardData.dateFilter) {
71
- setNewDateFilter(dashboardData.dateFilter);
72
- }
73
- }, [dashboardData]);
74
- const handleAddFilter = async () => {
75
- setNewFilters([...newFilters, { label: '' }]);
76
- };
77
- const handleSubmitDashboardChanges = async () => {
78
- if (!selectedDashboardName ||
79
- newFilters.some((filter) => !filter.label) ||
80
- (newDateFilter &&
81
- Object.keys(newDateFilter).length &&
82
- !newDateFilter.label)) {
83
- alert('Empty fields');
84
- return;
85
- }
86
- if (newFilters.filter((elem) => !elem.field).length) {
87
- alert(`no filter field for: ${newFilters.filter((elem) => !elem.field)[0].label}`);
88
- return;
89
- }
90
- const updatedFilters = newFilters.map((filter) => {
91
- const table = state.tables.find((table) => table.name === filter.table);
92
- const filterType = getPostgresBasicType(table.columns.find((col) => col.name === filter.field));
93
- return {
94
- table: filter.table,
95
- field: filter.field,
96
- labelField: filter.field,
97
- label: filter.label,
98
- filterType,
99
- };
100
- });
101
- if (dashNames &&
102
- dashNames.length > 0 &&
103
- dashNames.some((dashName) => dashName.name === selectedDashboardName &&
104
- selectedDashboardName !== selectedDashboard)) {
105
- alert('Dashboard name already taken!');
106
- return;
107
- }
108
- const fieldsSet = new Set();
109
- const hasDuplicateField = updatedFilters.some((filter) => {
110
- if (fieldsSet.has(filter.field)) {
111
- return true;
112
- }
113
- else {
114
- fieldsSet.add(filter.field);
115
- return false;
116
- }
117
- });
118
- if (hasDuplicateField ||
119
- (newDateFilter && Object.keys(newDateFilter).length > 0 &&
120
- updatedFilters.some((filter) => filter.filterType === 'date'))) {
121
- alert('Maximum of one filter per field');
122
- return;
123
- }
124
- let allValid = true;
125
- updatedFilters.forEach((filter) => {
126
- if (filter.filterType !== 'string' && filter.filterType !== 'date') {
127
- allValid = false;
128
- console.error(`Invalid filterType found: ${filter.filterType}`);
129
- }
130
- });
131
- if (!allValid) {
132
- alert('We only support string and filters.');
133
- return;
134
- }
135
- const url = `${QUILL_SERVER}/dashfilter/${client._id}/`;
136
- const body = {
137
- newDashboardName: selectedDashboardName,
138
- filters: updatedFilters,
139
- dateFilter: newDateFilter
140
- ? {
141
- ...newDateFilter,
142
- comparison: isDateComparison,
143
- primaryRange: initialRange,
144
- }
145
- : null,
146
- name: selectedDashboard,
147
- databaseType: state.client.databaseType,
148
- };
149
- dispatch({ type: 'SET_DATE_FILTER', payload: body.dateFilter });
150
- const headers = {
151
- 'Content-Type': 'application/json',
152
- Authorization: `Bearer `,
153
- };
154
- try {
155
- const response = await fetch(url, {
156
- method: 'POST',
157
- headers: headers,
158
- body: JSON.stringify(body),
159
- });
160
- await onSave();
161
- setSelectedEditDashboard(null);
162
- setIsOpen(false);
163
- }
164
- catch (e) {
165
- console.log('error');
166
- }
167
- };
168
- const handleDeleteFilter = (filter) => {
169
- setNewFilters(newFilters.filter((f) => f !== filter));
170
- };
171
- const handleDeleteDateFilter = async () => {
172
- setShowDateFilter(false);
173
- setNewDateFilter(null);
174
- };
175
- const handleAddDateFilter = async () => {
176
- setShowDateFilter(true);
177
- if (dashboardData && dashboardData.dateFilter) {
178
- setNewDateFilter(dashboardData.dateFilter);
179
- }
180
- };
181
- const handleDeleteDashboard = async () => {
182
- if (confirm('Are you sure? This action cannot be undone.')) {
183
- const URL = `${QUILL_SERVER}/dashboard/${selectedDashboard}`;
184
- await fetch(URL, {
185
- method: 'DELETE',
186
- headers: { 'Content-Type': 'application/json' },
187
- body: JSON.stringify({
188
- clientId: client._id,
189
- databaseType: state.client.databaseType,
190
- }),
191
- });
192
- setIsOpen(false);
193
- setNewFilters([]);
194
- await onSave();
195
- }
196
- };
197
- return (_jsx(ModalComponent, { isOpen: isOpen, close: () => {
198
- setIsOpen(false);
199
- setNewFilters([]);
200
- setIsDateComparison(state.dateFilter?.comparison ?? false);
201
- }, style: {
202
- minWidth: '814px',
203
- maxWidth: '814px',
204
- }, children: _jsxs("div", { style: {
205
- display: 'flex',
206
- gap: 16,
207
- flexDirection: 'column',
208
- width: '100%',
209
- height: '100%',
210
- maxHeight: '100%',
211
- overflowY: 'auto',
212
- }, children: [_jsx(HeaderComponent, { label: "Manage dashboard" }), _jsxs("div", { children: [_jsx(InputLabel, { children: "Name" }), _jsx("div", { style: { maxWidth: 230 }, children: _jsx(TextInputComponent, { value: selectedDashboardName, onChange: (e) => setSelectedDashboardName(e.target.value) }) })] }), _jsxs("div", { children: [_jsxs("div", { style: {
213
- display: 'flex',
214
- flexDirection: 'column',
215
- gap: '10px',
216
- }, children: [_jsx(CardSection, { children: "Date Filter" }), showDateFilter && (_jsx(_Fragment, { children: _jsxs("div", { style: {
217
- display: 'flex',
218
- flexDirection: 'row',
219
- gap: '10px',
220
- }, children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [_jsx(InputLabel, { children: "Label" }), _jsx("div", { style: {
221
- display: 'flex',
222
- flexDirection: 'row',
223
- alignItems: 'center',
224
- }, children: _jsx(TextInputComponent, { value: newDateFilter?.label, onChange: (e) => {
225
- setNewDateFilter({
226
- ...newDateFilter,
227
- label: e.target.value,
228
- });
229
- } }) })] }), _jsx("div", { style: {
230
- display: 'flex',
231
- flexDirection: 'row',
232
- gap: '10px',
233
- }, children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [_jsx(InputLabel, { children: "Initial Range" }), _jsx(SelectComponent, { value: initialRange.label, onChange: (e) => {
234
- setInitialRange(InitialDateRangeOptions.find((table) => table.label === e) ?? initialRange);
235
- }, options: InitialDateRangeOptions.map((table) => {
236
- return { label: table.label, value: table.label };
237
- }) })] }) }), _jsx("div", { style: {
238
- display: 'flex',
239
- flexDirection: 'row',
240
- gap: '10px',
241
- }, children: _jsxs("div", { style: {
242
- display: 'flex',
243
- flexDirection: 'column',
244
- }, children: [_jsx(InputLabel, { children: "Date Comparison" }), _jsx("div", { style: {
245
- display: 'flex',
246
- flexDirection: 'column',
247
- justifyContent: 'center',
248
- height: '100%',
249
- minWidth: 200,
250
- maxWidth: 200,
251
- width: 200,
252
- }, children: _jsx(TogglePrimitive, { value: isDateComparison, onClick: () => {
253
- setIsDateComparison((isDateComparison) => !isDateComparison);
254
- } }) })] }) }), _jsx("div", { style: {
255
- display: 'flex',
256
- flexGrow: 1,
257
- flexDirection: 'row',
258
- alignItems: 'end',
259
- justifyContent: 'end',
260
- gap: '10px',
261
- }, children: _jsx("div", { style: {
262
- display: 'flex',
263
- flexDirection: 'column',
264
- justifyContent: 'center',
265
- }, children: _jsx("div", { onClick: () => handleDeleteDateFilter(), style: {
266
- height: 38,
267
- width: 42,
268
- alignItems: 'center',
269
- justifyContent: 'center',
270
- display: 'flex',
271
- cursor: 'pointer',
272
- }, children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#4C5462", width: "20", height: "20", children: _jsx("path", { fillRule: "evenodd", d: "M5.47 5.47a.75.75 0 011.06 0L12 10.94l5.47-5.47a.75.75 0 111.06 1.06L13.06 12l5.47 5.47a.75.75 0 11-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 01-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 010-1.06z", clipRule: "evenodd" }) }) }) }) })] }) })), !showDateFilter && (_jsx("div", { style: { maxWidth: 230 }, children: _jsx(SecondaryButtonComponent, { onClick: handleAddDateFilter, label: "Add date filter +" }) }))] }), _jsx("div", { style: {
273
- display: 'flex',
274
- flexDirection: 'row',
275
- alignItems: 'center',
276
- justifyContent: 'space-between',
277
- marginTop: 20,
278
- }, children: _jsx(CardSection, { children: "Filters" }) }), newFilters.length > 0 && (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '6px' }, children: newFilters.map((filter, index) => {
279
- return (_jsxs("div", { style: {
280
- display: 'flex',
281
- flexDirection: 'row',
282
- gap: '10px',
283
- }, children: [_jsxs("div", { style: {
284
- display: 'flex',
285
- flexDirection: 'column',
286
- maxWidth: 300,
287
- }, children: [index === 0 && _jsx(InputLabel, { children: "Label" }), _jsx(TextInputComponent, { value: filter.label, onChange: (e) => {
288
- const updatedFilters = newFilters.map((otherFilter, i) => index === i
289
- ? { ...otherFilter, label: e.target.value }
290
- : otherFilter);
291
- setNewFilters(updatedFilters);
292
- }, width: "230px" })] }), _jsxs("div", { style: {
293
- display: 'flex',
294
- flexDirection: 'column',
295
- maxWidth: 300,
296
- }, children: [index === 0 && _jsx(InputLabel, { children: "Table" }), _jsx(SelectComponent, { defaultValue: "", value: filter.table, onChange: (e) => {
297
- const updatedFilters = newFilters.map((otherFilter, i) => index === i
298
- ? { ...otherFilter, table: e }
299
- : otherFilter);
300
- setNewFilters(updatedFilters);
301
- }, options: [
302
- { label: 'Select', value: '' },
303
- ...state.tables.map((table) => {
304
- return { label: table.name, value: table.name };
305
- }),
306
- ,
307
- ] })] }), _jsxs("div", { style: {
308
- display: 'flex',
309
- flexDirection: 'column',
310
- maxWidth: 300,
311
- }, children: [index === 0 && _jsx(InputLabel, { children: "Field" }), _jsx("div", { style: {
312
- display: 'flex',
313
- flexDirection: 'column',
314
- alignItems: 'center',
315
- }, children: _jsxs("div", { style: {
316
- display: 'flex',
317
- flexDirection: 'row',
318
- alignItems: 'center',
319
- }, children: [_jsx(SelectComponent, { defaultValue: "", value: filter && filter.field ? filter.field : '', options: state.tables
320
- .find((table) => table.name === filter.table)
321
- ?.columns.map((column) => {
322
- return {
323
- label: column.name,
324
- value: column.name,
325
- };
326
- }), onChange: (e) => {
327
- const updatedFilters = newFilters.map((otherFilter, i) => index === i
328
- ? { ...otherFilter, field: e }
329
- : otherFilter);
330
- setNewFilters(updatedFilters);
331
- } }), _jsx("div", { onClick: () => handleDeleteFilter(filter), style: {
332
- height: 38,
333
- width: 42,
334
- alignItems: 'center',
335
- justifyContent: 'center',
336
- display: 'flex',
337
- cursor: 'pointer',
338
- }, children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#4C5462", width: "20", height: "20", children: _jsx("path", { fillRule: "evenodd", d: "M5.47 5.47a.75.75 0 011.06 0L12 10.94l5.47-5.47a.75.75 0 111.06 1.06L13.06 12l5.47 5.47a.75.75 0 11-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 01-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 010-1.06z", clipRule: "evenodd" }) }) })] }) })] })] }, index));
339
- }) })), _jsx("div", { style: { height: 12 } }), _jsx(SecondaryButtonComponent, { onClick: handleAddFilter, label: "Add filter +" })] }), _jsx(CardSection, { children: "Chart order" }), _jsx("div", { style: { maxWidth: 230 }, children: _jsx(SecondaryButtonComponent, { onClick: () => openEditOrderModal(selectedDashboardName), label: "Edit chart order" }) }), _jsx(CardSection, { children: "Danger Zone" }), _jsx("div", { style: { maxWidth: 230 }, children: _jsx(SecondaryButtonComponent, { onClick: handleDeleteDashboard, label: "Delete Dashboard" }) }), _jsx("div", { style: { height: 18 } }), _jsx("div", { style: { maxWidth: 230 }, children: _jsx(ButtonComponent, { onClick: handleSubmitDashboardChanges, label: "Save changes" }) })] }) }));
340
- }
341
- export function AddFilterModal({ isOpen, selectedDashboard, client, setIsOpen, ModalComponent, TextInputComponent, SelectComponent, HeaderComponent, ButtonComponent, openAddDashboardModal, }) {
342
- const [selectedTable, setSelectedTable] = useState(null);
343
- const [name, setName] = useState('');
344
- const [field, setField] = useState('');
345
- const [filterType, setFilterType] = useState('string');
346
- const [dateRange, setDateRange] = useState([new Date(), new Date()]);
347
- const { state, dispatch } = useAdmin();
348
- useEffect(() => {
349
- if (state.tables?.length) {
350
- setSelectedTable(state.tables[0]);
351
- // setField(tables[0].columns.map((elem) => elem.name));
352
- setField(state.tables[0].columns[0].name);
353
- }
354
- }, [state.tables]);
355
- const handleAddFilter = async () => {
356
- if (!selectedTable || !field) {
357
- return;
358
- }
359
- const filterType = getPostgresBasicType(selectedTable.columns.find((col) => col.name === field));
360
- if (filterType !== 'string' && filterType !== 'date') {
361
- alert('We only support string and filters.');
362
- return;
363
- }
364
- let responseData;
365
- const url = `${QUILL_SERVER}/dashfilter/${client._id}/`;
366
- const body = {
367
- name: selectedDashboard,
368
- filter: {
369
- table: selectedTable.name,
370
- field: field,
371
- labelField: field,
372
- label: name,
373
- filterType,
374
- },
375
- };
376
- const headers = {
377
- 'Content-Type': 'application/json',
378
- Authorization: `Bearer `,
379
- };
380
- try {
381
- const response = await fetch(url, {
382
- method: 'POST',
383
- headers: headers,
384
- body: JSON.stringify(body),
385
- });
386
- if (!response.ok) {
387
- throw new Error(`HTTP error! Status: ${response.status}`);
388
- }
389
- responseData = await response.json();
390
- }
391
- catch (error) {
392
- console.error('There was a problem with the fetch operation:', error);
393
- }
394
- if (responseData) {
395
- setIsOpen(false);
396
- setName('');
397
- setField('');
398
- return;
399
- }
400
- };
401
- if (!selectedTable) {
402
- return null;
403
- }
404
- return (_jsx(ModalComponent, { isOpen: isOpen, close: () => setIsOpen(false), children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [_jsx(HeaderComponent, { label: "Add filter" }), _jsx("div", { children: "Label" }), _jsx(TextInputComponent, { value: name, onChange: (e) => setName(e.target.value) }), _jsx("div", { children: "Table" }), _jsx(SelectComponent, { defaultValue: "", value: selectedTable ? selectedTable : '', onChange: (e) => setSelectedTable(e.target.value), QuillOptions: state.tables.map((table) => {
405
- return { label: table.name, value: table.name };
406
- }) }), _jsx("div", { children: "Field" }), _jsx(SelectComponent, { defaultValue: "", value: field ? field : '', QuillOptions: selectedTable.columns.map((column) => {
407
- return { label: column.name, value: column.name };
408
- }), onChange: (e) => {
409
- setField(e);
410
- } }), _jsx(ButtonComponent, { label: "Add filter", onClick: handleAddFilter })] }) }));
411
- }
412
- export default function Portal({ publicKey, queryEndpoint, theme = defaultTheme, queryHeaders, withCredentials, environment, organizationId, TextInputComponent, ButtonComponent, SecondaryButtonComponent, ModalComponent, SelectComponent, OrganizationSelectComponent, UserManagementComponent, HeaderComponent, }) {
413
- return (_jsx(AdminProvider, { publicKey: publicKey, children: _jsx(Navigation, { theme: theme, publicKey: publicKey, queryEndpoint: queryEndpoint, queryHeaders: queryHeaders, withCredentials: withCredentials, TextInputComponent: TextInputComponent || TextInputPrimitive, ButtonComponent: ButtonComponent || ButtonPrimitive, HeaderComponent: HeaderComponent || HeaderPrimitive, SecondaryButtonComponent: SecondaryButtonComponent || SecondaryButtonPrimitive, ModalComponent: ModalComponent || ModalPrimitive, environment: environment, OrganizationSelectComponent: OrganizationSelectComponent, UserManagementComponent: UserManagementComponent, SelectComponent: SelectComponent || SelectPrimitive }) }));
32
+ export default function Portal({ publicKey, queryEndpoint, theme = defaultTheme, queryHeaders, withCredentials, environment, organizationId, TextInputComponent, ButtonComponent = MemoizedButton, SecondaryButtonComponent = MemoizedSecondaryButton, ModalComponent, SelectComponent, OrganizationSelectComponent, UserManagementComponent, HeaderComponent, }) {
33
+ return (_jsx(AdminProvider, { publicKey: publicKey, children: _jsx(Navigation, { theme: theme, publicKey: publicKey, queryEndpoint: queryEndpoint, queryHeaders: queryHeaders, withCredentials: withCredentials,
34
+ // @ts-ignore
35
+ TextInputComponent: TextInputComponent || TextInputPrimitive, ButtonComponent: ButtonComponent,
36
+ // @ts-ignore
37
+ HeaderComponent: HeaderComponent || HeaderPrimitive, SecondaryButtonComponent: SecondaryButtonComponent,
38
+ // @ts-ignore
39
+ ModalComponent: ModalComponent || ModalPrimitive, environment: environment, OrganizationSelectComponent: OrganizationSelectComponent, UserManagementComponent: UserManagementComponent,
40
+ // @ts-ignore
41
+ SelectComponent: SelectComponent || SelectPrimitive }) }));
414
42
  }
415
43
  function Navigation({ TextInputComponent, ButtonComponent, SecondaryButtonComponent, ModalComponent, SelectComponent, OrganizationSelectComponent, UserManagementComponent, HeaderComponent, publicKey, queryEndpoint, queryHeaders, environment, withCredentials, }) {
416
44
  const { state, dispatch } = useAdmin();
@@ -424,15 +52,21 @@ function Navigation({ TextInputComponent, ButtonComponent, SecondaryButtonCompon
424
52
  const renderComponentBasedOnName = () => {
425
53
  switch (state.activeComponent) {
426
54
  case 'Dashboards':
427
- return (_jsx(DashboardManager, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, HeaderComponent: HeaderComponent, setReportId: (id) => dispatch({ type: 'SET_REPORT_ID', payload: id }), queryEndpoint: queryEndpoint, queryHeaders: queryHeaders, withCredentials: withCredentials }));
55
+ return (_jsx(DashboardManager
56
+ // @ts-ignore
57
+ , {
58
+ // @ts-ignore
59
+ TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, HeaderComponent: HeaderComponent, setReportId: (id) => dispatch({ type: 'SET_REPORT_ID', payload: id }), queryEndpoint: queryEndpoint, queryHeaders: queryHeaders, withCredentials: withCredentials }));
428
60
  case 'SQL editor':
429
61
  return _jsx(DashboardBuilder, {});
430
- case 'Report':
431
- return (_jsx(ReportWrapper, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, OrganizationSelectComponent: OrganizationSelectComponent, organizationId: state.organizationId, queryEndpoint: queryEndpoint, queryHeaders: queryHeaders, withCredentials: withCredentials }));
432
62
  case 'SQL views':
433
63
  return _jsx(SQLViewManager, {});
434
64
  default:
435
- return (_jsx(Dashboards, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, OrganizationSelectComponent: OrganizationSelectComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, HeaderComponent: HeaderComponent, setReportId: (id) => dispatch({ type: 'SET_REPORT_ID', payload: id }), queryEndpoint: queryEndpoint, organizationId: state.organizationId, queryHeaders: queryHeaders, withCredentials: withCredentials }));
65
+ return (_jsx(DashboardManager
66
+ // @ts-ignore
67
+ , {
68
+ // @ts-ignore
69
+ TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, HeaderComponent: HeaderComponent, setReportId: (id) => dispatch({ type: 'SET_REPORT_ID', payload: id }), queryEndpoint: queryEndpoint, queryHeaders: queryHeaders, withCredentials: withCredentials }));
436
70
  }
437
71
  };
438
72
  return (_jsxs("div", { style: {
@@ -533,7 +167,7 @@ function Navigation({ TextInputComponent, ButtonComponent, SecondaryButtonCompon
533
167
  , {
534
168
  // organizationId={'2'}
535
169
  // publicKey={client?._id}
536
- organizationId: state.organizationId, queryEndpoint: queryEndpoint, withCredentials: withCredentials, queryHeaders: queryHeaders, publicKey: state.client._id, environment: state.environment, theme: theme, children: renderComponentBasedOnName() }) })] }));
170
+ organizationId: state.organizationId, queryEndpoint: queryEndpoint || '', withCredentials: withCredentials, queryHeaders: queryHeaders || {}, publicKey: state.client._id, environment: state.environment, theme: theme, children: renderComponentBasedOnName() }) })] }));
537
171
  }
538
172
  export const theme = {
539
173
  fontFamily: 'Inter; Helvetica',
@@ -629,172 +263,7 @@ export function getPostgresBasicType(column) {
629
263
  }
630
264
  return format;
631
265
  }
632
- export function classNames(...classes) {
633
- return classes.filter(Boolean).join(' ');
634
- }
635
- export function AddDashboardModal({ selectedDashboard, isOpen, setIsOpen, client, ModalComponent, TextInputComponent, SelectComponent, HeaderComponent, ButtonComponent, dashNames, getDashNames, organizationId, }) {
636
- const { state, dispatch } = useAdmin();
637
- const [selectedDashboardName, setSelectedDashboardName] = useState(selectedDashboard?.name);
638
- // const [tables] = useContext(TablesContext);
639
- const [selectedTable, setSelectedTable] = useState(null);
640
- const [name, setName] = useState('');
641
- const [field, setField] = useState('');
642
- const [filterType, setFilterType] = useState('string');
643
- const [dateRange, setDateRange] = useState([new Date(), new Date()]);
644
- const [newFilters, setNewFilters] = useState([]);
645
- const [newDateFilter, setNewDateFilter] = useState(null);
646
- useEffect(() => {
647
- if (state.tables?.length) {
648
- setSelectedTable(state.tables[0]);
649
- // setField(tables[0].columns.map((elem) => elem.name));
650
- setField(state.tables[0].columns[0].name);
651
- }
652
- }, [state.tables]);
653
- const handleDeleteFilter = async (filter) => {
654
- setNewFilters(newFilters.filter((f) => f !== filter));
655
- };
656
- const handleAddDashboardSubmit = async () => {
657
- if (!selectedDashboardName ||
658
- newFilters.some((filter) => !filter.label) ||
659
- (newDateFilter && newDateFilter.label)) {
660
- alert('Empty labels');
661
- return;
662
- }
663
- if (newFilters.some((filter) => !filter.field)) {
664
- alert('Empty fields');
665
- return;
666
- }
667
- if (!selectedTable || !field) {
668
- return;
669
- }
670
- if (dashNames &&
671
- dashNames.length > 0 &&
672
- dashNames.some((dashName) => dashName.name === selectedDashboardName)) {
673
- alert('Dashboard name already taken!');
674
- return;
675
- }
676
- let updatedFilters = newFilters.map((filter) => {
677
- const filterType = getPostgresBasicType(selectedTable.columns.find((col) => col.name === filter.field));
678
- return {
679
- table: selectedTable.name,
680
- field: filter.field,
681
- labelField: filter.field,
682
- label: filter.label,
683
- filterType,
684
- };
685
- });
686
- const fieldsSet = new Set();
687
- const hasDuplicateField = updatedFilters.some((filter) => {
688
- if (fieldsSet.has(filter.field)) {
689
- return true;
690
- }
691
- else {
692
- fieldsSet.add(filter.field);
693
- return false;
694
- }
695
- });
696
- if (hasDuplicateField) {
697
- alert('Maximum of one filter per field');
698
- return;
699
- }
700
- let allValid = true;
701
- updatedFilters.forEach((filter) => {
702
- if (filter.filterType !== 'string' && filter.filterType !== 'date') {
703
- allValid = false;
704
- console.error(`Invalid filterType found: ${filter.filterType}`);
705
- }
706
- });
707
- if (!allValid) {
708
- alert('We only support string and filters.');
709
- return;
710
- }
711
- if (updatedFilters.filter((filter) => filter.filterType === 'date').length > 1) {
712
- alert('More than one date filter');
713
- return;
714
- }
715
- let responseData;
716
- const url = `${QUILL_SERVER}/newdash/${client._id}/`;
717
- const body = newDateFilter && Object.keys(newDateFilter).length
718
- ? {
719
- dateFilter: newDateFilter,
720
- newDashboardName: selectedDashboardName,
721
- filters: updatedFilters,
722
- organizationId,
723
- }
724
- : {
725
- newDashboardName: selectedDashboardName,
726
- filters: updatedFilters,
727
- organizationId,
728
- };
729
- const headers = {
730
- 'Content-Type': 'application/json',
731
- Authorization: `Bearer `,
732
- };
733
- try {
734
- const response = await fetch(url, {
735
- method: 'POST',
736
- headers: headers,
737
- body: JSON.stringify(body),
738
- });
739
- if (!response.ok) {
740
- throw new Error(`HTTP error! Status: ${response.status}`);
741
- }
742
- responseData = await response.json();
743
- }
744
- catch (e) {
745
- console.log('error');
746
- }
747
- if (responseData) {
748
- setIsOpen(false);
749
- setName('');
750
- setSelectedDashboardName('');
751
- setNewFilters([]);
752
- setNewDateFilter(null);
753
- getDashNames();
754
- return;
755
- }
756
- };
757
- if (!selectedTable) {
758
- return _jsx(_Fragment, {});
759
- }
760
- const handleAddFilter = async () => {
761
- setNewFilters([...newFilters, { label: '', field }]);
762
- };
763
- return (_jsx(ModalComponent, { isOpen: isOpen, close: () => setIsOpen(false), children: _jsxs("div", { children: [_jsx(TextInputComponent, { placeholder: "Enter Dashboard Name...", onChange: (e) => setSelectedDashboardName(e.target.value), value: selectedDashboardName }), _jsxs("div", { style: {
764
- display: 'flex',
765
- flexDirection: 'column',
766
- alignItems: 'center',
767
- }, children: [newFilters.map((filter, index) => {
768
- return (_jsxs("div", { style: { display: 'flex', flexDirection: 'row' }, children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [_jsx("h2", { children: "Label" }), _jsx(TextInputComponent, { value: filter.label, onChange: (e) => {
769
- const updatedFilters = newFilters.map((otherFilter, i) => index === i
770
- ? { ...otherFilter, label: e.target.value }
771
- : otherFilter);
772
- setNewFilters(updatedFilters);
773
- } })] }), _jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [_jsx("h4", { children: "Field" }), _jsx("div", { style: {
774
- display: 'flex',
775
- flexDirection: 'column',
776
- alignItems: 'center',
777
- }, children: _jsxs("div", { style: {
778
- display: 'flex',
779
- flexDirection: 'row',
780
- alignItems: 'center',
781
- }, children: [_jsx(SelectComponent, { defaultValue: "", value: filter && filter.field ? filter.field : '', QuillOptions: selectedTable.columns.map((column) => {
782
- return { label: column.name, value: column.name };
783
- }), onChange: (e) => {
784
- const updatedFilters = newFilters.map((otherFilter, i) => index === i
785
- ? { ...otherFilter, field: e }
786
- : otherFilter);
787
- setNewFilters(updatedFilters);
788
- } }), _jsx("div", { onClick: () => handleDeleteFilter(filter), style: {
789
- height: 38,
790
- width: 42,
791
- alignItems: 'center',
792
- justifyContent: 'center',
793
- display: 'flex',
794
- }, children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#4C5462", width: "20", height: "20", children: _jsx("path", { fillRule: "evenodd", d: "M5.47 5.47a.75.75 0 011.06 0L12 10.94l5.47-5.47a.75.75 0 111.06 1.06L13.06 12l5.47 5.47a.75.75 0 11-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 01-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 010-1.06z", clipRule: "evenodd" }) }) })] }) })] })] }, filter.field + index));
795
- }), _jsx(ButtonComponent, { onClick: handleAddFilter, label: "Add new filter +" }), _jsx(ButtonComponent, { onClick: handleAddDashboardSubmit, label: "Add Dashboard +" })] })] }) }));
796
- }
797
- export function TableCell({ table, clickTableCell }) {
266
+ export function TableCell({ table, clickTableCell, }) {
798
267
  const handleClickTableCell = () => {
799
268
  clickTableCell(table);
800
269
  };
@@ -816,272 +285,201 @@ export function TableCell({ table, clickTableCell }) {
816
285
  // height: "1.3em",
817
286
  }, children: tokens.map((line, i) => (_jsx("div", { ...getLineProps({ line, key: i }), children: line.map((token, key) => (_jsx("span", { ...getTokenProps({ token, key }) }, key))) }, i))) })) })] }, table._id));
818
287
  }
819
- const SchemaListComponent = ({ schema, theme }) => {
820
- return (_jsx("div", { style: {
821
- background: theme.backgroundColor,
822
- maxHeight: 700,
823
- width: 300,
824
- minWidth: 300,
825
- overflowY: 'scroll',
826
- // maxHeight: "100%",
827
- paddingLeft: 20,
828
- paddingRight: 20,
829
- }, children: schema.map((elem, index) => (_jsx(SchemaItem, { elem: elem, theme: theme, index: index }, elem.displayName + index))) }));
288
+ const FakeModal = ({ children }) => (_jsx("div", { style: { height: '100%' }, children: children }));
289
+ const FakeSQLEditorModal = ({ children, isOpen, }) => {
290
+ if (!isOpen)
291
+ return null;
292
+ return _jsx("div", { style: { height: '100%' }, children: children });
830
293
  };
831
- function SchemaItem({ elem, theme, index }) {
832
- const [isOpen, setIsOpen] = useState(index === 0);
833
- const schemaContainerStyle = {
834
- display: 'flex',
835
- flexDirection: 'column',
836
- // WebkitTouchCallout: "none",
837
- // WebkitUserSelect: "none",
838
- // KhtmlUserSelect: "none",
839
- // MozUserSelect: "none",
840
- // msUserSelect: "none",
841
- // userSelect: "none",
842
- };
843
- const schemaRowStyle = {
844
- display: 'flex',
845
- flexDirection: 'row',
846
- alignItems: 'center',
847
- width: '100%',
848
- justifyContent: 'space-between',
849
- cursor: 'pointer',
850
- };
851
- const schemaRowHoverStyle = {
852
- background: theme.selectUnderlayColor,
853
- };
854
- return (_jsxs("div", { style: schemaContainerStyle, children: [_jsxs("div", { style: { ...schemaRowStyle, ...(isOpen && schemaRowHoverStyle) }, onClick: () => setIsOpen(!isOpen), children: [_jsx("p", { style: {
855
- marginLeft: theme.padding,
856
- fontSize: theme.fontSize,
857
- color: '#384151',
858
- fontWeight: '500',
859
- }, children: elem.displayName }), _jsx("div", { style: {
860
- display: 'flex',
861
- alignItems: 'center',
862
- justifyContent: 'center',
863
- // paddingRight: 25,
864
- paddingTop: 20,
865
- paddingBottom: 20,
866
- paddingLeft: 0,
867
- cursor: 'pointer',
868
- }, children: isOpen ? (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "h-5 w-5 text-gray-400", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19.5 8.25l-7.5 7.5-7.5-7.5" }) })) : (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "h-5 w-5", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" }) })) })] }), isOpen ? (_jsx("div", { style: {
869
- paddingBottom: theme.padding,
870
- display: 'flex',
871
- flexDirection: 'column',
872
- paddingLeft: theme.padding,
873
- paddingRight: theme.padding,
874
- }, children: elem.columns.map((elem, index) => (_jsxs("div", { style: {
875
- paddingTop: theme.padding,
876
- display: 'flex',
877
- flexDirection: 'row',
878
- alignItems: 'center',
879
- justifyContent: 'space-between',
880
- }, children: [_jsx("div", { title: elem.displayName, className: "text-gray-500", style: {
881
- fontSize: 13,
882
- // color: theme.secondaryFontColor,
883
- whiteSpace: 'nowrap',
884
- padding: 0,
885
- margin: 0,
886
- textOverflow: 'ellipsis',
887
- overflow: 'hidden',
888
- width: 200,
889
- maxWidth: 200,
890
- }, children: elem.displayName }), _jsx("div", { className: "text-gray-500", title: elem.displayName, style: {
891
- fontSize: 13,
892
- color: theme.secondaryFontColor,
893
- padding: 0,
894
- margin: 0,
895
- }, children: elem.fieldType })] }, elem.displayName + elem.index))) })) : null] }));
896
- }
897
- export function defineEditorTheme(monaco, theme) {
898
- monaco.editor.defineTheme('onedark', {
899
- base: theme.darkMode ? 'vs-dark' : 'vs',
900
- inherit: true,
901
- rules: [
902
- {
903
- token: 'comment',
904
- foreground: '#5d7988',
905
- fontStyle: 'italic',
906
- },
907
- { token: 'constant', foreground: '#e06c75' },
908
- ],
909
- colors: {
910
- 'editor.background': '#F9F9F9',
911
- },
912
- });
913
- }
914
- export function setEditorTheme(editor, monaco) {
915
- try {
916
- monaco.editor.setTheme('onedark');
917
- }
918
- catch (e) {
919
- console.log('ERROR: ', e);
920
- }
921
- }
922
- export function isValidDate(d) {
923
- return d instanceof Date && !isNaN(d);
924
- }
925
- export const isArrayOfValidDates = (arr, field) => arr.every((d) => new Date(d[field]) instanceof Date && !isNaN(new Date(d[field])));
926
- export function formatDateBuckets(startDate, endDate) {
927
- // Calculate the distance in hours
928
- const distanceInHours = Math.abs(differenceInHours(endDate, startDate));
929
- // Check if the distance is less than or equal to one hour
930
- if (distanceInHours <= 1) {
931
- return {
932
- unit: 'hour',
933
- format: 'h a',
934
- startOf: startOfHour,
935
- };
936
- }
937
- // Calculate the distance in days
938
- const distanceInDays = Math.abs(differenceInDays(endDate, startDate));
939
- // Check if the distance is less than or equal to one day
940
- if (distanceInDays <= 1) {
941
- return {
942
- unit: 'day',
943
- format: 'MMM d',
944
- startOf: startOfDay,
945
- };
946
- }
947
- // Calculate the distance in months
948
- const distanceInMonths = Math.abs(differenceInMonths(endDate, startDate));
949
- // Check if the distance is less than or equal to one month
950
- if (distanceInMonths <= 1) {
951
- return {
952
- unit: 'month',
953
- format: 'MMM yyyy',
954
- startOf: startOfMonth,
955
- };
956
- }
957
- // Calculate the distance in years
958
- const distanceInYears = Math.abs(differenceInYears(endDate, startDate));
959
- // Check if the distance is less than or equal to one year
960
- if (distanceInYears <= 1) {
961
- return {
962
- unit: 'year',
963
- format: 'yyyy',
964
- startOf: startOfYear,
965
- };
966
- }
967
- // Otherwise, the distance is more than one year
968
- return {
969
- unit: 'year',
970
- format: 'yyyy',
971
- startOf: startOfYear,
972
- };
973
- }
974
- const POSTGRES_DATE_TYPES = [
975
- 'timestamp',
976
- 'date',
977
- 'timestamptz',
978
- 'time',
979
- 'timetz',
980
- ];
981
- const FORMAT_QuillOptionS = [
982
- { value: 'whole_number', label: 'whole number' },
983
- { value: 'one_decimal_place', label: 'one decimal place' },
984
- { value: 'dollar_amount', label: 'dollar amount' },
985
- { value: 'MMM_yyyy', label: 'month' },
986
- { value: 'MMM_dd-MMM_dd', label: 'week' },
987
- { value: 'MMM_dd_yyyy', label: 'day' },
988
- { value: 'MMM_dd_hh:mm_ap_pm', label: 'day and time' },
989
- { value: 'hh_ap_pm', label: 'hour' },
990
- { value: 'percent', label: 'percent' },
991
- { value: 'string', label: 'string' },
992
- ];
993
- function Report({ reportId, saveDashboardItem, isOpen, setIsOpen, isEditQueryOpen, SecondaryButtonComponent, ButtonComponent, deleteReport, updateQuery, OrganizationSelectComponent, ModalComponent, NavigateToDashboardBuilder, }) {
994
- const { data, loading, error } = useQuill(reportId);
294
+ function QuillReport({ reportId, saveDashboardItem, isOpen, setIsOpen, isEditQueryOpen, SecondaryButtonComponent, ButtonComponent, deleteReport, handleSave, updateQuery, OrganizationSelectComponent, ModalComponent = MemoizedModal, NavigateToDashboardBuilder, }) {
995
295
  const { state, dispatch } = useAdmin();
996
- const goBack = () => {
997
- // setActiveComponent("Dashboards");
998
- dispatch({ type: 'SET_ACTIVE_COMPONENT', payload: 'Dashboards' });
296
+ const { data, loading, error } = useQuill(reportId);
297
+ const parentRef = useRef(null);
298
+ const [modalWidth, setModalWidth] = useState(200);
299
+ const [modalHeight, setModalHeight] = useState(200);
300
+ const [isOpenChartBuilder, setIsOpenChartBuilder] = useState(false);
301
+ const handleResize = useCallback(() => {
302
+ const screenSize = window.innerWidth;
303
+ const isEditQuery = state.activeQuery && state.activeEditItem;
304
+ if (isOpenChartBuilder && !isEditQuery && screenSize < 1200) {
305
+ setModalWidth(undefined); // use dynamic width of contents
306
+ }
307
+ else {
308
+ setModalWidth(window.innerWidth - 80);
309
+ }
310
+ setModalHeight(window.innerHeight - 80);
311
+ }, [isOpenChartBuilder, state.activeQuery, state.activeEditItem]);
312
+ useEffect(() => {
313
+ handleResize();
314
+ window.addEventListener('resize', handleResize);
315
+ return () => {
316
+ window.removeEventListener('resize', handleResize);
317
+ };
318
+ }, [handleResize]);
319
+ const handleSetIsOpen = (isOpen) => {
320
+ if (!isOpen) {
321
+ dispatch({
322
+ type: 'SET_ACTIVE_QUERY',
323
+ payload: '',
324
+ });
325
+ dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
326
+ }
327
+ setIsOpenChartBuilder(isOpen);
328
+ setIsOpen(isOpen);
999
329
  };
1000
330
  if (!data || loading) {
1001
331
  return null;
1002
332
  }
1003
- if (error) {
1004
- return _jsx("div", { children: error });
1005
- }
1006
- return (_jsxs("div", { style: { paddingLeft: 40, paddingRight: 40 }, children: [_jsx("div", { style: {
1007
- // width: 'calc(100vw - 30px)',
1008
- display: 'flex',
1009
- position: 'fixed',
1010
- backgroundColor: 'white',
1011
- zIndex: 1,
1012
- left: 0,
1013
- right: 0,
1014
- top: 0,
1015
- flexDirection: 'row',
1016
- paddingTop: 15,
1017
- alignItems: 'center',
1018
- justifyContent: 'space-between',
1019
- paddingLeft: '30px',
1020
- paddingRight: '30px',
1021
- borderBottomWidth: 1,
1022
- borderTopWidth: 0,
1023
- borderLeftWidth: 0,
1024
- borderRightWidth: 0,
1025
- borderStyle: 'solid',
1026
- borderColor: theme.borderColor,
1027
- paddingBottom: 20,
1028
- boxShadow: '0px 1px 4px 0px rgba(0, 0, 0, 0.07)',
1029
- // paddingRight: '50px',
1030
- // position: 'absolute'
1031
- // // zIndex: 10
1032
- }, children: _jsxs("div", { style: {
1033
- display: 'flex',
1034
- flexDirection: 'row',
1035
- alignItems: 'flex-end',
1036
- justifyContent: 'space-between',
1037
- width: '100%',
1038
- // marginLeft: '25px'
1039
- }, children: [_jsxs("div", { style: {
1040
- display: 'flex',
1041
- flexDirection: 'row',
1042
- alignItems: 'center',
1043
- paddingBottom: 4,
1044
- }, children: [_jsx(SecondaryButtonComponent, { label: "\u2190 Back", onClick: goBack }), _jsx("h1", { style: {
1045
- fontSize: '36px',
1046
- paddingTop: '0px',
1047
- fontWeight: '600',
1048
- color: '#384151',
1049
- margin: 0,
1050
- paddingLeft: 16,
1051
- }, children: data.name })] }), _jsxs("div", { style: {
1052
- display: 'flex',
1053
- flexDirection: 'row',
1054
- alignItems: 'center',
1055
- }, children: [_jsx("div", { style: { width: '20px' } }), _jsx("div", { style: { display: 'flex', flexDirection: 'column' }, children: _jsx("div", { style: {
1056
- display: 'flex',
1057
- flexDirection: 'row',
1058
- alignItems: 'flex-end',
1059
- gap: 16,
1060
- }, children: _jsx(OrgSelect, { environment: state.environment, setEnvironment: (env) => dispatch({ type: 'SET_ENVIRONMENT', payload: env }), organizations: state.organizations, organizationId: state.organizationId, setOrganizationId: (orgId) => dispatch({ type: 'SET_ORGANIZATION_ID', payload: orgId }), theme: state.theme }) }) })] })] }) }), _jsx("div", { style: { height: 240 } }), _jsx(Chart, { chartId: reportId, colors: theme.chartColors, isAnimationActive: false, containerStyle: {
1061
- width: 'calc(100vw - 80px)',
1062
- height: data.chartType === 'table' ? 600 : 400,
1063
- } }), _jsxs("div", { style: {
333
+ return (_jsx("div", { ref: parentRef, children: _jsx(ModalComponent, { isOpen: isOpen, setIsOpen: handleSetIsOpen, title: data.name || 'Report Detail', width: modalWidth, height: modalHeight, children: _jsxs("div", { style: {
334
+ width: '100%',
335
+ height: 'calc(100% - 52px)', // full height minus header height
1064
336
  display: 'flex',
1065
- alignItems: 'center',
1066
- gap: 16,
1067
- marginTop: 20,
1068
- }, children: [_jsx(SecondaryButtonComponent, { label: "Edit chart", onClick: () => setIsOpen(true) }), state.navigateToDashboardBuilder && (_jsx(SecondaryButtonComponent, { label: "Edit query", onClick: () => {
1069
- dispatch({ type: 'SET_ACTIVE_QUERY', payload: data.queryString });
1070
- dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: data });
1071
- state.navigateToDashboardBuilder();
1072
- } })), _jsx(SecondaryButtonComponent, { label: "Delete", onClick: deleteReport })] }), data.chartType !== 'table' && (_jsx(QuillTable, { containerStyle: { height: 400, width: '100%', marginTop: 24 }, rows: data.rows, columns: data.columns, showDownloadCSVButton: true })), _jsx(EditVisualizationModal, { isOpen: isOpen, setIsOpen: setIsOpen, report: data, isEditMode: !!state.activeQuery, data: data.rows, query: data.queryString, columns: data.columns, fields: data.fields, state: state, goBack: goBack })] }));
337
+ flexDirection: 'column',
338
+ flexGrow: 1,
339
+ }, children: [_jsxs("div", { style: {
340
+ display: 'flex',
341
+ alignItems: 'center',
342
+ gap: 16,
343
+ padding: 15,
344
+ }, children: [_jsxs("button", { style: {
345
+ height: 36,
346
+ color: theme?.secondaryTextColor,
347
+ border: '1px solid #e7e7e7',
348
+ borderRadius: 6,
349
+ outline: 'none',
350
+ cursor: 'pointer',
351
+ fontFamily: theme?.fontFamily,
352
+ fontWeight: theme?.buttonFontWeight || 500,
353
+ fontSize: 14,
354
+ padding: '0px 12px',
355
+ display: 'flex',
356
+ flexDirection: 'row',
357
+ alignItems: 'center',
358
+ gap: 5,
359
+ }, onClick: () => {
360
+ setIsOpenChartBuilder((showEditChart) => !showEditChart);
361
+ dispatch({
362
+ type: 'SET_ACTIVE_QUERY',
363
+ payload: '',
364
+ });
365
+ dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
366
+ }, className: "secondary-button-quill", children: [_jsx("style", { children: `.secondary-button-quill { background: white } .secondary-button-quill:hover { background: #F4F4F5 }` }), _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", height: 15, width: 15, children: [_jsx("path", { d: "M12 9a1 1 0 0 1-1-1V3c0-.552.45-1.007.997-.93a7.004 7.004 0 0 1 5.933 5.933c.078.547-.378.997-.93.997h-5Z" }), _jsx("path", { d: "M8.003 4.07C8.55 3.994 9 4.449 9 5v5a1 1 0 0 0 1 1h5c.552 0 1.008.45.93.997A7.001 7.001 0 0 1 2 11a7.002 7.002 0 0 1 6.003-6.93Z" })] }), "Edit chart"] }), _jsxs("button", { style: {
367
+ height: 36,
368
+ color: theme?.secondaryTextColor,
369
+ border: '1px solid #e7e7e7',
370
+ borderRadius: 6,
371
+ outline: 'none',
372
+ cursor: 'pointer',
373
+ fontFamily: theme?.fontFamily,
374
+ fontWeight: theme?.buttonFontWeight || 500,
375
+ fontSize: 14,
376
+ padding: '0px 12px',
377
+ display: 'flex',
378
+ flexDirection: 'row',
379
+ alignItems: 'center',
380
+ gap: 5,
381
+ }, onClick: () => {
382
+ if (state.activeQuery && state.activeEditItem) {
383
+ dispatch({ type: 'SET_ACTIVE_QUERY', payload: '' });
384
+ dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
385
+ return;
386
+ }
387
+ dispatch({
388
+ type: 'SET_ACTIVE_QUERY',
389
+ payload: data.queryString,
390
+ });
391
+ dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: data });
392
+ }, className: "secondary-button-quill", children: [_jsx("style", { children: `.secondary-button-quill { background: white } .secondary-button-quill:hover { background: #F4F4F5 }` }), _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", height: 12, width: 12, children: _jsx("path", { d: "M21.731 2.269a2.625 2.625 0 0 0-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 0 0 0-3.712ZM19.513 8.199l-3.712-3.712-12.15 12.15a5.25 5.25 0 0 0-1.32 2.214l-.8 2.685a.75.75 0 0 0 .933.933l2.685-.8a5.25 5.25 0 0 0 2.214-1.32L19.513 8.2Z" }) }), "Edit query"] }), _jsxs("button", { style: {
393
+ height: 36,
394
+ color: theme?.secondaryTextColor,
395
+ border: '1px solid #e7e7e7',
396
+ borderRadius: 6,
397
+ outline: 'none',
398
+ cursor: 'pointer',
399
+ fontFamily: theme?.fontFamily,
400
+ fontWeight: theme?.buttonFontWeight || 500,
401
+ fontSize: 14,
402
+ padding: '0px 12px',
403
+ display: 'flex',
404
+ flexDirection: 'row',
405
+ alignItems: 'center',
406
+ gap: 4,
407
+ }, onClick: deleteReport, className: "secondary-button-quill", children: [_jsx("style", { children: `.secondary-button-quill { background: white } .secondary-button-quill:hover { background: #F4F4F5 }` }), _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", height: 14, width: 14, children: _jsx("path", { fillRule: "evenodd", d: "M8.75 1A2.75 2.75 0 0 0 6 3.75v.443c-.795.077-1.584.176-2.365.298a.75.75 0 1 0 .23 1.482l.149-.022.841 10.518A2.75 2.75 0 0 0 7.596 19h4.807a2.75 2.75 0 0 0 2.742-2.53l.841-10.52.149.023a.75.75 0 0 0 .23-1.482A41.03 41.03 0 0 0 14 4.193V3.75A2.75 2.75 0 0 0 11.25 1h-2.5ZM10 4c.84 0 1.673.025 2.5.075V3.75c0-.69-.56-1.25-1.25-1.25h-2.5c-.69 0-1.25.56-1.25 1.25v.325C8.327 4.025 9.16 4 10 4ZM8.58 7.72a.75.75 0 0 0-1.5.06l.3 7.5a.75.75 0 1 0 1.5-.06l-.3-7.5Zm4.34.06a.75.75 0 1 0-1.5-.06l-.3 7.5a.75.75 0 1 0 1.5.06l.3-7.5Z", clipRule: "evenodd" }) }), "Delete"] })] }), _jsx("div", { style: {
408
+ display: 'flex',
409
+ flexDirection: 'row',
410
+ height: 'calc(100% - 66px)', // full height minus button container
411
+ flexGrow: 1,
412
+ }, children: _jsx("div", { style: {
413
+ width: '100%',
414
+ height: '100%',
415
+ overflowX: 'hidden',
416
+ overflowY: 'auto',
417
+ }, children: state.activeEditItem && state.activeQuery ? (_jsx(QueryEditor, { onSave: handleSave })) : (_jsx(ChartEditor, { isOpen: isOpenChartBuilder, setIsOpen: setIsOpenChartBuilder, reportId: reportId, isAdmin: true, organizationName: state.organizations.find((org) => {
418
+ return (org.id &&
419
+ String(org.id) === String(state.organizationId));
420
+ })?.name, onDelete: deleteReport, onAddToDashboardComplete: (report) => {
421
+ const dashboard = state.dashboards.find((dash) => {
422
+ return dash.name === report.dashboardName;
423
+ });
424
+ dispatch({
425
+ type: 'SET_SELECTED_DASHBOARD',
426
+ payload: dashboard,
427
+ });
428
+ handleSave();
429
+ }, isHorizontalView: true, ModalComponent: FakeModal, ButtonComponent: MemoizedButton })) }) })] }) }) }));
1073
430
  }
1074
- function EditVisualizationModal({ isOpen, setIsOpen, report, data, isEditMode, state, goBack, }) {
1075
- if (!report && !data?.length) {
1076
- return null;
431
+ function QueryEditor({ onSave }) {
432
+ const { state, dispatch } = useAdmin();
433
+ if (state.activeEditItem &&
434
+ state.activeEditItem.referencedTables &&
435
+ state.activeEditItem.referencedTables.length === 1 &&
436
+ state.activeQuery &&
437
+ !state.activeQuery.match(/^\s*with\s/i) &&
438
+ !hasColumnAlias(state.activeEditItem.columns, state.activeEditItem.referencedColumns[state.activeEditItem.referencedTables[0]] || undefined)) {
439
+ return (_jsx(ReportBuilder, { isAdminEnabled: true,
440
+ // initialTableName={state.tables.length > 0 && state.tables[0]!.name}
441
+ reportId: state.activeEditItem._id, onSubmitEditReport: (report) => {
442
+ const dashboard = state.dashboards.find((dash) => {
443
+ return dash.name === report.dashboardName;
444
+ });
445
+ dispatch({ type: 'SET_ACTIVE_QUERY', payload: '' });
446
+ dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
447
+ dispatch({
448
+ type: 'SET_SELECTED_DASHBOARD',
449
+ payload: dashboard,
450
+ });
451
+ onSave(); // refresh the dashboard in the background
452
+ }, organizationName: state.organizations.find((org) => {
453
+ return org.id && String(org.id) === String(state.organizationId);
454
+ })?.name, isChartBuilderHorizontalView: true,
455
+ // @ts-ignore
456
+ ChartBuilderModalComponent: FakeSQLEditorModal, containerStyle: {
457
+ height: '100%',
458
+ width: '100%',
459
+ } }));
1077
460
  }
1078
- return (_jsx(_Fragment, { children: isOpen && (_jsxs("div", { className: "inset-0 overflow-y-auto relative", style: { zIndex: 120 }, children: [_jsx("div", { className: "absolute inset-0 bg-black/30", "aria-hidden": "true", onClick: () => setIsOpen(false) }), _jsx("div", { className: "flex min-h-full items-center justify-center p-4", children: _jsx("div", { className: "bg-white px-7 py-7 rounded-lg", children: _jsx(ChartEditor, { isOpen: isOpen, setIsOpen: setIsOpen, isEditMode: isEditMode, chartId: report._id, admin: true, organizationName: state.organizations.find((org) => {
1079
- return (org.id && String(org.id) === String(state.organizationId));
1080
- })?.name, onDelete: goBack }) }) })] })) }));
461
+ return (_jsx(SQLEditor, { isChartBuilderHorizontalView: true, isChartBuilderEnabled: true, showAccessControlOptions: true, showDateFieldOptions: true, showTableFormatOptions: true, defaultQuery: state.activeQuery, addToDashboardButtonLabel: state.activeQuery ? 'Save changes' : 'Add to dashboard', chartBuilderTitle: state.activeQuery ? 'Save changes' : 'Add to dashboard', report: state.activeQuery ? state.activeEditItem : undefined, onAddToDashboardComplete: (report) => {
462
+ const dashboard = state.dashboards.find((dash) => {
463
+ return dash.name === report.dashboardName;
464
+ });
465
+ dispatch({ type: 'SET_ACTIVE_QUERY', payload: '' });
466
+ dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
467
+ dispatch({
468
+ type: 'SET_SELECTED_DASHBOARD',
469
+ payload: dashboard,
470
+ });
471
+ onSave(); // refresh the dashboard in the background
472
+ }, containerStyle: {
473
+ height: '100%',
474
+ width: '100%',
475
+ }, organizationName: state.organizations.find((org) => {
476
+ return org.id && String(org.id) === String(state.organizationId);
477
+ })?.name,
478
+ // @ts-ignore
479
+ ModalComponent: FakeSQLEditorModal, ButtonComponent: MemoizedButton }));
1081
480
  }
1082
- export function ReportWrapper({ SecondaryButtonComponent, ButtonComponent, ModalComponent, SelectComponent, OrganizationSelectComponent, organizationId, queryEndpoint, queryHeaders, withCredentials, }) {
481
+ export function ReportWrapper({ SecondaryButtonComponent, ButtonComponent, ModalComponent, SelectComponent, OrganizationSelectComponent, organizationId, queryEndpoint, queryHeaders, withCredentials, isOpen, setIsOpen, reloadDashboard, }) {
1083
482
  const { state, dispatch } = useAdmin();
1084
- let [isOpen, setIsOpen] = useState(false);
1085
483
  const [isEditQueryOpen, setIsEditQueryOpen] = useState(false);
1086
484
  const updateQuery = async (dashboardItemId, query) => {
1087
485
  if (!state.client || !dashboardItemId || !query) {
@@ -1119,7 +517,7 @@ export function ReportWrapper({ SecondaryButtonComponent, ButtonComponent, Modal
1119
517
  headers: {
1120
518
  'Content-Type': 'application/json',
1121
519
  Authorization: 'Bearer ',
1122
- environment: state.environment || undefined,
520
+ environment: state.environment,
1123
521
  },
1124
522
  body: JSON.stringify(requestBody),
1125
523
  });
@@ -1180,7 +578,7 @@ export function ReportWrapper({ SecondaryButtonComponent, ButtonComponent, Modal
1180
578
  method: 'POST',
1181
579
  headers: {
1182
580
  'Content-Type': 'application/json',
1183
- environment: state.environment || undefined,
581
+ environment: state.environment,
1184
582
  },
1185
583
  body: JSON.stringify(requestBody),
1186
584
  });
@@ -1189,148 +587,11 @@ export function ReportWrapper({ SecondaryButtonComponent, ButtonComponent, Modal
1189
587
  }
1190
588
  if (responseData) {
1191
589
  dispatch({ type: 'SET_ACTIVE_COMPONENT', payload: 'Dashboards' });
590
+ reloadDashboard();
1192
591
  }
1193
592
  };
1194
- return (_jsx(Report, { reportId: state.reportId, updateQuery: updateQuery, isOpen: isOpen, setIsOpen: setIsOpen, isEditQueryOpen: isEditQueryOpen, setIsEditQueryOpen: setIsEditQueryOpen, deleteReport: deleteReport, SecondaryButtonComponent: SecondaryButtonComponent, ButtonComponent: ButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, OrganizationSelectComponent: OrganizationSelectComponent }));
1195
- }
1196
- const measuringConfig = {
1197
- droppable: {
1198
- strategy: MeasuringStrategy.Always,
1199
- },
1200
- };
1201
- export function ReorderableList({ initialItems, client, itemMap, ButtonComponent, closeModal, onSave, }) {
1202
- const [items, setItems] = useState([]);
1203
- // const [client] = useContext(ClientContext);
1204
- const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, {
1205
- coordinateGetter: sortableKeyboardCoordinates,
1206
- }), useSensor(TouchSensor, {
1207
- activationConstraint: '',
1208
- }));
1209
- useEffect(() => {
1210
- setItems(initialItems
1211
- .sort((a, b) => {
1212
- if (a.order === undefined && b.order === undefined)
1213
- return 0; // both items don't have the 'order' field
1214
- if (a.order === undefined)
1215
- return 1; // only 'a' doesn't have the 'order' field, place 'a' last
1216
- if (b.order === undefined)
1217
- return -1; // only 'b' doesn't have the 'order' field, place 'b' last
1218
- return a.order - b.order; // both items have the 'order' field, sort numerically
1219
- })
1220
- .map((elem) => elem._id));
1221
- }, [initialItems]);
1222
- const handleSaveChanges = async () => {
1223
- if (!client) {
1224
- return;
1225
- }
1226
- if (!items.length) {
1227
- return;
1228
- }
1229
- try {
1230
- const response = await fetch(`${QUILL_SERVER}/dashorder/`, {
1231
- method: 'POST',
1232
- headers: {
1233
- 'Content-Type': 'application/json',
1234
- },
1235
- body: JSON.stringify({
1236
- publicKey: client._id,
1237
- orderArray: items,
1238
- }),
1239
- });
1240
- if (!response.ok) {
1241
- const errorData = await response.json();
1242
- throw new Error(`Error: ${errorData.error || 'Unknown error'}`);
1243
- }
1244
- const data = await response.json();
1245
- await onSave();
1246
- closeModal();
1247
- }
1248
- catch (error) {
1249
- console.error(error.message);
1250
- }
1251
- };
1252
- return (_jsxs("div", { children: [_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd, measuring: measuringConfig, children: _jsx(SortableContext, { items: items, strategy: verticalListSortingStrategy, children: _jsxs("div", { style: {
1253
- background: 'white',
1254
- position: 'fixed',
1255
- width: '100%',
1256
- height: 'calc(100% - 40px)',
1257
- overflowY: 'scroll',
1258
- overflowX: 'hidden',
1259
- maxWidth: 700,
1260
- }, children: [_jsx("div", { style: { height: 80 } }), items.map((id) => (_jsx(SortableItem, { id: id, name: itemMap?.get(id).name }, id))), _jsx("div", { style: { height: 100, width: '100%' } })] }) }) }), _jsx("div", { style: {
1261
- height: 80,
1262
- paddingTop: 20,
1263
- width: '100%',
1264
- background: 'white',
1265
- position: 'absolute',
1266
- bottom: -20,
1267
- left: 0,
1268
- right: 0,
1269
- }, children: _jsx(ButtonComponent, { onClick: handleSaveChanges, label: "Save changes" }) })] }));
1270
- function handleDragEnd(event) {
1271
- const { active, over } = event;
1272
- if (!over?.id || !active?.id) {
1273
- return;
1274
- }
1275
- if (active.id !== over.id) {
1276
- setItems((items) => {
1277
- const oldIndex = items.indexOf(active.id);
1278
- const newIndex = items.indexOf(over.id);
1279
- return arrayMove(items, oldIndex, newIndex);
1280
- });
1281
- }
1282
- }
1283
- }
1284
- const animateLayoutChanges = (args) => args.isSorting || args.wasDragging ? defaultAnimateLayoutChanges(args) : true;
1285
- function SortableItem({ id, name }) {
1286
- const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
1287
- animateLayoutChanges,
1288
- id: id,
1289
- });
1290
- let height = 50;
1291
- const style = {
1292
- transform: CSS.Translate.toString(transform),
1293
- transition,
1294
- display: 'flex',
1295
- justifyContent: 'space-between',
1296
- alignItems: 'center',
1297
- borderRadius: '10px',
1298
- border: '1px solid #E7E7E7',
1299
- boxShadow: '0px 2px 8px 0px rgba(56, 65, 81, 0.08)',
1300
- cursor: 'grab',
1301
- userSelect: 'none',
1302
- marginBottom: 20,
1303
- background: 'white',
593
+ const handleSave = () => {
594
+ reloadDashboard();
1304
595
  };
1305
- return (_jsx("div", { ref: setNodeRef, style: style, ...attributes, children: _jsxs("div", { style: {
1306
- cursor: 'pointer',
1307
- width: '100%',
1308
- display: 'flex',
1309
- flexDirection: 'row',
1310
- alignItems: 'center',
1311
- justifyContent: 'space-between',
1312
- height: 260,
1313
- }, ...listeners, children: [_jsxs("div", { style: {
1314
- display: 'flex',
1315
- flexDirection: 'column',
1316
- justifyContent: 'space-between',
1317
- height: 260,
1318
- paddingTop: 20,
1319
- paddingBottom: 20,
1320
- width: '100%',
1321
- }, children: [_jsx("div", { style: {
1322
- minWidth: 600,
1323
- width: '100%',
1324
- paddingLeft: 20,
1325
- fontSize: 18,
1326
- fontWeight: '500',
1327
- }, children: name }), _jsx(Chart, { chartId: id, containerStyle: {
1328
- height: 180,
1329
- width: '100%',
1330
- } })] }), _jsx("div", { style: {
1331
- display: 'flex',
1332
- flexDirection: 'column',
1333
- paddingRight: 20,
1334
- paddingLeft: 20,
1335
- }, children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", "stroke-width": "1.5", stroke: "#6D727E", height: 24, width: 24, children: _jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M8.25 15L12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9" }) }) })] }) }));
596
+ return (_jsx(QuillReport, { reportId: state.reportId, updateQuery: updateQuery, isOpen: isOpen, setIsOpen: setIsOpen, isEditQueryOpen: isEditQueryOpen, setIsEditQueryOpen: setIsEditQueryOpen, deleteReport: deleteReport, handleSave: handleSave, SecondaryButtonComponent: SecondaryButtonComponent, ButtonComponent: ButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, OrganizationSelectComponent: OrganizationSelectComponent }));
1336
597
  }