@quillsql/admin 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/Admin.js CHANGED
@@ -142,7 +142,336 @@ const defaultTheme = {
142
142
  labelFontWeight: "500",
143
143
  fontSize: 14,
144
144
  };
145
- function Portal({ publicKey, queryEndpoint, theme = defaultTheme, queryHeaders, withCredentials, environment, organizationId, TextInputComponent, ButtonComponent, SecondaryButtonComponent, ModalComponent, SelectComponent, OrganizationSelectComponent, UserManagementComponent, }) {
145
+ function EditFiltersModal({ isOpen, dashboardData, selectedDashboard, client, setIsOpen, filters, dateFilter, openAddFilterModal, ModalComponent, TextInputComponent, ButtonComponent, HeaderComponent, SelectComponent, selectedEditDashboard, dashNames, setSelectedEditDashboard, }) {
146
+ const [selectedDashboardName, setSelectedDashboardName] = (0, react_1.useState)("");
147
+ (0, react_1.useEffect)(() => {
148
+ setSelectedDashboardName(selectedDashboard);
149
+ }, [selectedDashboard]);
150
+ const [newFilters, setNewFilters] = (0, react_1.useState)([]);
151
+ const [newDateFilter, setNewDateFilter] = (0, react_1.useState)(null);
152
+ const [tables] = (0, react_1.useContext)(TablesContext);
153
+ const [selectedTable, setSelectedTable] = (0, react_1.useState)(null);
154
+ const [field, setField] = (0, react_1.useState)("");
155
+ (0, react_1.useEffect)(() => {
156
+ if (tables.length) {
157
+ setSelectedTable(tables[0]);
158
+ setField(tables[0].columns.map((elem) => elem.name)[0]);
159
+ }
160
+ }, [tables]);
161
+ (0, react_1.useEffect)(() => {
162
+ if (dashboardData && dashboardData.filters) {
163
+ setNewFilters(dashboardData.filters);
164
+ }
165
+ if (dashboardData && dashboardData.dateFilter) {
166
+ setNewDateFilter(dashboardData.dateFilter);
167
+ }
168
+ }, [dashboardData]);
169
+ const handleAddFilter = async () => {
170
+ setNewFilters([...newFilters, { label: "", field }]);
171
+ };
172
+ const handleSubmitDashboardChanges = async () => {
173
+ if (!selectedDashboardName ||
174
+ newFilters.some((filter) => !filter.label) ||
175
+ (newDateFilter &&
176
+ Object.keys(newDateFilter).length &&
177
+ !newDateFilter.label)) {
178
+ alert("Empty fields");
179
+ return;
180
+ }
181
+ if (newFilters.filter((elem) => !elem.field).length) {
182
+ alert(`no filter field for: ${newFilters.filter((elem) => !elem.field)[0].label}`);
183
+ return;
184
+ }
185
+ const updatedFilters = newFilters.map((filter) => {
186
+ const filterType = getPostgresBasicType(selectedTable.columns.find((col) => col.name === filter.field));
187
+ return {
188
+ table: selectedTable.name,
189
+ field: filter.field,
190
+ labelField: filter.field,
191
+ label: filter.label,
192
+ filterType,
193
+ };
194
+ });
195
+ if (dashNames &&
196
+ dashNames.length > 0 &&
197
+ dashNames.some((dashName) => dashName.name === selectedDashboardName &&
198
+ selectedDashboardName !== selectedDashboard)) {
199
+ alert("Dashboard name already taken!");
200
+ return;
201
+ }
202
+ const fieldsSet = new Set();
203
+ const hasDuplicateField = updatedFilters.some((filter) => {
204
+ if (fieldsSet.has(filter.field)) {
205
+ return true;
206
+ }
207
+ else {
208
+ fieldsSet.add(filter.field);
209
+ return false;
210
+ }
211
+ });
212
+ if (hasDuplicateField ||
213
+ (Object.keys(newDateFilter).length > 0 &&
214
+ updatedFilters.some((filter) => filter.filterType === "date"))) {
215
+ alert("Maximum of one filter per field");
216
+ return;
217
+ }
218
+ let allValid = true;
219
+ updatedFilters.forEach((filter) => {
220
+ if (filter.filterType !== "string" && filter.filterType !== "date") {
221
+ allValid = false;
222
+ console.error(`Invalid filterType found: ${filter.filterType}`);
223
+ }
224
+ });
225
+ if (!allValid) {
226
+ alert("We only support string and filters.");
227
+ return;
228
+ }
229
+ let responseData;
230
+ const url = `https://quill-344421.uc.r.appspot.com/dashfilter/${client._id}/`;
231
+ const body = {
232
+ newDashboardName: selectedDashboardName,
233
+ filters: updatedFilters,
234
+ dateFilter: newDateFilter,
235
+ name: selectedDashboard,
236
+ };
237
+ const headers = {
238
+ "Content-Type": "application/json",
239
+ Authorization: `Bearer `,
240
+ };
241
+ try {
242
+ const response = await fetch(url, {
243
+ method: "POST",
244
+ headers: headers,
245
+ body: JSON.stringify(body),
246
+ });
247
+ setSelectedEditDashboard(null);
248
+ setIsOpen(false);
249
+ }
250
+ catch (e) {
251
+ console.log("error");
252
+ }
253
+ };
254
+ // const handleDeleteFilter = async () => {
255
+ // const url = `https://quill-344421.uc.r.appspot.com/dashfilterdelete/${client._id}/`;
256
+ // const body = {
257
+ // name: selectedDashboard.name,
258
+ // filterId: "DATE_RANGE", //TODO: Change this?
259
+ // };
260
+ // const headers = {
261
+ // "Content-Type": "application/json",
262
+ // Authorization: `Bearer `,
263
+ // };
264
+ // try {
265
+ // const response = await fetch(url, {
266
+ // method: "POST",
267
+ // headers: headers,
268
+ // body: JSON.stringify(body),
269
+ // });
270
+ // if (!response.ok) {
271
+ // throw new Error(`HTTP error! Status: ${response.status}`);
272
+ // }
273
+ // const responseData = await response.json();
274
+ // if (responseData) {
275
+ // setIsOpen(false);
276
+ // return;
277
+ // }
278
+ // } catch (error) {
279
+ // console.error("There was a problem with the fetch operation:", error);
280
+ // }
281
+ // };
282
+ const handleDeleteFilter = (filter) => {
283
+ setNewFilters(newFilters.filter((f) => f !== filter));
284
+ };
285
+ const handleDeleteDateFilter = async () => {
286
+ // const response2 = await axios.post(
287
+ // `https://quill-344421.uc.r.appspot.com/dashfilterdelete/${client._id}/`,
288
+ // {
289
+ // name: selectedDashboard.name,
290
+ // filterId: "DATE_RANGE",
291
+ // },
292
+ // { headers: { Authorization: `Bearer ` } }
293
+ // );
294
+ // if (response2 && response2.data) {
295
+ // setIsOpen(false);
296
+ // return;
297
+ // }
298
+ setNewDateFilter({});
299
+ };
300
+ return ((0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: isOpen, close: () => {
301
+ setIsOpen(false);
302
+ }, children: (0, jsx_runtime_1.jsxs)("div", { style: {
303
+ display: "flex",
304
+ flexDirection: "column",
305
+ // alignItems: "center",
306
+ }, children: [(0, jsx_runtime_1.jsx)(HeaderComponent, { label: "Edit filters" }), (0, jsx_runtime_1.jsx)("div", { children: "Dashboard name" }), (0, jsx_runtime_1.jsx)(TextInputComponent, { value: selectedDashboardName, onChange: (e) => setSelectedDashboardName(e.target.value) }), (0, jsx_runtime_1.jsxs)("div", { children: [newDateFilter &&
307
+ Object.values(newDateFilter).length > 0 &&
308
+ newDateFilter.label ? (
309
+ // <div style={{ display: "flex", flexDirection: "row" }}>
310
+ // <div style={{ display: "flex", flexDirection: "column" }}>
311
+ // <div>Label</div>
312
+ // <div>{dashboardData.dateFilter.label}</div>
313
+ // </div>
314
+ // <div style={{ display: "flex", flexDirection: "column" }}>
315
+ // <div>Initial date range</div>
316
+ // <div
317
+ // style={{
318
+ // display: "flex",
319
+ // flexDirection: "column",
320
+ // alignItems: "center",
321
+ // }}
322
+ // >
323
+ // <div>
324
+ // {dashboardData.dateFilter.initialRange === "LAST_90_DAYS"
325
+ // ? "Last 90 days"
326
+ // : ""}
327
+ // {dashboardData.dateFilter.initialRange === "LAST_30_DAYS"
328
+ // ? "Last 30 days"
329
+ // : ""}
330
+ // {dashboardData.dateFilter.initialRange === "CURRENT_MONTH"
331
+ // ? "This month"
332
+ // : ""}
333
+ // </div>
334
+ // <div
335
+ // // onClick={handleDeleteDateFilter}
336
+ // style={{
337
+ // height: 42,
338
+ // width: 42,
339
+ // alignItems: "center",
340
+ // justifyContent: "center",
341
+ // display: "flex",
342
+ // }}
343
+ // >
344
+ // {/* <svg
345
+ // xmlns="http://www.w3.org/2000/svg"
346
+ // viewBox="0 0 24 24"
347
+ // fill="#4C5462"
348
+ // width="20"
349
+ // height="20"
350
+ // >
351
+ // <path
352
+ // fill-rule="evenodd"
353
+ // 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"
354
+ // clip-rule="evenodd"
355
+ // />
356
+ // </svg> */}
357
+ // </div>
358
+ // </div>
359
+ // </div>
360
+ // </div>
361
+ (0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", flexDirection: "row" }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", flexDirection: "column" }, children: [(0, jsx_runtime_1.jsx)("h2", { children: "Date Label" }), (0, jsx_runtime_1.jsx)(TextInputComponent, { value: newDateFilter.label, onChange: (e) => {
362
+ setNewDateFilter({
363
+ ...newDateFilter,
364
+ label: e.target.value,
365
+ });
366
+ } })] }), (0, jsx_runtime_1.jsx)("div", { onClick: () => handleDeleteDateFilter(), style: {
367
+ height: 42,
368
+ width: 42,
369
+ alignItems: "center",
370
+ justifyContent: "center",
371
+ display: "flex",
372
+ }, children: (0, jsx_runtime_1.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#4C5462", width: "20", height: "20", children: (0, jsx_runtime_1.jsx)("path", { "fill-rule": "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" }) }) })] })) : null, newFilters.length > 0 &&
373
+ newFilters.map((filter, index) => {
374
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", flexDirection: "row" }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", flexDirection: "column" }, children: [(0, jsx_runtime_1.jsx)("h2", { children: "Label" }), (0, jsx_runtime_1.jsx)(TextInputComponent, { value: filter.label, onChange: (e) => {
375
+ const updatedFilters = newFilters.map((otherFilter, i) => index === i
376
+ ? { ...otherFilter, label: e.target.value }
377
+ : otherFilter);
378
+ setNewFilters(updatedFilters);
379
+ } })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", flexDirection: "column" }, children: [(0, jsx_runtime_1.jsx)("h4", { children: "Field" }), (0, jsx_runtime_1.jsx)("div", { style: {
380
+ display: "flex",
381
+ flexDirection: "column",
382
+ alignItems: "center",
383
+ }, children: (0, jsx_runtime_1.jsxs)("div", { style: {
384
+ display: "flex",
385
+ flexDirection: "row",
386
+ alignItems: "center",
387
+ }, children: [(0, jsx_runtime_1.jsx)(SelectComponent, { defaultValue: "", value: filter && filter.field ? filter.field : "", options: selectedTable.columns.map((column) => {
388
+ return { label: column.name, value: column.name };
389
+ }), onChange: (e) => {
390
+ const updatedFilters = newFilters.map((otherFilter, i) => index === i
391
+ ? { ...otherFilter, field: e }
392
+ : otherFilter);
393
+ setNewFilters(updatedFilters);
394
+ } }), (0, jsx_runtime_1.jsx)("div", { onClick: () => handleDeleteFilter(filter), style: {
395
+ height: 42,
396
+ width: 42,
397
+ alignItems: "center",
398
+ justifyContent: "center",
399
+ display: "flex",
400
+ }, children: (0, jsx_runtime_1.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#4C5462", width: "20", height: "20", children: (0, jsx_runtime_1.jsx)("path", { "fill-rule": "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" }) }) })] }) })] })] }));
401
+ })] }), (0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: handleAddFilter, label: "Add new filter +" }), (0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: handleSubmitDashboardChanges, label: "Submit Dashboard Changes" })] }) }));
402
+ }
403
+ function AddFilterModal({ isOpen, selectedDashboard, client, setIsOpen, ModalComponent, TextInputComponent, SelectComponent, HeaderComponent, ButtonComponent, openAddDashboardModal, }) {
404
+ const [tables] = (0, react_1.useContext)(TablesContext);
405
+ const [selectedTable, setSelectedTable] = (0, react_1.useState)(null);
406
+ const [name, setName] = (0, react_1.useState)("");
407
+ const [field, setField] = (0, react_1.useState)("");
408
+ const [filterType, setFilterType] = (0, react_1.useState)("string");
409
+ const [dateRange, setDateRange] = (0, react_1.useState)([new Date(), new Date()]);
410
+ (0, react_1.useEffect)(() => {
411
+ if (tables.length) {
412
+ setSelectedTable(tables[0]);
413
+ // setField(tables[0].columns.map((elem) => elem.name));
414
+ setField(tables[0].columns[0].name);
415
+ }
416
+ }, [tables]);
417
+ const handleAddFilter = async () => {
418
+ if (!selectedTable || !field) {
419
+ return;
420
+ }
421
+ const filterType = getPostgresBasicType(selectedTable.columns.find((col) => col.name === field));
422
+ if (filterType !== "string" && filterType !== "date") {
423
+ alert("We only support string and filters.");
424
+ return;
425
+ }
426
+ let responseData;
427
+ const url = `https://quill-344421.uc.r.appspot.comdashfilter/${client._id}/`;
428
+ const body = {
429
+ name: selectedDashboard,
430
+ filter: {
431
+ table: selectedTable.name,
432
+ field: field,
433
+ labelField: field,
434
+ label: name,
435
+ filterType,
436
+ },
437
+ };
438
+ const headers = {
439
+ "Content-Type": "application/json",
440
+ Authorization: `Bearer `,
441
+ };
442
+ try {
443
+ const response = await fetch(url, {
444
+ method: "POST",
445
+ headers: headers,
446
+ body: JSON.stringify(body),
447
+ });
448
+ if (!response.ok) {
449
+ throw new Error(`HTTP error! Status: ${response.status}`);
450
+ }
451
+ responseData = await response.json();
452
+ }
453
+ catch (error) {
454
+ console.error("There was a problem with the fetch operation:", error);
455
+ }
456
+ if (responseData) {
457
+ setIsOpen(false);
458
+ setName("");
459
+ setField("");
460
+ return;
461
+ }
462
+ };
463
+ if (!selectedTable) {
464
+ return null;
465
+ }
466
+ return ((0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: isOpen, close: () => setIsOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", flexDirection: "column" }, children: [(0, jsx_runtime_1.jsx)(HeaderComponent, { label: "Add filter" }), (0, jsx_runtime_1.jsx)("div", { children: "Label" }), (0, jsx_runtime_1.jsx)(TextInputComponent, { value: name, onChange: (e) => setName(e.target.value) }), (0, jsx_runtime_1.jsx)("div", { children: "Table" }), (0, jsx_runtime_1.jsx)(SelectComponent, { defaultValue: "", value: selectedTable ? selectedTable : "", onChange: (e) => setSelectedTable(e.target.value), options: tables.map((table) => {
467
+ return { label: table.name, value: table.name };
468
+ }) }), (0, jsx_runtime_1.jsx)("div", { children: "Field" }), (0, jsx_runtime_1.jsx)(SelectComponent, { defaultValue: "", value: field ? field : "", options: selectedTable.columns.map((column) => {
469
+ return { label: column.name, value: column.name };
470
+ }), onChange: (e) => {
471
+ setField(e);
472
+ } }), (0, jsx_runtime_1.jsx)(ButtonComponent, { label: "Add filter", onClick: handleAddFilter })] }) }));
473
+ }
474
+ function Portal({ publicKey, queryEndpoint, theme = defaultTheme, queryHeaders, withCredentials, environment, organizationId, TextInputComponent, ButtonComponent, SecondaryButtonComponent, ModalComponent, SelectComponent, OrganizationSelectComponent, UserManagementComponent, HeaderComponent, }) {
146
475
  return ((0, jsx_runtime_1.jsx)(ContextProvider, { children: (0, jsx_runtime_1.jsx)(Navigation, { theme: theme, publicKey: publicKey, organizationId: organizationId, queryEndpoint: queryEndpoint, queryHeaders: queryHeaders, withCredentials: withCredentials, TextInputComponent: TextInputComponent ||
147
476
  (({ onChange, value, placeholder }) => ((0, jsx_runtime_1.jsx)("input", { style: {
148
477
  display: "flex",
@@ -177,7 +506,13 @@ function Portal({ publicKey, queryEndpoint, theme = defaultTheme, queryHeaders,
177
506
  fontSize: 14,
178
507
  paddingLeft: 20,
179
508
  paddingRight: 20,
180
- }, onClick: onClick, children: label }))), SecondaryButtonComponent: SecondaryButtonComponent ||
509
+ }, onClick: onClick, children: label }))), HeaderComponent: HeaderComponent ||
510
+ (({ label }) => ((0, jsx_runtime_1.jsx)("h1", { style: {
511
+ color: theme?.primaryTextColor,
512
+ fontFamily: theme?.fontFamily,
513
+ fontWeight: theme?.buttonFontWeight || 600,
514
+ fontSize: 16,
515
+ }, children: label }))), SecondaryButtonComponent: SecondaryButtonComponent ||
181
516
  (({ onClick, label }) => ((0, jsx_runtime_1.jsx)("button", { style: {
182
517
  height: 36,
183
518
  background: "#F9FAFB",
@@ -195,39 +530,44 @@ function Portal({ publicKey, queryEndpoint, theme = defaultTheme, queryHeaders,
195
530
  paddingLeft: 20,
196
531
  paddingRight: 20,
197
532
  }, onClick: onClick, children: label }))), ModalComponent: ModalComponent ||
198
- (({ isOpen, close, children }) => isOpen ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: {
199
- position: "fixed",
200
- top: "0",
201
- right: "0",
202
- bottom: "0",
203
- left: "0",
204
- zIndex: "50",
205
- backgroundColor: "rgba(255, 255, 255, 0.8)",
206
- backdropFilter: "blur(5px)",
207
- }, onClick: close }), (0, jsx_runtime_1.jsx)("div", { style: {
208
- // position: "absolute",
209
- position: "fixed",
210
- left: "50%",
211
- top: "50%",
212
- zIndex: "50",
213
- // width: "100%",
214
- // maxWidth: 1024,
215
- maxHeight: "90vh",
216
- display: "flex",
217
- justifyContent: "center",
218
- alignItems: "center",
219
- transform: "translateX(-50%) translateY(-50%)",
220
- background: "white",
221
- borderRadius: 8,
222
- borderStyle: "solid",
223
- borderWidth: 1,
224
- borderColor: "#e7e7e7",
225
- overflow: "hidden",
226
- padding: 30,
227
- // zIndex: 1000,
228
- }, children: children })] })) : null), environment: environment, OrganizationSelectComponent: OrganizationSelectComponent, UserManagementComponent: UserManagementComponent, SelectComponent: SelectComponent ||
533
+ (({ isOpen, close, children }) => {
534
+ if (!isOpen) {
535
+ return null;
536
+ }
537
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: {
538
+ position: "fixed",
539
+ top: "0",
540
+ right: "0",
541
+ bottom: "0",
542
+ left: "0",
543
+ zIndex: "50",
544
+ backgroundColor: "rgba(255, 255, 255, 0.8)",
545
+ backdropFilter: "blur(5px)",
546
+ }, onClick: close }), (0, jsx_runtime_1.jsx)("div", { style: {
547
+ // position: "absolute",
548
+ position: "fixed",
549
+ left: "50%",
550
+ top: "50%",
551
+ zIndex: "50",
552
+ // width: "100%",
553
+ // maxWidth: 1024,
554
+ maxHeight: "90vh",
555
+ display: "flex",
556
+ justifyContent: "center",
557
+ alignItems: "center",
558
+ transform: "translateX(-50%) translateY(-50%)",
559
+ background: "white",
560
+ borderRadius: 8,
561
+ borderStyle: "solid",
562
+ borderWidth: 1,
563
+ borderColor: "#e7e7e7",
564
+ overflow: "hidden",
565
+ padding: 30,
566
+ // zIndex: 1000,
567
+ }, children: children })] }));
568
+ }), environment: environment, OrganizationSelectComponent: OrganizationSelectComponent, UserManagementComponent: UserManagementComponent, SelectComponent: SelectComponent ||
229
569
  (({ options, onChange, value }) => {
230
- return ((0, jsx_runtime_1.jsxs)("div", { style: { position: "relative" }, children: [(0, jsx_runtime_1.jsx)("select", { style: {
570
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { position: "relative" }, children: [(0, jsx_runtime_1.jsx)("select", { defaultValue: "", style: {
231
571
  width: "100%",
232
572
  minWidth: 230,
233
573
  outline: "none",
@@ -246,7 +586,8 @@ function Portal({ publicKey, queryEndpoint, theme = defaultTheme, queryHeaders,
246
586
  color: theme?.primaryTextColor,
247
587
  boxShadow: "0 1px 2px 0 rgba(0,0,0,.05)",
248
588
  fontFamily: theme?.fontFamily,
249
- }, value: value, onChange: (event) => onChange(event.target.value), children: options.map((option) => ((0, jsx_runtime_1.jsx)("option", { value: option.value, label: option.label }))) }), (0, jsx_runtime_1.jsx)(ArrowDownHeadIcon, { style: {
589
+ }, value: value, onChange: (event) => onChange(event.target.value), children: options.length > 0 &&
590
+ options.map((option) => ((0, jsx_runtime_1.jsx)("option", { value: option.value, label: option.label }, option.value))) }), (0, jsx_runtime_1.jsx)(ArrowDownHeadIcon, { style: {
250
591
  height: "20px",
251
592
  width: "20px",
252
593
  flex: "none",
@@ -259,7 +600,7 @@ function Portal({ publicKey, queryEndpoint, theme = defaultTheme, queryHeaders,
259
600
  }
260
601
  exports.default = Portal;
261
602
  const ArrowDownHeadIcon = ({ ...props }) => ((0, jsx_runtime_1.jsxs)("svg", { ...props, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: "24", height: "24", children: [(0, jsx_runtime_1.jsx)("path", { fill: "none", d: "M0 0h24v24H0z" }), (0, jsx_runtime_1.jsx)("path", { fill: "currentColor", d: "M12 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z" })] }));
262
- function Navigation({ TextInputComponent, ButtonComponent, SecondaryButtonComponent, ModalComponent, SelectComponent, OrganizationSelectComponent, UserManagementComponent, publicKey, organizationId, queryEndpoint, queryHeaders, environment, withCredentials, }) {
603
+ function Navigation({ TextInputComponent, ButtonComponent, SecondaryButtonComponent, ModalComponent, SelectComponent, OrganizationSelectComponent, UserManagementComponent, HeaderComponent, publicKey, organizationId, queryEndpoint, queryHeaders, environment, withCredentials, }) {
263
604
  const [client, setClient] = (0, react_1.useContext)(ClientContext);
264
605
  const [environmentContext, setEnvironmentContext] = (0, react_1.useContext)(EnvironmentContext);
265
606
  const [tables, setTables] = (0, react_1.useContext)(TablesContext);
@@ -309,15 +650,15 @@ function Navigation({ TextInputComponent, ButtonComponent, SecondaryButtonCompon
309
650
  const renderComponentBasedOnName = () => {
310
651
  switch (activeComponent) {
311
652
  case "Dashboards":
312
- return ((0, jsx_runtime_1.jsx)(Dashboards, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, OrganizationSelectComponent: OrganizationSelectComponent, setReportId: setReportId, queryEndpoint: queryEndpoint, queryHeaders: queryHeaders, organizationId: organizationId, withCredentials: withCredentials }));
653
+ return ((0, jsx_runtime_1.jsx)(Dashboards, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, OrganizationSelectComponent: OrganizationSelectComponent, HeaderComponent: HeaderComponent, setReportId: setReportId, queryEndpoint: queryEndpoint, organizationId: organizationId, queryHeaders: queryHeaders, withCredentials: withCredentials }));
313
654
  case "SQL editor":
314
655
  return ((0, jsx_runtime_1.jsx)(QueryEditor, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent }));
315
656
  case "Report":
316
- return ((0, jsx_runtime_1.jsx)(ReportWrapper, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, organizationId: organizationId }));
657
+ return ((0, jsx_runtime_1.jsx)(ReportWrapper, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent }));
317
658
  case "SQL views":
318
- return ((0, jsx_runtime_1.jsx)(Tables, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent }));
659
+ return ((0, jsx_runtime_1.jsx)(Tables, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, queryEndpoint: queryEndpoint, queryHeaders: queryHeaders }));
319
660
  default:
320
- return ((0, jsx_runtime_1.jsx)(Dashboards, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, OrganizationSelectComponent: OrganizationSelectComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, setReportId: setReportId, queryEndpoint: queryEndpoint, queryHeaders: queryHeaders, organizationId: organizationId, withCredentials: withCredentials }));
661
+ return ((0, jsx_runtime_1.jsx)(Dashboards, { TextInputComponent: TextInputComponent, ButtonComponent: ButtonComponent, SecondaryButtonComponent: SecondaryButtonComponent, OrganizationSelectComponent: OrganizationSelectComponent, ModalComponent: ModalComponent, SelectComponent: SelectComponent, HeaderComponent: HeaderComponent, setReportId: setReportId, queryEndpoint: queryEndpoint, organizationId: organizationId, queryHeaders: queryHeaders, withCredentials: withCredentials }));
321
662
  }
322
663
  };
323
664
  return ((0, jsx_runtime_1.jsxs)("div", { style: {
@@ -508,17 +849,22 @@ function classNames(...classes) {
508
849
  return classes.filter(Boolean).join(" ");
509
850
  }
510
851
  exports.classNames = classNames;
511
- function Dashboards({ setReportId, TextInputComponent, ButtonComponent, SecondaryButtonComponent, OrganizationSelectComponent, ModalComponent, SelectComponent, queryEndpoint, queryHeaders, organizationId, withCredentials, }) {
852
+ function Dashboards({ setReportId, TextInputComponent, ButtonComponent, SecondaryButtonComponent, OrganizationSelectComponent, ModalComponent, SelectComponent, queryEndpoint, queryHeaders, organizationId, HeaderComponent, withCredentials, }) {
512
853
  const [organizations] = (0, react_1.useContext)(OrganizationsContext);
854
+ const [client] = (0, react_1.useContext)(ClientContext);
855
+ const [organization, setOrganization] = (0, react_1.useContext)(OrganizationContext);
513
856
  const [environment] = (0, react_1.useContext)(EnvironmentContext);
514
857
  const [dashboards, setDashboards] = (0, react_1.useState)([]);
515
858
  const [selectedDashboard, setSelectedDashboard] = (0, react_1.useState)("");
859
+ const [selectedEditDashboard, setSelectedEditDashboard] = (0, react_1.useState)("");
860
+ const [editDashboardData, setEditDashboardData] = (0, react_1.useState)(null);
516
861
  const [addFilterModalIsOpen, setAddFilterModalIsOpen] = (0, react_1.useState)(false);
862
+ const [isAddDashboardModalOpen, setIsAddDashboardModalOpen] = (0, react_1.useState)(false);
517
863
  const [editFilterModalIsOpen, setEditFilterModalIsOpen] = (0, react_1.useState)(false);
518
864
  const [dashboardData, setDashboardData] = (0, react_1.useState)(null);
519
865
  const [activeComponent, setActiveComponent] = (0, react_1.useContext)(ActiveComponentContext);
866
+ const [isEditDashboardModalOpen, setIsEditDashboardModalOpen] = (0, react_1.useState)(false);
520
867
  const [isOpen, setIsOpen] = (0, react_1.useState)(false);
521
- const [client] = (0, react_1.useContext)(ClientContext);
522
868
  // const navigate = useNavigate();
523
869
  // useEffect(() => {
524
870
  // if (customValue.length && customValue !== id && !userTyping) {
@@ -529,28 +875,28 @@ function Dashboards({ setReportId, TextInputComponent, ButtonComponent, Secondar
529
875
  // // navigate("/");
530
876
  // // }
531
877
  // }, [customValue, userTyping]);
878
+ async function getDashNames() {
879
+ const url = `https://quill-344421.uc.r.appspot.com/dashnames/${client._id}/`;
880
+ const response2 = await fetch(url, {
881
+ method: "GET",
882
+ headers: {
883
+ Authorization: "Bearer ",
884
+ environment: environment,
885
+ },
886
+ });
887
+ // If you need to retrieve the JSON data from the response:
888
+ const data = await response2.json();
889
+ const dashNames = data.dashboardNames.map((elem) => {
890
+ if (!elem) {
891
+ return { name: "null" };
892
+ }
893
+ return { name: elem };
894
+ });
895
+ setDashboards(dashNames);
896
+ setSelectedDashboard(dashNames[0].name);
897
+ }
532
898
  (0, react_1.useEffect)(() => {
533
899
  let isSubscribed = true;
534
- async function getDashNames() {
535
- const url = `https://quill-344421.uc.r.appspot.com/dashnames/${client._id}/`;
536
- const response2 = await fetch(url, {
537
- method: "GET",
538
- headers: {
539
- Authorization: "Bearer ",
540
- environment: environment,
541
- },
542
- });
543
- // If you need to retrieve the JSON data from the response:
544
- const data = await response2.json();
545
- const dashNames = data.dashboardNames.map((elem) => {
546
- if (!elem) {
547
- return { name: "null" };
548
- }
549
- return { name: elem };
550
- });
551
- setDashboards(dashNames);
552
- setSelectedDashboard(dashNames[0].name);
553
- }
554
900
  if (isSubscribed) {
555
901
  getDashNames();
556
902
  }
@@ -563,11 +909,15 @@ function Dashboards({ setReportId, TextInputComponent, ButtonComponent, Secondar
563
909
  // window.location.reload();
564
910
  // }
565
911
  // }, [id]);
912
+ const handleSetOrganization = (org) => {
913
+ setOrganization(null);
914
+ setTimeout(() => setOrganization(org), 50);
915
+ };
566
916
  (0, react_1.useEffect)(() => {
567
- async function getDashboardData() {
568
- let response2;
917
+ async function getDashboardData(dashboard, setData) {
918
+ let responseData;
569
919
  if (queryEndpoint) {
570
- response2 = await fetch(queryEndpoint, {
920
+ const response = await fetch(queryEndpoint, {
571
921
  method: "POST",
572
922
  headers: {
573
923
  ...queryHeaders,
@@ -577,38 +927,43 @@ function Dashboards({ setReportId, TextInputComponent, ButtonComponent, Secondar
577
927
  metadata: organizationId
578
928
  ? {
579
929
  orgId: organizationId,
580
- name: selectedDashboard,
581
930
  task: "config",
931
+ name: dashboard,
582
932
  }
583
- : { name: selectedDashboard, task: "config" },
933
+ : { task: "config", name: dashboard },
584
934
  }),
585
935
  credentials: withCredentials ? "include" : "omit", // If withCredentials is true, set to 'include'. Otherwise, set to 'omit'.
586
936
  });
937
+ responseData = await response.json(); // If the server returns JSON data
587
938
  }
588
939
  else {
589
- const url = new URL(`https://quill-344421.uc.r.appspot.com/dashconfig/`);
940
+ const url = new URL(`https://quill-344421.uc.r.appspot.com/dashconfig`);
590
941
  // Setting the search parameters for the URL
591
942
  url.search = new URLSearchParams({
592
943
  orgId: organizationId ? organizationId : "",
593
944
  publicKey: client._id,
594
- name: selectedDashboard,
945
+ name: dashboard,
595
946
  }).toString();
596
- response2 = await fetch(url, {
947
+ const response2 = await fetch(url, {
597
948
  method: "GET",
598
949
  headers: {
599
950
  Authorization: "Bearer ",
600
951
  environment: environment,
601
952
  },
602
953
  });
954
+ // If you need to retrieve the JSON data from the response:
955
+ responseData = await response2.json();
603
956
  }
604
- // If you need to retrieve the JSON data from the response:
605
- const data = await response2.json();
606
- setDashboardData(data);
957
+ setData(responseData);
958
+ }
959
+ if (selectedEditDashboard) {
960
+ getDashboardData(selectedEditDashboard, setEditDashboardData);
961
+ return;
607
962
  }
608
963
  if (selectedDashboard && client) {
609
- getDashboardData();
964
+ getDashboardData(selectedDashboard, setDashboardData);
610
965
  }
611
- }, [selectedDashboard, organizationId, client]);
966
+ }, [selectedDashboard, selectedEditDashboard, organizationId, client]);
612
967
  return ((0, jsx_runtime_1.jsxs)("div", { style: {
613
968
  display: "flex",
614
969
  flexDirection: "column",
@@ -669,16 +1024,16 @@ function Dashboards({ setReportId, TextInputComponent, ButtonComponent, Secondar
669
1024
  marginBottom: "4px",
670
1025
  fontWeight: "600",
671
1026
  color: exports.theme.secondaryTextColor,
672
- }, children: "Dashboard" }), (0, jsx_runtime_1.jsx)(SelectComponent, { options: dashboards.length
1027
+ }, children: "Dashboard" }), (0, jsx_runtime_1.jsx)(SelectComponent, { defaultValue: "", options: dashboards.length
673
1028
  ? dashboards.map((elem) => {
674
1029
  return { value: elem.name, label: elem.name };
675
1030
  })
676
- : [], onChange: (e) => setSelectedDashboard(e.target.value), value: selectedDashboard })] }), (0, jsx_runtime_1.jsx)("div", { style: {
1031
+ : [], onChange: (e) => setSelectedDashboard(e), value: selectedDashboard ? selectedDashboard : "" })] }), (0, jsx_runtime_1.jsxs)("div", { style: {
677
1032
  minWidth: 238 - 120,
678
1033
  gap: 12,
679
1034
  display: "flex",
680
1035
  flexDirection: "row",
681
- }, children: (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: "Create report", onClick: () => setActiveComponent("SQL editor") }) })] }) })] })] }) }), (0, jsx_runtime_1.jsx)("div", { style: { paddingTop: "190px", display: "inline-block" }, children: selectedDashboard && ((0, jsx_runtime_1.jsx)(react_2.Dashboard
1036
+ }, children: [(0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: "Edit dashboards", onClick: () => setIsEditDashboardModalOpen(true) }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: "Create report", onClick: () => setActiveComponent("SQL editor") })] })] }) })] })] }) }), (0, jsx_runtime_1.jsx)("div", { style: { paddingTop: "190px", display: "inline-block" }, children: selectedDashboard && ((0, jsx_runtime_1.jsx)(react_2.Dashboard
682
1037
  // TODO: CHANGE
683
1038
  , {
684
1039
  // TODO: CHANGE
@@ -692,27 +1047,259 @@ function Dashboards({ setReportId, TextInputComponent, ButtonComponent, Secondar
692
1047
  }, onClickDashboardItem: (elem) => {
693
1048
  setReportId(elem._id);
694
1049
  setActiveComponent("Report");
695
- } })) })] }));
1050
+ } })) }), (0, jsx_runtime_1.jsx)(EditDashboardsModal, { clientId: client._id, isOpen: isEditDashboardModalOpen, setIsOpen: setIsEditDashboardModalOpen, ModalComponent: ModalComponent, ButtonComponent: ButtonComponent, TextInputComponent: TextInputComponent, openEditFilterModal: (dashboardName) => {
1051
+ setSelectedEditDashboard(dashboardName);
1052
+ setEditFilterModalIsOpen(true);
1053
+ // setIsEditDashboardModalOpen(false);
1054
+ }, openAddDashboardModal: () => {
1055
+ setIsAddDashboardModalOpen(true);
1056
+ // setIsEditDashboardModalOpen(false);
1057
+ }, HeaderComponent: HeaderComponent, setDashboardData: setDashboardData, dashboards: dashboards, getDashNames: getDashNames }), (0, jsx_runtime_1.jsx)(EditFiltersModal, { selectedDashboard: selectedEditDashboard, dashboardData: editDashboardData, isOpen: editFilterModalIsOpen, setIsOpen: setEditFilterModalIsOpen, openAddFilterModal: () => {
1058
+ setAddFilterModalIsOpen(true);
1059
+ // setEditFilterModalIsOpen(false);
1060
+ }, client: client, ModalComponent: ModalComponent, ButtonComponent: ButtonComponent, TextInputComponent: TextInputComponent, HeaderComponent: HeaderComponent, SelectComponent: SelectComponent, dashNames: dashboards, setSelectedEditDashboard: setSelectedEditDashboard }), (0, jsx_runtime_1.jsx)(AddFilterModal, { selectedDashboard: selectedEditDashboard, isOpen: addFilterModalIsOpen, setIsOpen: setAddFilterModalIsOpen, client: client, ModalComponent: ModalComponent, TextInputComponent: TextInputComponent, SelectComponent: SelectComponent, HeaderComponent: HeaderComponent, ButtonComponent: ButtonComponent, openAddDashboardModal: () => {
1061
+ setIsAddDashboardModalOpen(true);
1062
+ // setAddFilterModalIsOpen(false);
1063
+ } }), (0, jsx_runtime_1.jsx)(AddDashboardModal, { selectedDashboard: selectedDashboard, isOpen: isAddDashboardModalOpen, setIsOpen: setIsAddDashboardModalOpen, client: client, ModalComponent: ModalComponent, TextInputComponent: TextInputComponent, SelectComponent: SelectComponent, HeaderComponent: HeaderComponent, ButtonComponent: ButtonComponent, dashNames: dashboards, openAddFilterModal: () => {
1064
+ setAddFilterModalIsOpen(true);
1065
+ // setIsAddDashboardModalOpen(false);
1066
+ }, organizationId: organizationId, getDashNames: getDashNames })] }));
696
1067
  }
