@quillsql/react 1.7.5 → 1.7.7

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 (79) hide show
  1. package/lib/Chart.d.ts +1 -1
  2. package/lib/Chart.js +107 -50
  3. package/lib/Chart.js.map +1 -1
  4. package/lib/Dashboard.d.ts +36 -1
  5. package/lib/Dashboard.js +107 -37
  6. package/lib/Dashboard.js.map +1 -1
  7. package/lib/ReportBuilder.js +117 -41
  8. package/lib/ReportBuilder.js.map +1 -1
  9. package/lib/SQLEditor.js +80 -29
  10. package/lib/SQLEditor.js.map +1 -1
  11. package/lib/Table.js +31 -16
  12. package/lib/Table.js.map +1 -1
  13. package/lib/components/BigModal/BigModal.js +1 -0
  14. package/lib/components/BigModal/BigModal.js.map +1 -1
  15. package/lib/components/Modal/Modal.js +1 -0
  16. package/lib/components/Modal/Modal.js.map +1 -1
  17. package/lib/hooks/useQuill.js +16 -1
  18. package/lib/hooks/useQuill.js.map +1 -1
  19. package/package.json +11 -5
  20. package/.eslintrc.json +0 -19
  21. package/.prettierrc +0 -11
  22. package/.vscode/settings.json +0 -10
  23. package/src/AddToDashboardModal.tsx +0 -1220
  24. package/src/BarList.tsx +0 -580
  25. package/src/Chart.tsx +0 -1337
  26. package/src/Context.tsx +0 -252
  27. package/src/Dashboard.tsx +0 -820
  28. package/src/DateRangePicker/Calendar.tsx +0 -442
  29. package/src/DateRangePicker/DateRangePicker.tsx +0 -261
  30. package/src/DateRangePicker/DateRangePickerButton.tsx +0 -250
  31. package/src/DateRangePicker/dateRangePickerUtils.tsx +0 -480
  32. package/src/DateRangePicker/index.ts +0 -4
  33. package/src/PieChart.tsx +0 -845
  34. package/src/QuillProvider.tsx +0 -81
  35. package/src/ReportBuilder.tsx +0 -2208
  36. package/src/SQLEditor.tsx +0 -1093
  37. package/src/Table.tsx +0 -1074
  38. package/src/TableChart.tsx +0 -428
  39. package/src/assets/ArrowDownHeadIcon.tsx +0 -11
  40. package/src/assets/ArrowDownIcon.tsx +0 -14
  41. package/src/assets/ArrowDownRightIcon.tsx +0 -14
  42. package/src/assets/ArrowLeftHeadIcon.tsx +0 -11
  43. package/src/assets/ArrowRightHeadIcon.tsx +0 -11
  44. package/src/assets/ArrowRightIcon.tsx +0 -14
  45. package/src/assets/ArrowUpHeadIcon.tsx +0 -11
  46. package/src/assets/ArrowUpIcon.tsx +0 -14
  47. package/src/assets/ArrowUpRightIcon.tsx +0 -14
  48. package/src/assets/CalendarIcon.tsx +0 -14
  49. package/src/assets/DoubleArrowLeftHeadIcon.tsx +0 -18
  50. package/src/assets/DoubleArrowRightHeadIcon.tsx +0 -20
  51. package/src/assets/ExclamationFilledIcon.tsx +0 -14
  52. package/src/assets/LoadingSpinner.tsx +0 -11
  53. package/src/assets/SearchIcon.tsx +0 -14
  54. package/src/assets/XCircleIcon.tsx +0 -14
  55. package/src/assets/index.ts +0 -16
  56. package/src/components/BigModal/BigModal.tsx +0 -108
  57. package/src/components/Dropdown/Dropdown.tsx +0 -169
  58. package/src/components/Dropdown/DropdownItem.tsx +0 -68
  59. package/src/components/Dropdown/index.ts +0 -2
  60. package/src/components/Modal/Modal.tsx +0 -132
  61. package/src/components/Modal/index.ts +0 -1
  62. package/src/components/selectUtils.ts +0 -60
  63. package/src/contexts/BaseColorContext.tsx +0 -5
  64. package/src/contexts/HoveredValueContext.tsx +0 -12
  65. package/src/contexts/RootStylesContext.tsx +0 -5
  66. package/src/contexts/SelectedValueContext.tsx +0 -13
  67. package/src/contexts/index.ts +0 -4
  68. package/src/hooks/index.ts +0 -4
  69. package/src/hooks/useInternalState.tsx +0 -18
  70. package/src/hooks/useOnClickOutside.tsx +0 -23
  71. package/src/hooks/useOnWindowResize.tsx +0 -17
  72. package/src/hooks/useQuill.ts +0 -138
  73. package/src/hooks/useSelectOnKeyDown.tsx +0 -80
  74. package/src/index.ts +0 -9
  75. package/src/lib/font.ts +0 -14
  76. package/src/lib/index.ts +0 -3
  77. package/src/lib/inputTypes.ts +0 -81
  78. package/src/lib/utils.tsx +0 -46
  79. package/tsconfig.json +0 -22