697
- function EditDashboardsModal({ ModalComponent, isOpen, setIsOpen, clientId }) {
698
- const [dashboards, setDashboards] = (0, react_1.useState)([]);
1068
+ function AddDashboardModal({ selectedDashboard, isOpen, setIsOpen, client, ModalComponent, TextInputComponent, SelectComponent, HeaderComponent, ButtonComponent, dashNames, getDashNames, organizationId, }) {
1069
+ const [selectedDashboardName, setSelectedDashboardName] = (0, react_1.useState)(selectedDashboard.name);
1070
+ const [tables] = (0, react_1.useContext)(TablesContext);
1071
+ const [selectedTable, setSelectedTable] = (0, react_1.useState)(null);
1072
+ const [name, setName] = (0, react_1.useState)("");
1073
+ const [field, setField] = (0, react_1.useState)("");
1074
+ const [filterType, setFilterType] = (0, react_1.useState)("string");
1075
+ const [dateRange, setDateRange] = (0, react_1.useState)([new Date(), new Date()]);
1076
+ const [newFilters, setNewFilters] = (0, react_1.useState)([]);
1077
+ const [newDateFilter, setNewDateFilter] = (0, react_1.useState)(null);
699
1078
  (0, react_1.useEffect)(() => {
700
- async function getDashboards(clientId) {
701
- const url = `https://quill-344421.uc.r.appspot.com/dashs/${clientId}/`;
702
- const response2 = await fetch(url, {
703
- method: "GET",
704
- headers: {
705
- Authorization: "Bearer ", // Ensure you append your token after 'Bearer ' if needed
706
- },
1079
+ if (tables.length) {
1080
+ setSelectedTable(tables[0]);
1081
+ // setField(tables[0].columns.map((elem) => elem.name));
1082
+ setField(tables[0].columns[0].name);
1083
+ }
1084
+ }, [tables]);
1085
+ const handleDeleteFilter = async (filter) => {
1086
+ setNewFilters(newFilters.filter((f) => f !== filter));
1087
+ };
1088
+ const handleAddDashboardSubmit = async () => {
1089
+ if (!selectedDashboardName ||
1090
+ newFilters.some((filter) => !filter.label) ||
1091
+ (newDateFilter && newDateFilter.label)) {
1092
+ alert("Empty labels");
1093
+ return;
1094
+ }
1095
+ if (newFilters.some((filter) => !filter.field)) {
1096
+ alert("Empty fields");
1097
+ return;
1098
+ }
1099
+ if (!selectedTable || !field) {
1100
+ return;
1101
+ }
1102
+ if (dashNames &&
1103
+ dashNames.length > 0 &&
1104
+ dashNames.some((dashName) => dashName.name === selectedDashboardName)) {
1105
+ alert("Dashboard name already taken!");
1106
+ return;
1107
+ }
1108
+ let updatedFilters = newFilters.map((filter) => {
1109
+ const filterType = getPostgresBasicType(selectedTable.columns.find((col) => col.name === filter.field));
1110
+ return {
1111
+ table: selectedTable.name,
1112
+ field: filter.field,
1113
+ labelField: filter.field,
1114
+ label: filter.label,
1115
+ filterType,
1116
+ };
1117
+ });
1118
+ const fieldsSet = new Set();
1119
+ const hasDuplicateField = updatedFilters.some((filter) => {
1120
+ if (fieldsSet.has(filter.field)) {
1121
+ return true;
1122
+ }
1123
+ else {
1124
+ fieldsSet.add(filter.field);
1125
+ return false;
1126
+ }
1127
+ });
1128
+ if (hasDuplicateField) {
1129
+ alert("Maximum of one filter per field");
1130
+ return;
1131
+ }
1132
+ let allValid = true;
1133
+ updatedFilters.forEach((filter) => {
1134
+ if (filter.filterType !== "string" && filter.filterType !== "date") {
1135
+ allValid = false;
1136
+ console.error(`Invalid filterType found: ${filter.filterType}`);
1137
+ }
1138
+ });
1139
+ if (!allValid) {
1140
+ alert("We only support string and filters.");
1141
+ return;
1142
+ }
1143
+ if (updatedFilters.filter((filter) => filter.filterType === "date").length > 1) {
1144
+ alert("More than one date filter");
1145
+ return;
1146
+ }
1147
+ let responseData;
1148
+ const url = `https://quill-344421.uc.r.appspot.com/newdash/${client._id}/`;
1149
+ const body = newDateFilter && Object.keys(newDateFilter).length
1150
+ ? {
1151
+ dateFilter: newDateFilter,
1152
+ newDashboardName: selectedDashboardName,
1153
+ filters: updatedFilters,
1154
+ organizationId,
1155
+ }
1156
+ : {
1157
+ newDashboardName: selectedDashboardName,
1158
+ filters: updatedFilters,
1159
+ organizationId,
1160
+ };
1161
+ const headers = {
1162
+ "Content-Type": "application/json",
1163
+ Authorization: `Bearer `,
1164
+ };
1165
+ try {
1166
+ const response = await fetch(url, {
1167
+ method: "POST",
1168
+ headers: headers,
1169
+ body: JSON.stringify(body),
707
1170
  });
708
- // If you need to retrieve the JSON data from the response:
709
- const data = await response2.json();
1171
+ if (!response.ok) {
1172
+ throw new Error(`HTTP error! Status: ${response.status}`);
1173
+ }
1174
+ responseData = await response.json();
1175
+ }
1176
+ catch (e) {
1177
+ console.log("error");
1178
+ }
1179
+ if (responseData) {
1180
+ setIsOpen(false);
1181
+ setName("");
1182
+ setSelectedDashboardName("");
1183
+ setNewFilters([]);
1184
+ setNewDateFilter(null);
1185
+ getDashNames();
1186
+ return;
1187
+ }
1188
+ };
1189
+ if (!selectedTable) {
1190
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
1191
+ }
1192
+ const handleAddFilter = async () => {
1193
+ setNewFilters([...newFilters, { label: "", field }]);
1194
+ };
1195
+ return ((0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: isOpen, close: () => setIsOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(TextInputComponent, { placeholder: "Enter Dashboard Name...", onChange: (e) => setSelectedDashboardName(e.target.value), value: selectedDashboardName }), (0, jsx_runtime_1.jsxs)("div", { style: {
1196
+ display: "flex",
1197
+ flexDirection: "column",
1198
+ alignItems: "center",
1199
+ }, children: [newFilters.map((filter, index) => {
1200
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", flexDirection: "row" }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", flexDirection: "column" }, children: [(0, jsx_runtime_1.jsx)("h2", { children: "Label" }), (0, jsx_runtime_1.jsx)(TextInputComponent, { value: filter.label, onChange: (e) => {
1201
+ const updatedFilters = newFilters.map((otherFilter, i) => index === i
1202
+ ? { ...otherFilter, label: e.target.value }
1203
+ : otherFilter);
1204
+ setNewFilters(updatedFilters);
1205
+ } })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", flexDirection: "column" }, children: [(0, jsx_runtime_1.jsx)("h4", { children: "Field" }), (0, jsx_runtime_1.jsx)("div", { style: {
1206
+ display: "flex",
1207
+ flexDirection: "column",
1208
+ alignItems: "center",
1209
+ }, children: (0, jsx_runtime_1.jsxs)("div", { style: {
1210
+ display: "flex",
1211
+ flexDirection: "row",
1212
+ alignItems: "center",
1213
+ }, children: [(0, jsx_runtime_1.jsx)(SelectComponent, { defaultValue: "", value: filter && filter.field ? filter.field : "", options: selectedTable.columns.map((column) => {
1214
+ return { label: column.name, value: column.name };
1215
+ }), onChange: (e) => {
1216
+ const updatedFilters = newFilters.map((otherFilter, i) => index === i
1217
+ ? { ...otherFilter, field: e }
1218
+ : otherFilter);
1219
+ setNewFilters(updatedFilters);
1220
+ } }), (0, jsx_runtime_1.jsx)("div", { onClick: () => handleDeleteFilter(filter), style: {
1221
+ height: 42,
1222
+ width: 42,
1223
+ alignItems: "center",
1224
+ justifyContent: "center",
1225
+ display: "flex",
1226
+ }, children: (0, jsx_runtime_1.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "#4C5462", width: "20", height: "20", children: (0, jsx_runtime_1.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));
1227
+ }), (0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: handleAddFilter, label: "Add new filter +" }), (0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: handleAddDashboardSubmit, label: "Add Dashboard +" })] })] }) }));
1228
+ }
1229
+ function EditDashboardsModal({ ModalComponent, TextInputComponent, isOpen, setIsOpen, clientId, ButtonComponent, openEditFilterModal, openAddDashboardModal, HeaderComponent, setDashboardData, dashboards, getDashNames, }) {
1230
+ // const [dashboards, setDashboards] = useState([]);
1231
+ // useEffect(() => {
1232
+ // async function getDashboards(clientId) {
1233
+ // const url = `https://quill-344421.uc.r.appspot.com/dashnames/${clientId}/`;
1234
+ // const response2 = await fetch(url, {
1235
+ // method: "GET",
1236
+ // headers: {
1237
+ // Authorization: "Bearer ", // Ensure you append your token after 'Bearer ' if needed
1238
+ // },
1239
+ // });
1240
+ // // If you need to retrieve the JSON data from the response:
1241
+ // const data = await response2.json();
1242
+ // setDashboards(data);
1243
+ // }
1244
+ // if (clientId) {
1245
+ // getDashboards(clientId);
1246
+ // }
1247
+ // }, [clientId]);
1248
+ async function handleDeleteDashboard(dashboardName) {
1249
+ const url = `https://quill-344421.uc.r.appspot.com/dashdelete/${clientId}/`;
1250
+ const body = {
1251
+ name: dashboardName,
1252
+ };
1253
+ const headers = {
1254
+ "Content-Type": "application/json",
1255
+ Authorization: `Bearer `,
1256
+ };
1257
+ try {
1258
+ const response = await fetch(url, {
1259
+ method: "POST",
1260
+ headers: headers,
1261
+ body: JSON.stringify(body),
1262
+ });
1263
+ if (!response.ok) {
1264
+ throw new Error(`HTTP error! Status: ${response.status}`);
1265
+ }
1266
+ const responseData = await response.json();
1267
+ if (responseData) {
1268
+ getDashNames();
1269
+ return;
1270
+ }
710
1271
  }
711
- if (clientId) {
712
- getDashboards(clientId);
1272
+ catch (e) {
1273
+ console.log("error", e);
713
1274
  }
714
- }, [clientId]);
715
- return ((0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: isOpen, close: () => setIsOpen(false), children: (0, jsx_runtime_1.jsx)("div", {}) }));
1275
+ }
1276
+ return ((0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: isOpen, close: () => setIsOpen(false), children: (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { style: {
1277
+ display: "flex",
1278
+ flexDirection: "column",
1279
+ }, children: dashboards &&
1280
+ dashboards.map((dashboardName, index) => {
1281
+ return ((0, jsx_runtime_1.jsxs)("div", { style: {
1282
+ display: "flex",
1283
+ flexDirection: "row",
1284
+ }, children: [(0, jsx_runtime_1.jsx)("div", { style: {
1285
+ display: "flex",
1286
+ flexDirection: "column",
1287
+ }, children: (0, jsx_runtime_1.jsx)("div", { style: {
1288
+ marginRight: 12,
1289
+ }, children: dashboardName.name }) }), (0, jsx_runtime_1.jsxs)("div", { style: {
1290
+ display: "flex",
1291
+ flexDirection: "column",
1292
+ }, children: [" ", (0, jsx_runtime_1.jsxs)("div", { style: {
1293
+ display: "flex",
1294
+ flexDirection: "row",
1295
+ alignItems: "flex-end",
1296
+ }, children: [(0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: () => openEditFilterModal(dashboardName.name), label: "Edit" }), (0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: () => handleDeleteDashboard(dashboardName.name), label: "Delete" })] })] })] }, dashboardName + index));
1297
+ }) }), (0, jsx_runtime_1.jsx)("div", { style: {
1298
+ display: "flex",
1299
+ flexDirection: "column",
1300
+ alignItems: "center",
1301
+ justifyContent: "center",
1302
+ }, children: (0, jsx_runtime_1.jsx)(ButtonComponent, { onClick: openAddDashboardModal, label: "Create new dashboard" }) })] }) }));
716
1303
  }
717
1304
  function DropdownMenu({ items, setSelected, selected, filterKey }) {
718
1305
  return ((0, jsx_runtime_1.jsx)("select", { onChange: (e) => {
@@ -720,32 +1307,7 @@ function DropdownMenu({ items, setSelected, selected, filterKey }) {
720
1307
  }, value: selected ? selected.name : "", children: items.slice(0, 50).map((item) => ((0, jsx_runtime_1.jsx)("option", { value: item.name, children: item.name }, item.name))) }));
721
1308
  }
722
1309
  exports.DropdownMenu = DropdownMenu;
723
- function defineEditorTheme(monaco, theme) {
724
- monaco.editor.defineTheme("onedark", {
725
- base: theme.darkMode ? "vs-dark" : "vs",
726
- inherit: true,
727
- rules: [
728
- {
729
- token: "comment",
730
- foreground: "#5d7988",
731
- fontStyle: "italic",
732
- },
733
- { token: "constant", foreground: "#e06c75" },
734
- ],
735
- colors: {
736
- "editor.background": "#F9F9F9",
737
- },
738
- });
739
- }
740
- function setEditorTheme(editor, monaco) {
741
- try {
742
- monaco.editor.setTheme("onedark");
743
- }
744
- catch (e) {
745
- console.log("ERROR: ", e);
746
- }
747
- }
748
- function Tables({ TextInputComponent, ButtonComponent, SecondaryButtonComponent, ModalComponent, SelectComponent, }) {
1310
+ function Tables({ TextInputComponent, ButtonComponent, SecondaryButtonComponent, ModalComponent, SelectComponent, queryEndpoint, queryHeaders, withCredentials, }) {
749
1311
  const [tables, setTables] = (0, react_1.useState)([]);
750
1312
  const [modalIsOpen, setIsOpen] = (0, react_1.useState)(false);
751
1313
  const [editModalIsOpen, setEditModalIsOpen] = (0, react_1.useState)(false);
@@ -755,7 +1317,6 @@ function Tables({ TextInputComponent, ButtonComponent, SecondaryButtonComponent,
755
1317
  const [editName, setEditName] = (0, react_1.useState)("");
756
1318
  const [editViewQuery, setEditViewQuery] = (0, react_1.useState)("");
757
1319
  const [client] = (0, react_1.useContext)(ClientContext);
758
- const [code, setCode] = (0, react_1.useState)(``);
759
1320
  const [tableToBeDeleted, setTableToBeDeleted] = (0, react_1.useState)("");
760
1321
  const [deleteName, setDeleteName] = (0, react_1.useState)("");
761
1322
  const [deleteModalIsOpen, setDeleteModalIsOpen] = (0, react_1.useState)(false);
@@ -764,7 +1325,7 @@ function Tables({ TextInputComponent, ButtonComponent, SecondaryButtonComponent,
764
1325
  };
765
1326
  const openModal = () => {
766
1327
  setIsOpen(true);
767
- setCode("");
1328
+ setEditViewQuery("");
768
1329
  };
769
1330
  const closeModal = () => {
770
1331
  setIsOpen(false);
@@ -781,21 +1342,47 @@ function Tables({ TextInputComponent, ButtonComponent, SecondaryButtonComponent,
781
1342
  setEditName(table.name);
782
1343
  setEditViewQuery(table.viewQuery);
783
1344
  setEditViewId(table._id);
784
- setCode(table.viewQuery);
785
1345
  };
786
1346
  const handleDeleteTable = async () => {
787
1347
  if (deleteName !== tableToBeDeleted) {
788
1348
  alert("Table names must match");
789
1349
  return;
790
1350
  }
791
- const response = await fetch(`https://quill-344421.uc.r.appspot.com/table/${client._id}/`, {
792
- method: "POST",
793
- headers: { Authorization: `Bearer ` },
794
- body: JSON.stringify({
795
- id: editViewId,
796
- deleted: true,
797
- }),
798
- });
1351
+ if (!editViewId) {
1352
+ console.log("No view id found");
1353
+ return;
1354
+ }
1355
+ let response;
1356
+ if (queryEndpoint) {
1357
+ response = await fetch(queryEndpoint, {
1358
+ method: "POST",
1359
+ headers: {
1360
+ "Content-Type": "application/json",
1361
+ ...queryHeaders,
1362
+ },
1363
+ body: JSON.stringify({
1364
+ metadata: {
1365
+ task: "view",
1366
+ id: editViewId,
1367
+ deleted: true,
1368
+ },
1369
+ }),
1370
+ credentials: withCredentials ? "include" : "omit", // If withCredentials is true, set to 'include'. Otherwise, set to 'omit'.
1371
+ });
1372
+ }
1373
+ else {
1374
+ response = await fetch(`https://quill-344421.uc.r.appspot.com/table/${client._id}/`, {
1375
+ method: "POST",
1376
+ headers: {
1377
+ "Content-Type": "application/json",
1378
+ Authorization: `Bearer `,
1379
+ },
1380
+ body: JSON.stringify({
1381
+ id: editViewId,
1382
+ deleted: true,
1383
+ }),
1384
+ });
1385
+ }
799
1386
  const data = await response.json();
800
1387
  if (data) {
801
1388
  setDeleteName("");
@@ -836,38 +1423,47 @@ function Tables({ TextInputComponent, ButtonComponent, SecondaryButtonComponent,
836
1423
  alert("Please enter a table query.");
837
1424
  return;
838
1425
  }
839
- if (editViewQuery[editViewQuery.length - 1] === ";") {
840
- const response = await fetch(`https://quill-344421.uc.r.appspot.com/table/${client._id}/`, {
1426
+ if (!editViewId) {
1427
+ alert("Could not save.");
1428
+ return;
1429
+ }
1430
+ let response;
1431
+ if (queryEndpoint) {
1432
+ response = await fetch(queryEndpoint, {
1433
+ method: "POST",
1434
+ headers: {
1435
+ "Content-Type": "application/json",
1436
+ ...queryHeaders,
1437
+ },
1438
+ body: JSON.stringify({
1439
+ metadata: {
1440
+ query: editViewQuery[editViewQuery.length - 1] === ";"
1441
+ ? editViewQuery.slice(0, -1)
1442
+ : editViewQuery,
1443
+ name: editName,
1444
+ task: "view",
1445
+ id: editViewId,
1446
+ },
1447
+ }),
1448
+ credentials: withCredentials ? "include" : "omit", // If withCredentials is true, set to 'include'. Otherwise, set to 'omit'.
1449
+ });
1450
+ }
1451
+ else {
1452
+ response = await fetch(`https://quill-344421.uc.r.appspot.com/table/${client._id}/`, {
841
1453
  method: "POST",
842
1454
  headers: {
843
1455
  "Content-Type": "application/json",
844
1456
  Authorization: `Bearer `,
845
1457
  },
846
1458
  body: JSON.stringify({
847
- viewQuery: editViewQuery.slice(0, -1),
1459
+ viewQuery: editViewQuery[editViewQuery.length - 1] === ";"
1460
+ ? editViewQuery.slice(0, -1)
1461
+ : editViewQuery,
848
1462
  name: editName,
849
1463
  id: editViewId,
850
1464
  }),
851
1465
  });
852
- const data = await response.json();
853
- if (data) {
854
- closeEditModal();
855
- getTables();
856
- }
857
- return;
858
1466
  }
859
- const response = await fetch(`https://quill-344421.uc.r.appspot.com/table/${client._id}/`, {
860
- method: "POST",
861
- headers: {
862
- "Content-Type": "application/json",
863
- Authorization: `Bearer `,
864
- },
865
- body: JSON.stringify({
866
- viewQuery: editViewQuery,
867
- name: editName,
868
- id: editViewId,
869
- }),
870
- });
871
1467
  const data = await response.json();
872
1468
  if (data) {
873
1469
  closeEditModal();
@@ -879,40 +1475,45 @@ function Tables({ TextInputComponent, ButtonComponent, SecondaryButtonComponent,
879
1475
  alert("Please enter a table name.");
880
1476
  return;
881
1477
  }
882
- if (!code.length) {
1478
+ if (!editViewQuery.length) {
883
1479
  alert("Please enter a table query.");
884
1480
  return;
885
1481
  }
886
- if (code[code.length - 1] === ";") {
887
- const response = await fetch(`https://quill-344421.uc.r.appspot.com/table/${client._id}/`, {
1482
+ let response;
1483
+ if (queryEndpoint) {
1484
+ response = await fetch(queryEndpoint, {
1485
+ method: "POST",
1486
+ headers: {
1487
+ "Content-Type": "application/json",
1488
+ ...queryHeaders,
1489
+ },
1490
+ body: JSON.stringify({
1491
+ metadata: {
1492
+ query: editViewQuery[editViewQuery.length - 1] === ";"
1493
+ ? editViewQuery.slice(0, -1)
1494
+ : editViewQuery,
1495
+ name: name,
1496
+ task: "view",
1497
+ },
1498
+ }),
1499
+ credentials: withCredentials ? "include" : "omit", // If withCredentials is true, set to 'include'. Otherwise, set to 'omit'.
1500
+ });
1501
+ }
1502
+ else {
1503
+ response = await fetch(`https://quill-344421.uc.r.appspot.com/table/${client._id}/`, {
888
1504
  method: "POST",
889
1505
  headers: {
890
1506
  "Content-Type": "application/json",
891
1507
  Authorization: `Bearer `,
892
1508
  },
893
1509
  body: JSON.stringify({
894
- viewQuery: code.slice(0, -1),
1510
+ viewQuery: editViewQuery[editViewQuery.length - 1] === ";"
1511
+ ? editViewQuery.slice(0, -1)
1512
+ : editViewQuery,
895
1513
  name: name,
896
1514
  }),
897
1515
  });
898
- const data = await response.json();
899
- if (data) {
900
- closeModal();
901
- getTables();
902
- }
903
- return;
904
1516
  }
905
- const response = await fetch(`https://quill-344421.uc.r.appspot.com/table/${client._id}/`, {
906
- method: "POST",
907
- headers: {
908
- "Content-Type": "application/json",
909
- Authorization: `Bearer `,
910
- },
911
- body: JSON.stringify({
912
- viewQuery: code,
913
- name: name,
914
- }),
915
- });
916
1517
  const data = await response.json();
917
1518
  if (data) {
918
1519
  closeModal();
@@ -949,13 +1550,13 @@ function Tables({ TextInputComponent, ButtonComponent, SecondaryButtonComponent,
949
1550
  borderTopRightRadius: 0,
950
1551
  borderBottomRightRadius: 0,
951
1552
  overflow: "hidden",
952
- }, children: (0, jsx_runtime_1.jsx)(react_3.default, { height: "500px", width: "100%", defaultLanguage: "pgsql", defaultValue: "", value: code, loading: (0, jsx_runtime_1.jsx)("div", {}), options: {
1553
+ }, children: (0, jsx_runtime_1.jsx)(react_3.default, { height: "500px", width: "100%", defaultLanguage: "pgsql", defaultValue: "", value: editViewQuery, loading: (0, jsx_runtime_1.jsx)("div", {}), options: {
953
1554
  wordWrap: "on",
954
1555
  minimap: {
955
1556
  enabled: false,
956
1557
  },
957
1558
  padding: { top: 16 },
958
- }, onChange: (query) => setCode(query), beforeMount: (monaco) => defineEditorTheme(monaco, exports.theme), onMount: setEditorTheme }) }), (0, jsx_runtime_1.jsx)(ButtonComponent, { label: "Add view +", onClick: handleAddTable })] }) }), (0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: editModalIsOpen, close: closeEditModal, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col p-[6px]", children: [(0, jsx_runtime_1.jsxs)("div", { style: {
1559
+ }, onChange: (query) => setEditViewQuery(query), beforeMount: (monaco) => defineEditorTheme(monaco, exports.theme), onMount: setEditorTheme }) }), (0, jsx_runtime_1.jsx)(ButtonComponent, { label: "Add view +", onClick: handleAddTable })] }) }), (0, jsx_runtime_1.jsx)(ModalComponent, { isOpen: editModalIsOpen, close: closeEditModal, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col p-[6px]", children: [(0, jsx_runtime_1.jsxs)("div", { style: {
959
1560
  display: "flex",
960
1561
  flexDirection: "row",
961
1562
  alignItems: "center",
@@ -999,13 +1600,13 @@ function Tables({ TextInputComponent, ButtonComponent, SecondaryButtonComponent,
999
1600
  borderTopRightRadius: 0,
1000
1601
  borderBottomRightRadius: 0,
1001
1602
  overflow: "hidden",
1002
- }, children: (0, jsx_runtime_1.jsx)(react_3.default, { height: "300px", width: "520px", defaultLanguage: "pgsql", defaultValue: "", value: code, loading: (0, jsx_runtime_1.jsx)("div", {}), options: {
1603
+ }, children: (0, jsx_runtime_1.jsx)(react_3.default, { height: "300px", width: "520px", defaultLanguage: "pgsql", defaultValue: "", value: editViewQuery, loading: (0, jsx_runtime_1.jsx)("div", {}), options: {
1003
1604
  wordWrap: "on",
1004
1605
  minimap: {
1005
1606
  enabled: false,
1006
1607
  },
1007
1608
  padding: { top: 16 },
1008
- }, onChange: (query) => setCode(query), beforeMount: (monaco) => defineEditorTheme(monaco, exports.theme), onMount: setEditorTheme }) }), (0, jsx_runtime_1.jsxs)("div", { style: {
1609
+ }, onChange: (query) => setEditViewQuery(query), beforeMount: (monaco) => defineEditorTheme(monaco, exports.theme), onMount: setEditorTheme }) }), (0, jsx_runtime_1.jsxs)("div", { style: {
1009
1610
  display: "flex",
1010
1611
  flexDirection: "row",
1011
1612
  alignItems: "center",
@@ -1065,7 +1666,7 @@ function Modal({ isOpen, onRequestClose, children }) {
1065
1666
  // zIndex: 1000,
1066
1667
  }, children: children })] }));
1067
1668
  }
1068
- function TableCell({ table, clickTableCell }) {
1669
+ function TableCell({ table, clickTableCell, key }) {
1069
1670
  const handleClickTableCell = () => {
1070
1671
  clickTableCell(table);
1071
1672
  };
@@ -1085,7 +1686,7 @@ function TableCell({ table, clickTableCell }) {
1085
1686
  maxWidth: 520,
1086
1687
  // lineHeight: "1.3em",
1087
1688
  // height: "1.3em",
1088
- }, children: tokens.map((line, i) => ((0, jsx_runtime_1.jsx)("div", { ...getLineProps({ line, key: i }), children: line.map((token, key) => ((0, jsx_runtime_1.jsx)("span", { ...getTokenProps({ token, key }) }, key))) }, i))) })) })] }));
1689
+ }, children: tokens.map((line, i) => ((0, jsx_runtime_1.jsx)("div", { ...getLineProps({ line, key: i }), children: line.map((token, key) => ((0, jsx_runtime_1.jsx)("span", { ...getTokenProps({ token, key }) }, key))) }, i))) })) })] }, table.displayName));
1089
1690
  }