@@ -1,1220 +0,0 @@
1
- // @ts-nocheck
2
- import React, { useContext, useMemo, useEffect, useState } from 'react';
3
- import { ClientContext, SchemaContext, ThemeContext } from './Context';
4
- import BigModal from './components/BigModal/BigModal';
5
- import { Formik, Form, Field } from 'formik';
6
- import {
7
- differenceInDays,
8
- differenceInHours,
9
- differenceInMonths,
10
- differenceInYears,
11
- startOfDay,
12
- startOfHour,
13
- startOfMonth,
14
- startOfYear,
15
- } from 'date-fns';
16
- import axios from 'axios';
17
- import Chart from './Chart';
18
- import { XMarkIcon } from '@heroicons/react/20/solid';
19
- import { QuillTheme } from './QuillProvider';
20
-
21
- function convertPostgresColumn(column) {
22
- let format;
23
-
24
- switch (column.dataTypeID) {
25
- case 20: // int8
26
- case 21: // int2
27
- case 23: // int4
28
- format = 'whole_number';
29
- break;
30
- case 700: // float4
31
- case 701: // float8
32
- case 1700: // numeric
33
- format = 'two_decimal_places';
34
- break;
35
- case 1082: // date
36
- case 1083: // time
37
- case 1184: // timestamptz
38
- case 1114: // timestamp
39
- format = 'MMM_dd_yyyy';
40
- break;
41
- case 1043: // varchar
42
- default:
43
- format = 'string';
44
- }
45
-
46
- return {
47
- label: column.name,
48
- field: column.name,
49
- format: format,
50
- };
51
- }
52
-
53
- export default function AddToDashboardModal({
54
- isOpen,
55
- setIsOpen,
56
- SelectComponent,
57
- TextInputComponent,
58
- ButtonComponent,
59
- SecondaryButtonComponent,
60
- rows,
61
- columns,
62
- query,
63
- ModalComponent,
64
- formHeaderStyle,
65
- formLabelStyle,
66
- }) {
67
- const [theme] =
68
- useContext<[QuillTheme, (theme: QuillTheme) => void]>(ThemeContext);
69
- const [client] = useContext(ClientContext);
70
- const [schema, setSchema] = useContext(SchemaContext);
71
-
72
- useEffect(() => {
73
- let isSubscribed = true;
74
- async function getSchema() {
75
- const { publicKey, environment } = client;
76
- if (!schema.length) {
77
- const response3 = await axios.get(
78
- `https://quill-344421.uc.r.appspot.com/schema2/${publicKey}/`,
79
- {
80
- headers: {
81
- Authorization: `Bearer `,
82
- environment: environment || undefined,
83
- },
84
- }
85
- );
86
- if (isSubscribed) {
87
- setSchema(response3.data.tables);
88
- }
89
- }
90
- }
91
- if (isSubscribed) {
92
- getSchema();
93
- }
94
- return () => {
95
- isSubscribed = false;
96
- };
97
- }, [schema]);
98
-
99
- const editChart = async ({ report, values, yAxisFields, columns, query }) => {
100
- const {
101
- publicKey,
102
- orgId,
103
- authToken,
104
- queryEndpoint,
105
- queryHeaders,
106
- withCredentials,
107
- } = client;
108
- const {
109
- xAxisLabel,
110
- yAxisLabel,
111
- chartName,
112
- chartType,
113
- xAxisField,
114
- xAxisFormat,
115
- dashboardName,
116
- dateFieldTable,
117
- dateField,
118
- } = values;
119
-
120
- if (!chartName) {
121
- alert('Please enter a chart name');
122
- return;
123
- }
124
-
125
- // if (!dashboardName) {
126
- // alert("Please choose a dashboard name");
127
- // return;
128
- // }
129
-
130
- // if (!xAxisLabel && chartType !== "pie" && chartType !== "table") {
131
- // alert("Please enter a label for the x-axis");
132
- // return;
133
- // }
134
-
135
- // if (!yAxisLabel && chartType !== "pie" && chartType !== "table") {
136
- // alert("Please enter a label for the y-axis");
137
- // return;
138
- // }
139
-
140
- for (let i = 0; i < yAxisFields.length; i++) {
141
- if (!yAxisFields[i].label && chartType !== 'pie') {
142
- alert(`Please enter a label for column '${yAxisFields[i].field}'`);
143
- return;
144
- }
145
- }
146
-
147
- if (!client || !organization) {
148
- return;
149
- }
150
-
151
- let response;
152
- if (queryEndpoint) {
153
- response = await axios.post(
154
- queryEndpoint,
155
- {
156
- metadata: {
157
- name: chartName,
158
- xAxisField,
159
- yAxisFields,
160
- xAxisLabel,
161
- xAxisFormat,
162
- yAxisLabel,
163
- chartType,
164
- dashboardName,
165
- columns,
166
- dateField: { table: dateFieldTable, field: dateField },
167
- query: query,
168
- task: 'create',
169
- },
170
- },
171
- { headers: queryHeaders, withCredentials }
172
- );
173
- } else {
174
- response = await axios.post(
175
- `https://quill-344421.uc.r.appspot.com/dashedit/${publicKey}/${orgId}/`,
176
- {
177
- name: chartName,
178
- xAxisField,
179
- yAxisFields,
180
- xAxisLabel,
181
- xAxisFormat,
182
- yAxisLabel,
183
- chartType,
184
- dashboardName,
185
- columns,
186
- dateField: { table: dateFieldTable, field: dateField },
187
- query: query,
188
- },
189
- {
190
- headers: {
191
- Authorization: `Bearer ${authToken}`,
192
- environment: environment || undefined,
193
- },
194
- }
195
- );
196
- }
197
- if (!response.data) {
198
- return;
199
- }
200
- // setDashboard((dashboard) => {
201
- // return {
202
- // ...dashboard,
203
- // [response.data._id]: { ...existingVisualization, ...response.data }
204
- // }
205
- // })
206
- setIsOpen(false);
207
- // TODO: fire callback instead so user can customize action
208
- // navigate("/dashboards");
209
- };
210
- return (
211
- // <BigModal theme={theme} showModal={isOpen} setShowModal={setIsOpen}>
212
- <ModalComponent
213
- isOpen={isOpen}
214
- title={'Add to dashboard'}
215
- onClose={() => setIsOpen(false)}
216
- >
217
- <ChartForm
218
- editChart={editChart}
219
- theme={theme}
220
- schema={schema}
221
- data={rows}
222
- fields={columns}
223
- // leave null for now
224
- report={null}
225
- query={query}
226
- // organizationName={organization?.name}
227
- SelectComponent={SelectComponent}
228
- TextInputComponent={TextInputComponent}
229
- ButtonComponent={ButtonComponent}
230
- SecondaryButtonComponent={SecondaryButtonComponent}
231
- formHeaderStyle={formHeaderStyle}
232
- formLabelStyle={formLabelStyle}
233
- />
234
- </ModalComponent>
235
- // </BigModal>
236
- );
237
- }
238
-
239
- function ChartForm({
240
- data,
241
- fields,
242
- theme,
243
- saveVisualization,
244
- report,
245
- editChart,
246
- schema,
247
- query,
248
- // organizationName,
249
- SelectComponent,
250
- TextInputComponent,
251
- ButtonComponent,
252
- SecondaryButtonComponent,
253
- formHeaderStyle,
254
- formLabelStyle,
255
- }) {
256
- const fieldOptions = Object.keys(data[0]).map(field => ({
257
- value: field,
258
- label: field,
259
- }));
260
- const [dateFieldOptions, setDateFieldOptions] = useState([]);
261
-
262
- useEffect(() => {
263
- const fetchReferencedTables = async () => {
264
- const result = await getReferencedTables(query, 'PostgresQL', schema);
265
- setDateFieldOptions(result);
266
- };
267
-
268
- fetchReferencedTables();
269
- }, [query, schema]);
270
-
271
- return (
272
- <Formik
273
- initialValues={{
274
- xAxisField: report?.xAxisField || fieldOptions[0].value,
275
- xAxisLabel: report?.xAxisLabel || '',
276
- xAxisFormat: report?.xAxisFormat || FORMAT_OPTIONS[0].value,
277
- yAxisLabel: report?.yAxisLabel || '',
278
- chartName: report?.name,
279
- chartType: report?.chartType || 'bar',
280
- xAxisFieldLabel: '',
281
- dashboardName: report?.dashboardName || '',
282
- dateFieldTable:
283
- (dateFieldOptions.length && dateFieldOptions[0].name) || '',
284
- dateField:
285
- (dateFieldOptions.length && dateFieldOptions[0].columns[0].name) ||
286
- '',
287
- template: report?.template || false,
288
- }}
289
- onSubmit={() => {}}
290
- >
291
- {({ values, isSubmitting, setFieldValue }) => (
292
- <FormikForm
293
- values={values}
294
- isSubmitting={isSubmitting}
295
- data={data}
296
- fieldOptions={fieldOptions}
297
- dateFieldOptions={dateFieldOptions}
298
- theme={theme}
299
- saveVisualization={saveVisualization}
300
- report={report}
301
- editChart={editChart}
302
- fields={fields}
303
- query={query}
304
- setFieldValue={setFieldValue}
305
- // organizationName={organizationName}
306
- SelectComponent={SelectComponent}
307
- TextInputComponent={TextInputComponent}
308
- ButtonComponent={ButtonComponent}
309
- SecondaryButtonComponent={SecondaryButtonComponent}
310
- formHeaderStyle={formHeaderStyle}
311
- formLabelStyle={formLabelStyle}
312
- />
313
- )}
314
- </Formik>
315
- );
316
- }
317
-
318
- export function isValidDate(d) {
319
- return d instanceof Date && !isNaN(d);
320
- }
321
-
322
- export const isArrayOfValidDates = (arr, field) =>
323
- arr.every(
324
- d => new Date(d[field]) instanceof Date && !isNaN(new Date(d[field]))
325
- );
326
-
327
- export function formatDateBuckets(startDate, endDate) {
328
- // Calculate the distance in hours
329
- const distanceInHours = Math.abs(differenceInHours(endDate, startDate));
330
-
331
- // Check if the distance is less than or equal to one hour
332
- if (distanceInHours <= 1) {
333
- return {
334
- unit: 'hour',
335
- format: 'h a',
336
- startOf: startOfHour,
337
- };
338
- }
339
-
340
- // Calculate the distance in days
341
- const distanceInDays = Math.abs(differenceInDays(endDate, startDate));
342
-
343
- // Check if the distance is less than or equal to one day
344
- if (distanceInDays <= 1) {
345
- return {
346
- unit: 'day',
347
- format: 'MMM d',
348
- startOf: startOfDay,
349
- };
350
- }
351
-
352
- // Calculate the distance in months
353
- const distanceInMonths = Math.abs(differenceInMonths(endDate, startDate));
354
-
355
- // Check if the distance is less than or equal to one month
356
- if (distanceInMonths <= 1) {
357
- return {
358
- unit: 'month',
359
- format: 'MMM yyyy',
360
- startOf: startOfMonth,
361
- };
362
- }
363
-
364
- // Calculate the distance in years
365
- const distanceInYears = Math.abs(differenceInYears(endDate, startDate));
366
-
367
- // Check if the distance is less than or equal to one year
368
- if (distanceInYears <= 1) {
369
- return {
370
- unit: 'year',
371
- format: 'yyyy',
372
- startOf: startOfYear,
373
- };
374
- }
375
-
376
- // Otherwise, the distance is more than one year
377
- return {
378
- unit: 'year',
379
- format: 'yyyy',
380
- startOf: startOfYear,
381
- };
382
- }
383
-
384
- const FormTextInput = ({ field, form, ...props }) => {
385
- const { theme, wider } = props;
386
- return (
387
- <input
388
- className={`px-[12px] text-sm h-[38px] py-1.5 shadow-sm w-[245px] border-[#E7E7E7] ${'text-[#212121]'} border-[1px] bg-[white] rounded-md`}
389
- type="text"
390
- {...field}
391
- {...props}
392
- />
393
- );
394
- };
395
-
396
- const POSTGRES_DATE_TYPES = [
397
- 'timestamp',
398
- 'date',
399
- 'timestamptz',
400
- 'time',
401
- 'timetz',
402
- ];
403
-
404
- async function getReferencedTables(sqlQuery, databaseType, dbTables) {
405
- // const parser = new Parser();
406
- let tables = [];
407
- let withAliases = [];
408
-
409
- const response = await axios.post(
410
- 'https://quill-344421.uc.r.appspot.com/astify',
411
- { query: sqlQuery }
412
- );
413
- let ast = response.data.ast;
414
- ast = ast.length ? ast[0] : ast;
415
-
416
- if (ast.with && ast.with.length) {
417
- for (let i = 0; i < ast.with.length; i++) {
418
- withAliases.push(ast.with[i].name.value);
419
- for (let j = 0; j < ast.with[i].stmt.from.length; j++)
420
- tables.push(ast.with[i].stmt.from[j].table);
421
- }
422
- }
423
- const tablesInQuery = [...tables, ...ast.from.map(elem => elem.table)].filter(
424
- elem => !withAliases.includes(elem)
425
- );
426
- return dbTables
427
- .filter(table => tablesInQuery.includes(table.displayName))
428
- .map(table => {
429
- return {
430
- name: table.displayName,
431
- columns: table.columns.filter(column =>
432
- POSTGRES_DATE_TYPES.includes(column.fieldType)
433
- ),
434
- };
435
- })
436
- .filter(table => table.columns.length > 0);
437
- }
438
-
439
- const FORMAT_OPTIONS = [
440
- { value: 'whole_number', label: 'whole number' },
441
- { value: 'one_decimal_place', label: 'one decimal place' },
442
- { value: 'dollar_amount', label: 'dollar amount' },
443
- { value: 'MMM_yyyy', label: 'month' },
444
- { value: 'MMM_dd-MMM_dd', label: 'week' },
445
- { value: 'MMM_dd_yyyy', label: 'day' },
446
- { value: 'MMM_dd_hh:mm_ap_pm', label: 'day and time' },
447
- { value: 'hh_ap_pm', label: 'hour' },
448
- { value: 'percent', label: 'percent' },
449
- { value: 'string', label: 'string' },
450
- ];
451
-
452
- function FormikForm({
453
- values,
454
- isSubmitting,
455
- data,
456
- fieldOptions,
457
- dateFieldOptions,
458
- theme,
459
- report,
460
- editChart,
461
- fields,
462
- query,
463
- SelectComponent,
464
- TextInputComponent,
465
- ButtonComponent,
466
- SecondaryButtonComponent,
467
- setFieldValue,
468
- organizationName,
469
- formHeaderStyle,
470
- formLabelStyle,
471
- }) {
472
- const [chartConfig, setChartConfig] = useState({});
473
- const [yAxisFields, setYAxisFields] = useState(
474
- report
475
- ? report.yAxisFields
476
- : [
477
- {
478
- field:
479
- fieldOptions.length > 1
480
- ? fieldOptions[1].value
481
- : fieldOptions[0].value,
482
- label: '',
483
- format: 'whole_number',
484
- },
485
- ]
486
- );
487
- const [columns, setColumns] = useState(
488
- report && report.columns.length
489
- ? report.columns
490
- : fields?.length
491
- ? fields.map(field => convertPostgresColumn(field))
492
- : []
493
- );
494
-
495
- const handleAddYAxisField = () => {
496
- setYAxisFields([
497
- ...yAxisFields,
498
- { label: '', field: '', format: 'whole_number' },
499
- ]);
500
- };
501
-
502
- const handleDeleteYAxisField = index => {
503
- setYAxisFields(yAxisFields => yAxisFields.filter((_, i) => index !== i));
504
- };
505
-
506
- const handleYAxisFieldChange = (index, value) => {
507
- const newYAxisFields = [...yAxisFields];
508
- newYAxisFields[index] = { ...newYAxisFields[index], field: value };
509
- setYAxisFields(newYAxisFields);
510
- };
511
-
512
- const handleYAxisFieldFormatChange = (index, value) => {
513
- const newYAxisFields = [...yAxisFields];
514
- newYAxisFields[index] = { ...newYAxisFields[index], format: value };
515
- setYAxisFields(newYAxisFields);
516
- };
517
-
518
- const handleYAxisFieldLabelChange = (index, value) => {
519
- const newYAxisFields = [...yAxisFields];
520
- newYAxisFields[index] = { ...newYAxisFields[index], label: value };
521
- setYAxisFields(newYAxisFields);
522
- };
523
-
524
- const handleColumnFieldChange = (index, value) => {
525
- const newColumns = [...columns];
526
- newColumns[index] = { ...newColumns[index], field: value };
527
- setColumns(newColumns);
528
- };
529
-
530
- const handleColumnFormatChange = (index, value) => {
531
- const newColumns = [...columns];
532
- newColumns[index] = { ...newColumns[index], format: value };
533
- setColumns(newColumns);
534
- };
535
-
536
- const handleColumnLabelChange = (index, value) => {
537
- const newColumns = [...columns];
538
- newColumns[index] = { ...newColumns[index], label: value };
539
- setColumns(newColumns);
540
- };
541
-
542
- useEffect(() => {
543
- setChartConfig({ ...values, yAxisFields: yAxisFields, rows: data });
544
- }, [values, yAxisFields]);
545
-
546
- // console.log('VIBE: ', { report, values, yAxisFields, columns, query });
547
-
548
- return (
549
- <Form style={{ display: 'inline-block' }}>
550
- <div style={{ display: 'flex', flexDirection: 'column' }}>
551
- <div
552
- style={{
553
- display: 'flex',
554
- flexDirection: 'column',
555
- }}
556
- >
557
- {/* <div
558
- style={{
559
- fontFamily: theme.fontFamily,
560
- color: theme.primaryTextColor,
561
- fontSize: 20,
562
- fontWeight: 600,
563
- }}
564
- >
565
- {report ? 'Edit chart' : 'Add to dashboard'}
566
- </div> */}
567
- <div style={{ height: 20 }} />
568
- <div style={{ marginLeft: -25 }}>
569
- {Object.keys(chartConfig).length > 0 && (
570
- <Chart
571
- chartId="646e37a660feef000be67a93"
572
- config={chartConfig} //TODO: resolve; this might be a problem
573
- colors={theme.chartColors}
574
- containerStyle={{
575
- width: '100%',
576
- height: 300,
577
- }}
578
- />
579
- )}
580
- </div>
581
- <div style={{ height: 20 }} />
582
- <div
583
- style={
584
- formHeaderStyle || {
585
- fontFamily: theme.fontFamily,
586
- color: theme.primaryTextColor,
587
- fontSize: theme.fontSize + 2,
588
- fontWeight: 600,
589
- marginTop: 20,
590
- }
591
- }
592
- >
593
- {'Chart'}
594
- </div>
595
- <div
596
- style={{
597
- display: 'flex',
598
- flexDirection: 'row',
599
- alignItems: 'center',
600
- }}
601
- >
602
- <div style={{ display: 'flex', flexDirection: 'column' }}>
603
- <div
604
- style={
605
- formLabelStyle || {
606
- fontSize: '14px',
607
- marginBottom: '6px',
608
- fontWeight: '600',
609
- marginTop: 8,
610
- color: theme.secondaryTextColor,
611
- fontFamily: theme?.fontFamily,
612
- }
613
- }
614
- >
615
- Name
616
- </div>
617
- <div style={{ minWidth: 200 }}>
618
- <Field
619
- name="chartName"
620
- component={TextInputComponent}
621
- theme={theme}
622
- wider
623
- />
624
- </div>
625
- </div>
626
- <div style={{ width: 20 }} />
627
- <div style={{ display: 'flex', flexDirection: 'column' }}>
628
- <div
629
- style={
630
- formLabelStyle || {
631
- fontFamily: theme.fontFamily,
632
- color: theme.secondaryTextColor,
633
- fontSize: theme.fontSize,
634
- fontWeight: theme.labelFontWeight,
635
- marginTop: 8,
636
- marginBottom: 6,
637
- }
638
- }
639
- >
640
- Dashboard name
641
- </div>
642
- <div style={{ minWidth: 200 }}>
643
- <Field
644
- name="dashboardName"
645
- component={TextInputComponent}
646
- theme={theme}
647
- wider
648
- />
649
- </div>
650
- </div>
651
- <div style={{ width: 20 }} />
652
- <div style={{ display: 'flex', flexDirection: 'column' }}>
653
- <div
654
- style={
655
- formLabelStyle || {
656
- fontFamily: theme.fontFamily,
657
- color: theme.secondaryTextColor,
658
- fontSize: theme.fontSize,
659
- fontWeight: theme.labelFontWeight,
660
- marginTop: 8,
661
- }
662
- }
663
- >
664
- Chart type
665
- </div>
666
- <div style={{ minWidth: 200 }}>
667
- <Field
668
- name="chartType"
669
- component={SelectComponent}
670
- theme={theme}
671
- options={[
672
- { label: 'bar', value: 'bar' },
673
- { label: 'line', value: 'line' },
674
- { label: 'column', value: 'column' },
675
- { label: 'pie', value: 'pie' },
676
- { label: 'metric', value: 'metric' },
677
- { label: 'table', value: 'table' },
678
- ]}
679
- />
680
- </div>
681
- </div>
682
- </div>
683
- </div>
684
- <div
685
- style={{
686
- display: 'flex',
687
- flexDirection: 'row',
688
- alignItems: 'center',
689
- // justifyContent: 'space-between',
690
- marginTop: 20,
691
- }}
692
- >
693
- {values.chartType !== 'table' && (
694
- <div style={{ display: 'flex', flexDirection: 'column' }}>
695
- <div
696
- style={
697
- formLabelStyle || {
698
- fontFamily: theme.fontFamily,
699
- color: theme.secondaryTextColor,
700
- fontSize: theme.fontSize,
701
- fontWeight: theme.labelFontWeight,
702
- }
703
- }
704
- >
705
- {values.chartType === 'pie'
706
- ? 'Category column'
707
- : 'x-axis column'}
708
- </div>
709
- <div style={{ height: 6 }} />
710
- <div
711
- style={{
712
- display: 'flex',
713
- flexDirection: 'row',
714
- alignItems: 'center',
715
- }}
716
- >
717
- <div style={{ minWidth: 200 }}>
718
- <Field
719
- name="xAxisField"
720
- component={SelectComponent}
721
- theme={theme}
722
- options={fieldOptions}
723
- />
724
- </div>
725
- {/* {fieldOptions.map((option) => (
726
- <option key={option.value} value={option.value}>
727
- {option.label}
728
- </option>
729
- ))}
730
- </Field> */}
731
- <div style={{ width: 20 }} />
732
- <div style={{ minWidth: 200 }}>
733
- <Field
734
- name="xAxisLabel"
735
- component={TextInputComponent}
736
- theme={theme}
737
- />
738
- </div>
739
- <div style={{ width: 20 }} />
740
- <div style={{ minWidth: 200 }}>
741
- <Field
742
- name="xAxisFormat"
743
- component={SelectComponent}
744
- theme={theme}
745
- options={FORMAT_OPTIONS}
746
- />
747
- </div>
748
- {/* {FORMAT_OPTIONS.map((option) => (
749
- <option key={option.value} value={option.value}>
750
- {option.label}
751
- </option>
752
- ))}
753
- </Field> */}
754
- </div>
755
- </div>
756
- )}
757
- </div>
758
- <div
759
- style={{
760
- display: 'flex',
761
- flexDirection: 'row',
762
- alignItems: 'flex-start',
763
- // justifyContent: 'space-between',
764
- marginTop: 20,
765
- }}
766
- >
767
- <div style={{ display: 'flex', flexDirection: 'column' }}>
768
- <div
769
- style={
770
- formLabelStyle || {
771
- fontFamily: theme.fontFamily,
772
- color: theme.secondaryTextColor,
773
- fontSize: theme.fontSize,
774
- fontWeight: theme.labelFontWeight,
775
- minWidth: 200,
776
- }
777
- }
778
- >
779
- {values.chartType === 'table'
780
- ? 'Columns'
781
- : values.chartType === 'pie'
782
- ? 'Quantity column'
783
- : 'y-axis columns'}
784
- </div>
785
- <div
786
- style={{
787
- display: 'flex',
788
- flexDirection: 'column',
789
- }}
790
- >
791
- {yAxisFields.map((yAxisField, index) => (
792
- <div
793
- key={`yAxisField-${index}`}
794
- style={{
795
- display: 'flex',
796
- flexDirection: 'row',
797
- alignItems: 'center',
798
- marginTop: index === 0 ? 6 : 10,
799
- }}
800
- >
801
- <div style={{ minWidth: 200 }}>
802
- <Field
803
- name={`yAxisField-${index}`}
804
- component={SelectComponent}
805
- theme={theme}
806
- value={yAxisField.field}
807
- onChange={option => handleYAxisFieldChange(index, option)}
808
- options={fieldOptions}
809
- />
810
- </div>
811
- </div>
812
- ))}
813
- {values.chartType !== 'pie' && (
814
- <div style={{ marginTop: 12 }}>
815
- <SecondaryButtonComponent
816
- onClick={handleAddYAxisField}
817
- label="Add column +"
818
- />
819
- </div>
820
- )}
821
- <div style={{ height: 10 }} />
822
- </div>
823
- </div>
824
- <div style={{ width: 20 }} />
825
- <div
826
- style={{
827
- display: 'flex',
828
- flexDirection: 'column',
829
- justifyContent: 'flex-start',
830
- }}
831
- >
832
- <div
833
- style={
834
- formLabelStyle || {
835
- fontFamily: theme.fontFamily,
836
- color: 'transparent',
837
- fontSize: theme.fontSize,
838
- fontWeight: theme.labelFontWeight,
839
- minWidth: 200,
840
- // marginBottom: 10,
841
- }
842
- }
843
- >
844
- y-axis label
845
- </div>
846
- {values.chartType !== 'pie' &&
847
- yAxisFields.map((yAxisField, index) => (
848
- <div
849
- key={`yAxisField-${index}`}
850
- style={{
851
- display: 'flex',
852
- flexDirection: 'row',
853
- alignItems: 'center',
854
- marginTop: index === 0 ? 6 : 10,
855
- }}
856
- >
857
- <div style={{ minWidth: 200 }}>
858
- <Field
859
- name={`yAxisField-${index}`}
860
- component={TextInputComponent}
861
- theme={theme}
862
- placeholder="Enter column label"
863
- value={yAxisField.label}
864
- onChange={event =>
865
- handleYAxisFieldLabelChange(index, event.target.value)
866
- }
867
- />
868
- </div>
869
- <div style={{ width: 20 }} />
870
- <div style={{ minWidth: 200 }}>
871
- <Field
872
- name={`yAxisFieldFormat-${index}`}
873
- component={SelectComponent}
874
- theme={theme}
875
- value={yAxisField.format}
876
- onChange={option =>
877
- handleYAxisFieldFormatChange(index, option)
878
- }
879
- options={FORMAT_OPTIONS}
880
- />
881
- </div>
882
- <div
883
- onClick={() =>
884
- index > 0 ? handleDeleteYAxisField(index) : undefined
885
- }
886
- style={{
887
- cursor: index > 0 ? 'pointer' : undefined,
888
- paddingLeft: 6,
889
- paddingTop: 12,
890
- paddingBottom: 12,
891
- paddingRight: 6,
892
- maxHeight: 38,
893
- display: 'flex',
894
- alignItems: 'center',
895
- justifyContent: 'center',
896
- }}
897
- >
898
- <XMarkIcon
899
- style={{
900
- height: '20px',
901
- width: '20px',
902
- color:
903
- index > 0
904
- ? theme?.secondaryTextColor
905
- : 'rgba(0,0,0,0)',
906
- }}
907
- aria-hidden="true"
908
- />
909
- </div>
910
- </div>
911
- ))}
912
- </div>
913
- </div>
914
- <div style={{ height: 20 }} />
915
- <div
916
- style={
917
- formHeaderStyle || {
918
- fontFamily: theme.fontFamily,
919
- color: theme.primaryTextColor,
920
- fontSize: theme.fontSize + 2,
921
- fontWeight: 600,
922
- }
923
- }
924
- >
925
- {'Table'}
926
- </div>
927
- <div
928
- style={{
929
- display: 'flex',
930
- flexDirection: 'row',
931
- alignItems: 'flex-start',
932
- // justifyContent: 'space-between',
933
- // marginTop: 8,
934
- }}
935
- >
936
- <div style={{ display: 'flex', flexDirection: 'column' }}>
937
- <div
938
- style={
939
- formLabelStyle || {
940
- fontFamily: theme.fontFamily,
941
- color: theme.secondaryTextColor,
942
- fontSize: theme.fontSize,
943
- fontWeight: theme.labelFontWeight,
944
- }
945
- }
946
- >
947
- {'Columns'}
948
- </div>
949
- <div
950
- style={{
951
- display: 'flex',
952
- flexDirection: 'column',
953
- }}
954
- >
955
- {columns.map((yAxisField, index) => (
956
- <div
957
- key={`column-${index}`}
958
- style={{
959
- display: 'flex',
960
- flexDirection: 'row',
961
- alignItems: 'center',
962
- marginTop: index === 0 ? 6 : 10,
963
- }}
964
- >
965
- <div style={{ minWidth: 200 }}>
966
- <Field
967
- name={`column-${index}`}
968
- component={SelectComponent}
969
- theme={theme}
970
- value={yAxisField.field}
971
- onChange={option =>
972
- handleColumnFieldChange(index, option)
973
- }
974
- options={fieldOptions}
975
- />
976
- </div>
977
- </div>
978
- ))}
979
- <div style={{ height: 10 }} />
980
- </div>
981
- </div>
982
- <div style={{ width: 20 }} />
983
- <div
984
- style={{
985
- display: 'flex',
986
- flexDirection: 'column',
987
- justifyContent: 'flex-start',
988
- }}
989
- >
990
- <div
991
- style={
992
- formLabelStyle || {
993
- fontFamily: theme.fontFamily,
994
- color: 'transparent',
995
- fontSize: theme.fontSize,
996
- fontWeight: theme.labelFontWeight,
997
- minWidth: 200,
998
- // marginBottom: 10,
999
- }
1000
- }
1001
- >
1002
- label
1003
- </div>
1004
- {columns.map((yAxisField, index) => (
1005
- <div
1006
- key={`column-${index}`}
1007
- style={{
1008
- display: 'flex',
1009
- flexDirection: 'row',
1010
- alignItems: 'center',
1011
- marginTop: index === 0 ? 6 : 10,
1012
- }}
1013
- >
1014
- <div style={{ minWidth: 200 }}>
1015
- <Field
1016
- name={`columnlabel-${index}`}
1017
- component={TextInputComponent}
1018
- theme={theme}
1019
- placeholder="Enter column label"
1020
- value={yAxisField.label}
1021
- onChange={event =>
1022
- handleColumnLabelChange(index, event.target.value)
1023
- }
1024
- />
1025
- </div>
1026
- <div style={{ width: 20 }} />
1027
- <div style={{ minWidth: 200 }}>
1028
- <Field
1029
- name={`columnFormat-${index}`}
1030
- component={SelectComponent}
1031
- theme={theme}
1032
- value={yAxisField.format}
1033
- onChange={option => handleColumnFormatChange(index, option)}
1034
- options={FORMAT_OPTIONS}
1035
- />
1036
- </div>
1037
- {/* <div
1038
- style={{
1039
- cursor: index > 0 ? 'pointer' : undefined,
1040
- paddingLeft: 6,
1041
- paddingTop: 12,
1042
- paddingBottom: 12,
1043
- paddingRight: 6,
1044
- maxHeight: 38,
1045
- display: 'flex',
1046
- alignItems: 'center',
1047
- justifyContent: 'center',
1048
- }}
1049
- >
1050
- <XMarkIcon
1051
- style={{
1052
- height: '20px',
1053
- width: '20px',
1054
- color:
1055
- index > 0 ? theme?.secondaryTextColor : 'rgba(0,0,0,0)',
1056
- }}
1057
- aria-hidden="true"
1058
- />
1059
- </div> */}
1060
- </div>
1061
- ))}
1062
- </div>
1063
- </div>
1064
- <div style={{ height: 20 }} />
1065
- {/* <div
1066
- style={
1067
- formHeaderStyle || {
1068
- fontFamily: theme.fontFamily,
1069
- color: theme.primaryTextColor,
1070
- fontSize: theme.fontSize + 2,
1071
- fontWeight: 600,
1072
- // marginTop: 20,
1073
- }
1074
- }
1075
- >
1076
- {'Filters'}
1077
- </div>
1078
- <div
1079
- style={{
1080
- display: 'flex',
1081
- flexDirection: 'row',
1082
- alignItems: 'center',
1083
- }}
1084
- >
1085
- <div style={{ display: 'flex', flexDirection: 'column' }}>
1086
- <div
1087
- style={
1088
- formLabelStyle || {
1089
- fontFamily: theme.fontFamily,
1090
- color: theme.secondaryTextColor,
1091
- fontSize: theme.fontSize,
1092
- fontWeight: theme.labelFontWeight,
1093
- marginTop: 8,
1094
- marginBottom: 6,
1095
- }
1096
- }
1097
- >
1098
- Date field table
1099
- </div>
1100
- <div style={{ minWidth: 200 }}>
1101
- <Field
1102
- name="dateFieldTable"
1103
- component={SelectComponent}
1104
- theme={theme}
1105
- options={dateFieldOptions.map(elem => {
1106
- return { label: elem.name, value: elem.name };
1107
- })}
1108
- />
1109
- </div>
1110
- </div>
1111
- <div style={{ width: 20 }} />
1112
- <div style={{ display: 'flex', flexDirection: 'column' }}>
1113
- <div
1114
- style={
1115
- formLabelStyle || {
1116
- fontFamily: theme.fontFamily,
1117
- color: theme.secondaryTextColor,
1118
- fontSize: theme.fontSize,
1119
- fontWeight: theme.labelFontWeight,
1120
- marginTop: 8,
1121
- marginBottom: 6,
1122
- }
1123
- }
1124
- >
1125
- Date field
1126
- </div>
1127
- <div style={{ minWidth: 200 }}>
1128
- <Field
1129
- name="dateField"
1130
- component={SelectComponent}
1131
- theme={theme}
1132
- options={
1133
- dateFieldOptions.filter(
1134
- elem => elem.name === values.dateFieldTable
1135
- ).length
1136
- ? dateFieldOptions
1137
- .filter(elem => elem.name === values.dateFieldTable)[0]
1138
- .columns.map(elem => {
1139
- return { label: elem.name, value: elem.name };
1140
- })
1141
- : []
1142
- }
1143
- />
1144
- </div>
1145
- </div>
1146
- </div> */}
1147
- {/* <div
1148
- style={{
1149
- display: "flex",
1150
- flexDirection: "column",
1151
- // alignItems: "center",
1152
- // justifyContent: "space-between",
1153
- marginTop: 10,
1154
- marginBottom: 20,
1155
- }}
1156
- >
1157
- <div
1158
- style={{
1159
- fontFamily: theme.fontFamily,
1160
- color: theme.primaryTextColor,
1161
- fontSize: theme.fontSize + 2,
1162
- fontWeight: 600,
1163
- marginTop: 20,
1164
- marginBottom: 12,
1165
- }}
1166
- >
1167
- {"Access Control"}
1168
- </div>
1169
- <Tab.Group
1170
- className={`px-1 flex flex-row text-sm font-medium py-1 h-[38px] w-[500px] border-[#E7E7E7] ${"text-[#212121]"} bg-[#212121]/[0.03] rounded-md`}
1171
- selectedIndex={values.template === true ? 1 : 0}
1172
- onChange={(index) => {
1173
- if (index === 0) {
1174
- setFieldValue("template", false);
1175
- } else {
1176
- setFieldValue("template", true);
1177
- }
1178
- }}
1179
- >
1180
- <Tab.List>
1181
- <Tab
1182
- className={({ selected }) =>
1183
- classNames(
1184
- "w-full rounded-md py-1 text-sm font-medium leading-5 text-[#212121]",
1185
- "ring-white ring-opacity-60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2",
1186
- selected
1187
- ? "bg-white shadow"
1188
- : "hover:bg-white/[0.12] text-[#212121]/[.3]"
1189
- )
1190
- }
1191
- >
1192
- {`This Organization (${organizationName})`}
1193
- </Tab>
1194
- <Tab
1195
- className={({ selected }) =>
1196
- classNames(
1197
- "w-full rounded-md py-1 text-sm font-medium leading-5 text-[#212121]",
1198
- "ring-white ring-opacity-60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2",
1199
- selected
1200
- ? "bg-white shadow"
1201
- : "hover:bg-white/[0.12] text-[#212121]/[.3]"
1202
- )
1203
- }
1204
- >
1205
- {"Global (All Organizations)"}
1206
- </Tab>
1207
- </Tab.List>
1208
- </Tab.Group>
1209
- </div> */}
1210
- <div style={{ height: 20 }} />
1211
- <ButtonComponent
1212
- onClick={() =>
1213
- editChart({ report, values, yAxisFields, columns, query })
1214
- }
1215
- label={report ? 'Save changes' : 'Add to dashboard'}
1216
- />
1217
- </div>
1218
- </Form>
1219
- );
1220
- }