1090
1691
  function QueryEditor({ TextInputComponent, ButtonComponent, SecondaryButtonComponent, ModalComponent, SelectComponent, }) {
1091
1692
  const [customerId, setCustomerId] = (0, react_1.useState)("");
@@ -1149,75 +1750,6 @@ function QueryEditor({ TextInputComponent, ButtonComponent, SecondaryButtonCompo
1149
1750
  };
1150
1751
  }, [environment]);
1151
1752
  // const navigate = useNavigate();
1152
- const editChart = async ({ report, values, yAxisFields, columns, query }) => {
1153
- const { publicKey, customerId, authToken } = client;
1154
- const { xAxisLabel, yAxisLabel, chartName, chartType, xAxisField, xAxisFormat, dashboardName, dateFieldTable, dateField, } = values;
1155
- if (!chartName) {
1156
- alert("Please enter a chart name");
1157
- return;
1158
- }
1159
- for (let i = 0; i < yAxisFields.length; i++) {
1160
- if (!yAxisFields[i].label && chartType !== "pie") {
1161
- alert(`Please enter a label for column '${yAxisFields[i].field}'`);
1162
- return;
1163
- }
1164
- }
1165
- if (!client || !organization) {
1166
- return;
1167
- }
1168
- const response = await fetch(`https://quill-344421.uc.r.appspot.com/dashedit/${client._id}/${organization.id}/`, {
1169
- method: "POST",
1170
- headers: {
1171
- "Content-Type": "application/json",
1172
- Authorization: `Bearer ${authToken}`,
1173
- environment: environment || undefined,
1174
- },
1175
- body: JSON.stringify({
1176
- name: chartName,
1177
- xAxisField,
1178
- yAxisFields,
1179
- xAxisLabel,
1180
- xAxisFormat,
1181
- yAxisLabel,
1182
- chartType,
1183
- dashboardName,
1184
- columns,
1185
- dateField: { table: dateFieldTable, field: dateField },
1186
- query: query,
1187
- }),
1188
- });
1189
- const responseData = await response.json();
1190
- if (!responseData) {
1191
- return;
1192
- }
1193
- // setDashboard((dashboard) => {
1194
- // return {
1195
- // ...dashboard,
1196
- // [response.data._id]: { ...existingVisualization, ...response.data }
1197
- // }
1198
- // })
1199
- setIsOpen(false);
1200
- setActiveComponent("/Dashboards");
1201
- };
1202
- const handleRunSqlPrompt = async () => {
1203
- const { _id } = client;
1204
- setSqlResponseLoading(true);
1205
- const response = await fetch(`https://quill-344421.uc.r.appspot.com/quillai`, {
1206
- method: "POST",
1207
- headers: {
1208
- Authorization: `Bearer `,
1209
- environment: environment,
1210
- "Content-Type": "application/json", // Important when sending JSON
1211
- },
1212
- body: JSON.stringify({
1213
- initialQuestion: sqlPrompt,
1214
- publicKey: _id,
1215
- }),
1216
- });
1217
- const responseData = await response.json();
1218
- setQuery(responseData.message);
1219
- setSqlResponseLoading(false);
1220
- };
1221
1753
  const handleRunQuery = async () => {
1222
1754
  const { _id } = client;
1223
1755
  try {
@@ -1501,11 +2033,38 @@ const FORMAT_OPTIONS = [
1501
2033
  { value: "percent", label: "percent" },
1502
2034
  { value: "string", label: "string" },
1503
2035
  ];
1504
- function Report({ reportId, saveDashboardItem, isOpen, setIsOpen, isEditQueryOpen, setIsEditQueryOpen, SecondaryButtonComponent, ModalComponent, deleteReport, updateQuery, }) {
2036
+ function Report({ reportId, saveDashboardItem, isOpen, setIsOpen, isEditQueryOpen, setIsEditQueryOpen, SecondaryButtonComponent, ButtonComponent, deleteReport, updateQuery, }) {
1505
2037
  const { data, loading, error } = (0, react_2.useQuill)(reportId);
1506
2038
  const [client] = (0, react_1.useContext)(ClientContext);
1507
2039
  const [activeQuery, setActiveQuery] = (0, react_1.useContext)(ActiveQueryContext);
1508
2040
  const [activeComponent, setActiveComponent] = (0, react_1.useContext)(ActiveComponentContext);
2041
+ const downloadCSV = () => {
2042
+ // report.rows
2043
+ if (!data) {
2044
+ return;
2045
+ }
2046
+ const json = data.rows; // JSON data passed as a prop
2047
+ const fields = Object.keys(json[0]); // Assumes all objects have same keys
2048
+ const csvRows = [];
2049
+ // Header row
2050
+ csvRows.push(fields.join(","));
2051
+ // Data rows
2052
+ for (let row of json) {
2053
+ let values = fields.map((field) => JSON.stringify(row[field] || ""));
2054
+ csvRows.push(values.join(","));
2055
+ }
2056
+ // Create CSV string and create a 'blob' with it
2057
+ const csvString = csvRows.join("\r\n");
2058
+ const csvBlob = new Blob([csvString], { type: "text/csv" });
2059
+ // Create a download link and click it
2060
+ const downloadLink = document.createElement("a");
2061
+ downloadLink.download = "download.csv";
2062
+ downloadLink.href = URL.createObjectURL(csvBlob);
2063
+ downloadLink.style.display = "none";
2064
+ document.body.appendChild(downloadLink);
2065
+ downloadLink.click();
2066
+ document.body.removeChild(downloadLink);
2067
+ };
1509
2068
  const goBack = () => {
1510
2069
  setActiveComponent("Dashboards");
1511
2070
  };
@@ -1533,11 +2092,11 @@ function Report({ reportId, saveDashboardItem, isOpen, setIsOpen, isEditQueryOpe
1533
2092
  }, children: [(0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: "Edit chart", onClick: () => setIsOpen(true) }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: "Edit query", onClick: () => setIsEditQueryOpen(true) }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: "Open query", onClick: () => {
1534
2093
  setActiveQuery(data.queryString);
1535
2094
  setActiveComponent("SQL editor");
1536
- } }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: "Delete", onClick: deleteReport })] }), (0, jsx_runtime_1.jsx)(react_2.Table
2095
+ } }), (0, jsx_runtime_1.jsx)(SecondaryButtonComponent, { label: "Delete", onClick: deleteReport })] }), data.chartType !== "table" && ((0, jsx_runtime_1.jsx)(react_2.Table
1537
2096
  // containerStyle={{ width: "80vw", height: 1100 }}
1538
2097
  , {
1539
2098
  // containerStyle={{ width: "80vw", height: 1100 }}
1540
- containerStyle: { height: 400, width: "100%", marginTop: 24 }, chartId: reportId }), (0, jsx_runtime_1.jsx)(react_2.AddToDashboardModal, { isOpen: isOpen, setIsOpen: setIsOpen, rows: data.rows, columns: data.columns, fields: data.fields, query: data.queryString, report: data, ModalComponent: ModalComponent, showTableFormatOptions: true, showDateFieldOptions: true, showAccessControlOptions: true }), (0, jsx_runtime_1.jsx)(EditQueryModal, { query: data.queryString, report: data, isOpen: isEditQueryOpen, setIsOpen: setIsEditQueryOpen, updateQuery: updateQuery })] }));
2099
+ containerStyle: { height: 400, width: "100%", marginTop: 24 }, chartId: reportId })), (0, jsx_runtime_1.jsx)(EditVisualizationModal, { isOpen: isOpen, setIsOpen: setIsOpen, report: data, data: data.rows, query: data.queryString, columns: data.columns, fields: data.fields }), (0, jsx_runtime_1.jsx)(EditQueryModal, { query: data.queryString, report: data, isOpen: isEditQueryOpen, setIsOpen: setIsEditQueryOpen, updateQuery: updateQuery })] }));
1541
2100
  }
1542
2101
  function EditQueryModal({ query, report, isOpen, setIsOpen, updateQuery }) {
1543
2102
  const [newQuery, setNewQuery] = (0, react_1.useState)(query);
@@ -1591,7 +2150,7 @@ function EditVisualizationModal({ isOpen, setIsOpen, report, columns, data, fiel
1591
2150
  }
1592
2151
  return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: isOpen && ((0, jsx_runtime_1.jsxs)("div", { className: "fixed inset-0 overflow-y-auto relative", style: { zIndex: 120 }, children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 bg-black/30", "aria-hidden": "true", onClick: () => setIsOpen(false) }), (0, jsx_runtime_1.jsx)("div", { className: "flex min-h-full items-center justify-center p-4", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-white px-7 py-7 rounded-lg", children: (0, jsx_runtime_1.jsx)(react_2.AddToDashboardModal, { fields: fields, isOpen: isOpen, setIsOpen: setIsOpen, rows: data, columns: columns, query: query, report: report, showTableFormatOptions: true, showDateFieldOptions: true, showAccessControlOptions: true }) }) })] })) }));
1593
2152
  }
1594
- function ReportWrapper({ SecondaryButtonComponent, ButtonComponent, ModalComponent, SelectComponent, organizationId, }) {
2153
+ function ReportWrapper({ SecondaryButtonComponent, ButtonComponent, ModalComponent, SelectComponent, }) {
1595
2154
  const [organization, setOrganization] = (0, react_1.useContext)(OrganizationContext);
1596
2155
  const [client] = (0, react_1.useContext)(ClientContext);
1597
2156
  const [environment] = (0, react_1.useContext)(EnvironmentContext);
@@ -1628,10 +2187,10 @@ function ReportWrapper({ SecondaryButtonComponent, ButtonComponent, ModalCompone
1628
2187
  if (!reportId) {
1629
2188
  return;
1630
2189
  }
1631
- if (!client || !organizationId) {
2190
+ if (!client) {
1632
2191
  return;
1633
2192
  }
1634
- const url = `https://quill-344421.uc.r.appspot.com/deletedash/${client._id}/${organizationId}/`;
2193
+ const url = `https://quill-344421.uc.r.appspot.com/deletedash/${client._id}/${customerId}/`;
1635
2194
  const requestBody = {
1636
2195
  dashboardItemId: reportId,
1637
2196
  };