@quillsql/react 2.15.16 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1245 -2273
- package/dist/index.js +1096 -2111
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -14781,21 +14781,6 @@ function isDateFormat(xAxisFormat) {
|
|
|
14781
14781
|
const isDate = DATE_FORMATS.includes(xAxisFormat);
|
|
14782
14782
|
return isDate;
|
|
14783
14783
|
}
|
|
14784
|
-
function getComparisonInterval(comparisonRange, dateBucket) {
|
|
14785
|
-
const dayCount = (0, import_date_fns5.differenceInDays)(
|
|
14786
|
-
comparisonRange.endDate,
|
|
14787
|
-
comparisonRange.startDate
|
|
14788
|
-
);
|
|
14789
|
-
if (!isNaN(dayCount)) {
|
|
14790
|
-
if (dateBucket === "month") {
|
|
14791
|
-
return Math.floor(dayCount / 30) + " month";
|
|
14792
|
-
} else if (dateBucket === "year") {
|
|
14793
|
-
return Math.floor(dayCount / 365) + " year";
|
|
14794
|
-
} else {
|
|
14795
|
-
return dayCount + " day";
|
|
14796
|
-
}
|
|
14797
|
-
}
|
|
14798
|
-
}
|
|
14799
14784
|
function getDateBucketFromRange(dateRange) {
|
|
14800
14785
|
const difference = (0, import_date_fns5.differenceInDays)(dateRange.end, dateRange.start);
|
|
14801
14786
|
if (difference < 14) {
|
|
@@ -16609,311 +16594,771 @@ function parseValueFromBigQueryDates(rows, columns) {
|
|
|
16609
16594
|
});
|
|
16610
16595
|
}
|
|
16611
16596
|
|
|
16612
|
-
// src/utils/
|
|
16613
|
-
|
|
16614
|
-
|
|
16615
|
-
|
|
16616
|
-
|
|
16617
|
-
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
|
|
16624
|
-
|
|
16597
|
+
// src/utils/pivotConstructor.ts
|
|
16598
|
+
async function generatePivotWithSQL({
|
|
16599
|
+
pivot,
|
|
16600
|
+
report,
|
|
16601
|
+
client,
|
|
16602
|
+
dateBucket,
|
|
16603
|
+
dateFilter,
|
|
16604
|
+
distinctStrings,
|
|
16605
|
+
dashboardName,
|
|
16606
|
+
tenants,
|
|
16607
|
+
additionalProcessing,
|
|
16608
|
+
pivotQuery,
|
|
16609
|
+
comparisonPivotQuery,
|
|
16610
|
+
getPivotRowCount = true,
|
|
16611
|
+
caller,
|
|
16612
|
+
getToken
|
|
16613
|
+
}) {
|
|
16614
|
+
const databaseType = client.databaseType || "postgresql";
|
|
16615
|
+
if (!pivot.aggregations?.length && pivot.aggregationType) {
|
|
16616
|
+
pivot.aggregations = [
|
|
16617
|
+
{
|
|
16618
|
+
aggregationType: pivot.aggregationType,
|
|
16619
|
+
valueField: pivot.valueField,
|
|
16620
|
+
valueFieldType: pivot.valueFieldType,
|
|
16621
|
+
valueField2: pivot.valueField2,
|
|
16622
|
+
valueField2Type: pivot.valueField2Type
|
|
16625
16623
|
}
|
|
16626
|
-
|
|
16627
|
-
|
|
16628
|
-
|
|
16624
|
+
];
|
|
16625
|
+
}
|
|
16626
|
+
const pivotConfig = {
|
|
16627
|
+
rowField: pivot.rowField,
|
|
16628
|
+
rowFieldType: pivot.rowFieldType,
|
|
16629
|
+
columnField: pivot.columnField,
|
|
16630
|
+
aggregations: pivot.aggregations?.map((agg) => ({
|
|
16631
|
+
aggregationType: agg.aggregationType,
|
|
16632
|
+
valueField: agg.valueField,
|
|
16633
|
+
valueFieldType: agg.valueFieldType
|
|
16634
|
+
}))
|
|
16635
|
+
};
|
|
16636
|
+
const resp = await quillFetch({
|
|
16637
|
+
client,
|
|
16638
|
+
task: "pivot-template",
|
|
16639
|
+
metadata: {
|
|
16640
|
+
clientId: client.clientId,
|
|
16641
|
+
pivot: pivotConfig,
|
|
16642
|
+
itemQuery: report?.queryString,
|
|
16643
|
+
dashboardName,
|
|
16644
|
+
tenants
|
|
16645
|
+
},
|
|
16646
|
+
credentials: "same-origin",
|
|
16647
|
+
getToken
|
|
16629
16648
|
});
|
|
16630
|
-
|
|
16631
|
-
|
|
16632
|
-
function dateAdder(date, interval2) {
|
|
16633
|
-
const match = interval2.match(/^(\d+)\s+(day|month|year)$/);
|
|
16634
|
-
if (!match) {
|
|
16635
|
-
throw new Error(`Invalid interval format: ${interval2}`);
|
|
16649
|
+
if (resp.data?.success === false) {
|
|
16650
|
+
throw resp.data.errorMessage;
|
|
16636
16651
|
}
|
|
16637
|
-
const
|
|
16638
|
-
|
|
16639
|
-
|
|
16652
|
+
const queryResponseRows = resp.data?.rows || resp.queries?.queryResults?.[0]?.rows || [];
|
|
16653
|
+
const queryResponseFields = resp.data?.fields || resp.queries?.queryResults?.[0]?.fields || [];
|
|
16654
|
+
const rowCount = resp.queries?.queryResults?.[1]?.rows?.[0]?.row_count || 0;
|
|
16655
|
+
parseValueFromBigQueryDates(queryResponseRows, queryResponseFields);
|
|
16656
|
+
const responseRows = queryResponseRows;
|
|
16657
|
+
const responseFields = queryResponseFields;
|
|
16658
|
+
const rows = pivot.rowField ? responseRows.map(
|
|
16659
|
+
(row) => !row[pivot.rowField] ? { ...row, [pivot.rowField]: "-" } : row
|
|
16660
|
+
) : responseRows;
|
|
16661
|
+
if (pivot.columnField && client.databaseType?.toLowerCase() === "bigquery") {
|
|
16662
|
+
rows.forEach((row) => {
|
|
16663
|
+
Object.keys(row).forEach((key) => {
|
|
16664
|
+
const processedKey = processColumnName(key);
|
|
16665
|
+
if (processedKey !== key) {
|
|
16666
|
+
row[processedKey] = row[key];
|
|
16667
|
+
delete row[key];
|
|
16668
|
+
}
|
|
16669
|
+
});
|
|
16670
|
+
});
|
|
16640
16671
|
}
|
|
16641
|
-
const
|
|
16642
|
-
|
|
16643
|
-
|
|
16644
|
-
|
|
16645
|
-
|
|
16646
|
-
|
|
16647
|
-
|
|
16648
|
-
|
|
16649
|
-
|
|
16650
|
-
|
|
16651
|
-
|
|
16672
|
+
const columns = responseFields?.map((field) => ({
|
|
16673
|
+
field: processColumnName(field.field || field.name),
|
|
16674
|
+
label: snakeCaseToTitleCase(
|
|
16675
|
+
processColumnName(
|
|
16676
|
+
(field.field || field.name).replace("comparison_", "comparison ")
|
|
16677
|
+
)
|
|
16678
|
+
),
|
|
16679
|
+
format: (field.field || field.name) === pivot.rowField ? "string" : pivot.aggregations?.find(
|
|
16680
|
+
(agg) => agg.valueField === (field.field || field.name) || `${agg.valueField}_percentage` === (field.field || field.name) || !agg.valueField && agg.aggregationType === "percentage" && (field.field || field.name)?.endsWith("percentage")
|
|
16681
|
+
)?.aggregationType === "percentage" ? "percent" : "whole_number",
|
|
16682
|
+
fieldType: field.fieldType,
|
|
16683
|
+
jsType: field.jsType,
|
|
16684
|
+
dataTypeID: field.dataTypeID
|
|
16685
|
+
})).filter(
|
|
16686
|
+
(field, index) => field.field !== "comparison_" + pivot.rowField || index === 0
|
|
16687
|
+
).sort((a, b) => {
|
|
16688
|
+
if (a.field === pivot.rowField) {
|
|
16689
|
+
return -1;
|
|
16690
|
+
}
|
|
16691
|
+
if (b.field === pivot.rowField) {
|
|
16692
|
+
return 1;
|
|
16693
|
+
}
|
|
16694
|
+
return 0;
|
|
16695
|
+
});
|
|
16696
|
+
if (pivot.rowField && !isStringType(pivot.rowFieldType || "")) {
|
|
16697
|
+
rows.forEach((row) => {
|
|
16698
|
+
row.__quillRawDate = typeof row[pivot.rowField || ""] === "object" ? row[pivot.rowField || ""].value : row[pivot.rowField || ""];
|
|
16699
|
+
let value = typeof row[pivot.rowField || ""] === "object" ? row[pivot.rowField || ""].value : row[pivot.rowField || ""];
|
|
16700
|
+
if (dateBucket === "week" && dateFilter?.startDate && dateFilter?.endDate) {
|
|
16701
|
+
const rowDate = new Date(value);
|
|
16702
|
+
if (rowDate < dateFilter.startDate) {
|
|
16703
|
+
value = dateFilter.startDate.toISOString();
|
|
16704
|
+
} else if (rowDate > dateFilter.endDate) {
|
|
16705
|
+
value = dateFilter.endDate.toISOString();
|
|
16706
|
+
}
|
|
16707
|
+
}
|
|
16708
|
+
const dateString = getDateString(
|
|
16709
|
+
value,
|
|
16710
|
+
dateFilter?.startDate && dateFilter?.endDate ? { start: dateFilter.startDate, end: dateFilter.endDate } : void 0,
|
|
16711
|
+
dateBucket,
|
|
16712
|
+
databaseType
|
|
16713
|
+
);
|
|
16714
|
+
row[pivot.rowField || ""] = dateString;
|
|
16715
|
+
});
|
|
16716
|
+
if (pivot.rowField && pivot.rowFieldType && !isStringType(pivot.rowFieldType) && dateFilter?.startDate && dateFilter?.endDate) {
|
|
16717
|
+
const dateSet = new Set(
|
|
16718
|
+
rows.map((row) => row[pivot.rowField || ""])
|
|
16719
|
+
);
|
|
16720
|
+
for (let date = dateFilter.startDate; date <= dateFilter.endDate; date = new Date(date.getTime() + 24 * 60 * 60 * 1e3)) {
|
|
16721
|
+
const formattedDate = getDateString(
|
|
16722
|
+
date.toISOString(),
|
|
16723
|
+
{ start: dateFilter.startDate, end: dateFilter.endDate },
|
|
16724
|
+
dateBucket,
|
|
16725
|
+
databaseType
|
|
16726
|
+
);
|
|
16727
|
+
if (!dateSet.has(formattedDate)) {
|
|
16728
|
+
const newRow = {};
|
|
16729
|
+
newRow[pivot.rowField] = formattedDate;
|
|
16730
|
+
newRow.__quillRawDate = date.toISOString();
|
|
16731
|
+
rows.push(newRow);
|
|
16732
|
+
dateSet.add(formattedDate);
|
|
16733
|
+
}
|
|
16734
|
+
}
|
|
16735
|
+
}
|
|
16736
|
+
if (!pivot.sort) {
|
|
16737
|
+
rows.sort((a, b) => {
|
|
16738
|
+
if (a.__quillRawDate < b.__quillRawDate) {
|
|
16739
|
+
return -1;
|
|
16740
|
+
}
|
|
16741
|
+
if (a.__quillRawDate > b.__quillRawDate) {
|
|
16742
|
+
return 1;
|
|
16743
|
+
}
|
|
16744
|
+
return 0;
|
|
16745
|
+
});
|
|
16746
|
+
}
|
|
16652
16747
|
}
|
|
16748
|
+
columns?.forEach((column, index) => {
|
|
16749
|
+
if (column.label && ["null", "undefined"].includes(column.label.toLowerCase()) && !pivot.columnField && !pivot.aggregations?.[index]?.valueField && pivot.aggregations?.[index]?.aggregationType === "count") {
|
|
16750
|
+
column.label = "Count";
|
|
16751
|
+
}
|
|
16752
|
+
});
|
|
16753
|
+
const numericColumns = columns?.filter(
|
|
16754
|
+
(column) => column.format === "whole_number" || column.format === "percentage"
|
|
16755
|
+
);
|
|
16756
|
+
rows.forEach((row) => {
|
|
16757
|
+
numericColumns?.forEach((column) => {
|
|
16758
|
+
row[column.field] = row[column.field] ?? 0;
|
|
16759
|
+
});
|
|
16760
|
+
});
|
|
16761
|
+
return {
|
|
16762
|
+
rows,
|
|
16763
|
+
columns: columns ?? [],
|
|
16764
|
+
rowCount: rowCount || rows.length,
|
|
16765
|
+
pivotQuery: report?.queryString || "",
|
|
16766
|
+
comparisonPivotQuery: comparisonPivotQuery || ""
|
|
16767
|
+
};
|
|
16653
16768
|
}
|
|
16654
|
-
function
|
|
16655
|
-
|
|
16656
|
-
|
|
16657
|
-
|
|
16658
|
-
|
|
16659
|
-
|
|
16660
|
-
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
case "day":
|
|
16664
|
-
return (0, import_date_fns7.startOfDay)(zonedDate);
|
|
16665
|
-
case "year":
|
|
16666
|
-
return (0, import_date_fns7.startOfYear)(zonedDate);
|
|
16667
|
-
default:
|
|
16668
|
-
throw new Error(`Unsupported granularity: ${granularity}`);
|
|
16769
|
+
function generatePivotTableYAxis(pivot, cols, yAxisField) {
|
|
16770
|
+
if (pivot?.aggregationType === "count") {
|
|
16771
|
+
return [
|
|
16772
|
+
{
|
|
16773
|
+
field: pivot.valueField ?? "count",
|
|
16774
|
+
label: yAxisField.label,
|
|
16775
|
+
format: yAxisField.format
|
|
16776
|
+
}
|
|
16777
|
+
];
|
|
16669
16778
|
}
|
|
16779
|
+
return [
|
|
16780
|
+
{
|
|
16781
|
+
field: pivot.valueField ?? "count",
|
|
16782
|
+
label: yAxisField.label,
|
|
16783
|
+
format: yAxisField.format
|
|
16784
|
+
}
|
|
16785
|
+
];
|
|
16670
16786
|
}
|
|
16671
|
-
function
|
|
16672
|
-
pivot
|
|
16673
|
-
|
|
16674
|
-
|
|
16675
|
-
|
|
16676
|
-
|
|
16677
|
-
|
|
16678
|
-
|
|
16787
|
+
function generatePivotTitle(pivot) {
|
|
16788
|
+
if (pivot.rowField && !pivot.valueField && pivot.aggregations?.[0]) {
|
|
16789
|
+
return snakeAndCamelCaseToTitleCase(
|
|
16790
|
+
`${pivot.aggregations[0].aggregationType} of ${pivot.rowField}${pivot.columnField ? ` by ${pivot.columnField}` : ""}
|
|
16791
|
+
`
|
|
16792
|
+
);
|
|
16793
|
+
} else if (!pivot.rowField && pivot.aggregations?.[0]?.valueField) {
|
|
16794
|
+
return snakeAndCamelCaseToTitleCase(
|
|
16795
|
+
`${pivot.aggregations[0].aggregationType} of ${pivot.aggregations[0].valueField}
|
|
16796
|
+
`
|
|
16797
|
+
);
|
|
16798
|
+
}
|
|
16799
|
+
return snakeAndCamelCaseToTitleCase(
|
|
16800
|
+
`${pivot.aggregations?.[0]?.aggregationType ?? "Aggregation"} of ${pivot.aggregations?.[0]?.valueField ?? "value"}${pivot.rowField ? ` by ${pivot.rowField}` : ""}${pivot.columnField ? ` and ${pivot.columnField}` : ""}`
|
|
16801
|
+
);
|
|
16679
16802
|
}
|
|
16680
|
-
function
|
|
16803
|
+
async function generatePivotTable({
|
|
16681
16804
|
pivot,
|
|
16682
|
-
rows,
|
|
16683
|
-
compRows,
|
|
16684
|
-
databaseType,
|
|
16685
16805
|
dateBucket,
|
|
16686
|
-
|
|
16687
|
-
|
|
16806
|
+
dateFilter,
|
|
16807
|
+
report,
|
|
16808
|
+
client,
|
|
16809
|
+
getToken,
|
|
16810
|
+
eventTracking,
|
|
16811
|
+
uniqueValues,
|
|
16812
|
+
dashboardName,
|
|
16813
|
+
tenants,
|
|
16814
|
+
additionalProcessing,
|
|
16815
|
+
caller,
|
|
16816
|
+
pivotQuery
|
|
16688
16817
|
}) {
|
|
16689
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
|
|
16707
|
-
|
|
16708
|
-
|
|
16709
|
-
|
|
16818
|
+
try {
|
|
16819
|
+
if (report && client) {
|
|
16820
|
+
const pivotTable = await generatePivotWithSQL({
|
|
16821
|
+
pivotQuery,
|
|
16822
|
+
pivot,
|
|
16823
|
+
report,
|
|
16824
|
+
client,
|
|
16825
|
+
dateBucket,
|
|
16826
|
+
dateFilter,
|
|
16827
|
+
dashboardName,
|
|
16828
|
+
tenants,
|
|
16829
|
+
additionalProcessing,
|
|
16830
|
+
caller,
|
|
16831
|
+
getToken
|
|
16832
|
+
});
|
|
16833
|
+
return pivotTable;
|
|
16834
|
+
}
|
|
16835
|
+
} catch (e) {
|
|
16836
|
+
eventTracking?.logError?.({
|
|
16837
|
+
type: "bug",
|
|
16838
|
+
// TODO: determine type
|
|
16839
|
+
severity: "high",
|
|
16840
|
+
message: "Error generating pivot table",
|
|
16841
|
+
errorMessage: e.message,
|
|
16842
|
+
errorStack: e.stack,
|
|
16843
|
+
errorData: {
|
|
16844
|
+
caller: "PivotModal",
|
|
16845
|
+
function: "generatePivotTable"
|
|
16846
|
+
}
|
|
16847
|
+
});
|
|
16848
|
+
throw Error(`Failed to generate pivot table with SQL: ${e}`);
|
|
16710
16849
|
}
|
|
16711
|
-
|
|
16850
|
+
throw Error("Failed to generate pivot table: invalid report");
|
|
16712
16851
|
}
|
|
16713
|
-
|
|
16714
|
-
|
|
16715
|
-
|
|
16716
|
-
|
|
16717
|
-
|
|
16718
|
-
|
|
16852
|
+
|
|
16853
|
+
// src/utils/paginationProcessing.ts
|
|
16854
|
+
var DEFAULT_PAGINATION = {
|
|
16855
|
+
page: 0,
|
|
16856
|
+
rowsPerPage: 10,
|
|
16857
|
+
rowsPerRequest: 600
|
|
16858
|
+
};
|
|
16859
|
+
var DEFAULT_TABLE_PAGINATION = {
|
|
16860
|
+
page: 0,
|
|
16861
|
+
rowsPerPage: 10,
|
|
16862
|
+
rowsPerRequest: 50
|
|
16863
|
+
};
|
|
16864
|
+
function shouldFetchMore(pagination, page, maxPage, currentRowCount) {
|
|
16865
|
+
if (!pagination || currentRowCount && currentRowCount >= pagination.rowsPerPage * (page + 1)) {
|
|
16866
|
+
return false;
|
|
16719
16867
|
}
|
|
16720
|
-
|
|
16721
|
-
|
|
16722
|
-
|
|
16723
|
-
|
|
16724
|
-
|
|
16725
|
-
|
|
16726
|
-
|
|
16727
|
-
comparisonInterval
|
|
16868
|
+
const indexAdjustedPage = page;
|
|
16869
|
+
const pageInterval = Math.floor(
|
|
16870
|
+
indexAdjustedPage * pagination.rowsPerPage / pagination.rowsPerRequest
|
|
16871
|
+
);
|
|
16872
|
+
const indexAdjustedPreviousPage = maxPage;
|
|
16873
|
+
const previousPageInterval = Math.floor(
|
|
16874
|
+
indexAdjustedPreviousPage * pagination.rowsPerPage / pagination.rowsPerRequest
|
|
16728
16875
|
);
|
|
16876
|
+
return pageInterval > previousPageInterval;
|
|
16729
16877
|
}
|
|
16730
|
-
function
|
|
16731
|
-
if (!
|
|
16732
|
-
return
|
|
16878
|
+
function shouldSortInMemory(pagination, rowCount) {
|
|
16879
|
+
if (!rowCount || rowCount < pagination.rowsPerRequest) {
|
|
16880
|
+
return true;
|
|
16733
16881
|
}
|
|
16734
|
-
return
|
|
16735
|
-
const matchingCompRow = compRows.find(
|
|
16736
|
-
(compRow) => compRow[pivot.rowField] === row[pivot.rowField]
|
|
16737
|
-
);
|
|
16738
|
-
const comparisonFields = columnFieldValues.reduce(
|
|
16739
|
-
(acc, fieldValue) => {
|
|
16740
|
-
acc[`comparison_${fieldValue}`] = matchingCompRow ? matchingCompRow[fieldValue] || null : null;
|
|
16741
|
-
return acc;
|
|
16742
|
-
},
|
|
16743
|
-
{}
|
|
16744
|
-
);
|
|
16745
|
-
return {
|
|
16746
|
-
...row,
|
|
16747
|
-
...comparisonFields
|
|
16748
|
-
};
|
|
16749
|
-
});
|
|
16882
|
+
return false;
|
|
16750
16883
|
}
|
|
16751
|
-
|
|
16752
|
-
|
|
16753
|
-
|
|
16754
|
-
|
|
16755
|
-
|
|
16756
|
-
|
|
16757
|
-
|
|
16758
|
-
|
|
16759
|
-
|
|
16760
|
-
|
|
16761
|
-
|
|
16762
|
-
|
|
16763
|
-
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
|
|
16769
|
-
|
|
16770
|
-
|
|
16771
|
-
|
|
16772
|
-
|
|
16773
|
-
|
|
16774
|
-
|
|
16775
|
-
|
|
16776
|
-
|
|
16884
|
+
|
|
16885
|
+
// src/utils/dashboard.ts
|
|
16886
|
+
var defaultDashboardItem = {
|
|
16887
|
+
id: "",
|
|
16888
|
+
name: "",
|
|
16889
|
+
dashboardName: "",
|
|
16890
|
+
rows: [],
|
|
16891
|
+
compareRows: [],
|
|
16892
|
+
columns: [],
|
|
16893
|
+
chartType: "",
|
|
16894
|
+
pivot: null,
|
|
16895
|
+
yAxisFields: [],
|
|
16896
|
+
xAxisLabel: "",
|
|
16897
|
+
xAxisField: "",
|
|
16898
|
+
xAxisFormat: "string",
|
|
16899
|
+
order: -1,
|
|
16900
|
+
filtersApplied: [],
|
|
16901
|
+
queryString: "",
|
|
16902
|
+
rowCount: 0,
|
|
16903
|
+
columnInternal: []
|
|
16904
|
+
};
|
|
16905
|
+
async function cleanDashboardItem({
|
|
16906
|
+
item,
|
|
16907
|
+
dashboardFilters,
|
|
16908
|
+
getToken,
|
|
16909
|
+
eventTracking,
|
|
16910
|
+
client,
|
|
16911
|
+
dateBucket,
|
|
16912
|
+
additionalProcessing,
|
|
16913
|
+
customFields,
|
|
16914
|
+
skipPivotFetch,
|
|
16915
|
+
tenants
|
|
16916
|
+
}) {
|
|
16917
|
+
if (!item) return defaultDashboardItem;
|
|
16918
|
+
if (!item.rows) {
|
|
16777
16919
|
return {
|
|
16778
|
-
...
|
|
16779
|
-
|
|
16920
|
+
...defaultDashboardItem,
|
|
16921
|
+
id: item._id,
|
|
16922
|
+
name: item.name
|
|
16780
16923
|
};
|
|
16781
|
-
});
|
|
16782
|
-
}
|
|
16783
|
-
function merge1DPivotRows(pivot, rows, compRows, databaseType, dateBucket, comparisonInterval) {
|
|
16784
|
-
if (isStringType(pivot.rowFieldType || "") || !pivot.rowFieldType) {
|
|
16785
|
-
return merge1DStringPivotRows(pivot, rows, compRows);
|
|
16786
16924
|
}
|
|
16787
|
-
|
|
16788
|
-
|
|
16789
|
-
|
|
16790
|
-
|
|
16791
|
-
|
|
16792
|
-
|
|
16793
|
-
|
|
16794
|
-
|
|
16795
|
-
|
|
16796
|
-
|
|
16797
|
-
|
|
16798
|
-
|
|
16925
|
+
const fields = item.fields || [];
|
|
16926
|
+
const columnsWithCustomFields = [...item.columns ?? []];
|
|
16927
|
+
if (item.includeCustomFields && item.rows?.length > 0) {
|
|
16928
|
+
const tables = item.referencedTables ?? [];
|
|
16929
|
+
tables.forEach((table) => {
|
|
16930
|
+
const _customFields = customFields?.[table] ?? [];
|
|
16931
|
+
_customFields.forEach((field) => {
|
|
16932
|
+
const isJsonCustomField = !!field.refColumn;
|
|
16933
|
+
if (item.rows[0][field.field] !== void 0 && !item.columns.some((col) => col.field === field.field)) {
|
|
16934
|
+
const result_field = fields.find((f) => f.name === field.field);
|
|
16935
|
+
const converted_field = convertPostgresColumn(result_field ?? {});
|
|
16936
|
+
columnsWithCustomFields.push({
|
|
16937
|
+
field: field.field,
|
|
16938
|
+
format: converted_field.format,
|
|
16939
|
+
label: snakeAndCamelCaseToTitleCase(field.field),
|
|
16940
|
+
fieldType: converted_field.fieldType,
|
|
16941
|
+
dataTypeID: converted_field.dataTypeID,
|
|
16942
|
+
jsType: converted_field.jsType,
|
|
16943
|
+
inferFormat: isJsonCustomField
|
|
16944
|
+
});
|
|
16945
|
+
}
|
|
16946
|
+
});
|
|
16947
|
+
});
|
|
16799
16948
|
}
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
(compRow) => compRow[pivot.rowField] === row[pivot.rowField]
|
|
16803
|
-
);
|
|
16804
|
-
let aggregationSuffix = "";
|
|
16805
|
-
if (matchingCompRow && pivot.aggregationType === "percentage") {
|
|
16806
|
-
if (matchingCompRow[`${pivot.valueField}_Percentage`]) {
|
|
16807
|
-
aggregationSuffix = "_Percentage";
|
|
16808
|
-
} else if (matchingCompRow[`${pivot.valueField}_PERCENTAGE`]) {
|
|
16809
|
-
aggregationSuffix = "_PERCENTAGE";
|
|
16810
|
-
} else {
|
|
16811
|
-
aggregationSuffix = "_percentage";
|
|
16812
|
-
}
|
|
16813
|
-
}
|
|
16814
|
-
return {
|
|
16815
|
-
...row,
|
|
16816
|
-
[`comparison_${pivot.valueField}${aggregationSuffix}`]: matchingCompRow ? matchingCompRow[`${pivot.valueField}${aggregationSuffix}`] : null
|
|
16817
|
-
};
|
|
16949
|
+
const processedColumns = item.columns.map((col) => {
|
|
16950
|
+
return { ...col, label: snakeAndCamelCaseToTitleCase(col.label) };
|
|
16818
16951
|
});
|
|
16819
|
-
|
|
16820
|
-
|
|
16821
|
-
|
|
16822
|
-
return rows;
|
|
16823
|
-
}
|
|
16824
|
-
return rows.map((row) => {
|
|
16825
|
-
const rowDate = typeof row[pivot.rowField] === "string" ? new Date(row[pivot.rowField]) : row[pivot.rowField];
|
|
16826
|
-
const truncatedRowDate = dateTrunc(rowDate, dateBucket, databaseType);
|
|
16827
|
-
const matchingCompRow = compRows.find((compRow) => {
|
|
16828
|
-
const comparisonDateWithInterval = dateAdder(
|
|
16829
|
-
compRow[`${pivot.rowField}`],
|
|
16830
|
-
comparisonInterval
|
|
16831
|
-
);
|
|
16832
|
-
const truncatedCompRowDate = dateTrunc(
|
|
16833
|
-
comparisonDateWithInterval,
|
|
16834
|
-
dateBucket,
|
|
16835
|
-
databaseType
|
|
16836
|
-
);
|
|
16837
|
-
return truncatedRowDate.toISOString() === truncatedCompRowDate.toISOString();
|
|
16838
|
-
});
|
|
16839
|
-
let aggregationSuffix = "";
|
|
16840
|
-
if (matchingCompRow && pivot.aggregationType === "percentage") {
|
|
16841
|
-
if (matchingCompRow[`${pivot.valueField}_Percentage`]) {
|
|
16842
|
-
aggregationSuffix = "_Percentage";
|
|
16843
|
-
} else if (matchingCompRow[`${pivot.valueField}_PERCENTAGE`]) {
|
|
16844
|
-
aggregationSuffix = "_PERCENTAGE";
|
|
16845
|
-
} else {
|
|
16846
|
-
aggregationSuffix = "_percentage";
|
|
16847
|
-
}
|
|
16848
|
-
}
|
|
16952
|
+
const columnInternal = (item.includeCustomFields ? columnsWithCustomFields : item.columns).map((col) => {
|
|
16953
|
+
const field = item.fields?.find((f) => f.name === col.field);
|
|
16954
|
+
const converted_field = convertPostgresColumn(field ?? {});
|
|
16849
16955
|
return {
|
|
16850
|
-
|
|
16851
|
-
|
|
16956
|
+
fieldType: converted_field.fieldType,
|
|
16957
|
+
dataTypeID: converted_field.dataTypeID,
|
|
16958
|
+
jsType: converted_field.jsType,
|
|
16959
|
+
...col,
|
|
16960
|
+
label: snakeAndCamelCaseToTitleCase(col.label)
|
|
16852
16961
|
};
|
|
16853
16962
|
});
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
16864
|
-
|
|
16963
|
+
let pivotTable;
|
|
16964
|
+
let pivotError;
|
|
16965
|
+
try {
|
|
16966
|
+
const shouldPaginatePivotAsTable = item.chartType === "table";
|
|
16967
|
+
const pivotChartProcessing = {
|
|
16968
|
+
page: DEFAULT_PAGINATION
|
|
16969
|
+
};
|
|
16970
|
+
pivotTable = await getPivotTable(
|
|
16971
|
+
{
|
|
16972
|
+
...item,
|
|
16973
|
+
pivot: item.pivot && !skipPivotFetch ? {
|
|
16974
|
+
...item.pivot,
|
|
16975
|
+
aggregations: item.pivot.aggregations ?? [
|
|
16976
|
+
{
|
|
16977
|
+
valueField: item.pivot.valueField,
|
|
16978
|
+
valueFieldType: item.pivot.valueFieldType,
|
|
16979
|
+
valueField2: item.pivot.valueField2,
|
|
16980
|
+
valueField2Type: item.pivot.valueField2Type,
|
|
16981
|
+
aggregationType: item.pivot.aggregationType
|
|
16982
|
+
}
|
|
16983
|
+
]
|
|
16984
|
+
} : void 0
|
|
16985
|
+
},
|
|
16986
|
+
dashboardFilters,
|
|
16987
|
+
item.dashboardName,
|
|
16988
|
+
getToken,
|
|
16989
|
+
client,
|
|
16990
|
+
eventTracking,
|
|
16991
|
+
dateBucket,
|
|
16992
|
+
shouldPaginatePivotAsTable ? additionalProcessing : pivotChartProcessing,
|
|
16993
|
+
tenants,
|
|
16994
|
+
customFields
|
|
16995
|
+
);
|
|
16996
|
+
} catch (e) {
|
|
16997
|
+
pivotTable = void 0;
|
|
16998
|
+
eventTracking?.logError?.({
|
|
16999
|
+
type: "bug",
|
|
17000
|
+
// TODO: determine type
|
|
17001
|
+
severity: "high",
|
|
17002
|
+
message: "Error fetching pivot table",
|
|
17003
|
+
errorMessage: e.message,
|
|
17004
|
+
errorStack: e.stack,
|
|
17005
|
+
errorData: {
|
|
17006
|
+
caller: "cleanDashboardItem",
|
|
17007
|
+
function: "cleanDashboardItem"
|
|
16865
17008
|
}
|
|
17009
|
+
});
|
|
17010
|
+
console.error("Error fetching pivot table", e);
|
|
17011
|
+
pivotError = "Error fetching pivot table";
|
|
17012
|
+
}
|
|
17013
|
+
const referenceLineYValues = [];
|
|
17014
|
+
for (const key in item) {
|
|
17015
|
+
if (key.startsWith("referenceLine_")) {
|
|
17016
|
+
const field = key.slice(14);
|
|
17017
|
+
if (!item[key] || !item[key][0]) continue;
|
|
17018
|
+
const value = Object.values(item[key][0])[0];
|
|
17019
|
+
referenceLineYValues.push({ label: field, query: [value, value] });
|
|
16866
17020
|
}
|
|
16867
|
-
const compRow = {
|
|
16868
|
-
[`comparison_${pivot.valueField}${aggregationSuffix}`]: compRows[i]?.[`${pivot.valueField}${aggregationSuffix}`]
|
|
16869
|
-
};
|
|
16870
|
-
return { ...row, ...compRow };
|
|
16871
|
-
});
|
|
16872
|
-
}
|
|
16873
|
-
|
|
16874
|
-
// src/utils/queryConstructor.ts
|
|
16875
|
-
function processSingleQuotes(value, databaseType) {
|
|
16876
|
-
if (["postgresql", "snowflake", "clickhouse"].includes(
|
|
16877
|
-
databaseType.toLowerCase()
|
|
16878
|
-
)) {
|
|
16879
|
-
return value.replaceAll("'", "''");
|
|
16880
17021
|
}
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16892
|
-
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
return fallbackOnNull ? `"${fallbackOnNull}"` : `"_"`;
|
|
16896
|
-
}
|
|
16897
|
-
if (isColumnFieldAlias) {
|
|
16898
|
-
return `"${column.replaceAll('"', "")}"`;
|
|
16899
|
-
}
|
|
16900
|
-
const columnParts = column.split(".");
|
|
16901
|
-
if (columnParts.length > 1) {
|
|
16902
|
-
return `"` + columnParts.map((part) => part.replaceAll('"', "")).join('"."') + `"`;
|
|
17022
|
+
if (item.referenceLines) {
|
|
17023
|
+
for (const referenceLine of item.referenceLines) {
|
|
17024
|
+
if (Array.isArray(referenceLine.query)) {
|
|
17025
|
+
referenceLineYValues.push({
|
|
17026
|
+
label: referenceLine.label,
|
|
17027
|
+
query: referenceLine.query
|
|
17028
|
+
});
|
|
17029
|
+
} else if (referenceLine.query === "") {
|
|
17030
|
+
referenceLineYValues.push({
|
|
17031
|
+
label: referenceLine.label,
|
|
17032
|
+
query: (pivotTable?.rows ? pivotTable.rows : item.rows).map(
|
|
17033
|
+
(row) => Number(row[referenceLine.label]) || 0
|
|
17034
|
+
)
|
|
17035
|
+
});
|
|
16903
17036
|
}
|
|
16904
|
-
return `"${column.replaceAll('"', "")}"`;
|
|
16905
17037
|
}
|
|
16906
|
-
|
|
16907
|
-
|
|
16908
|
-
|
|
16909
|
-
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
|
|
16915
|
-
|
|
16916
|
-
|
|
17038
|
+
}
|
|
17039
|
+
return {
|
|
17040
|
+
id: item._id ?? item.id,
|
|
17041
|
+
name: item.name,
|
|
17042
|
+
dashboardName: item.dashboardName,
|
|
17043
|
+
// section: item.section,
|
|
17044
|
+
rows: item.rows,
|
|
17045
|
+
pivotRows: pivotTable ? pivotTable.rows : void 0,
|
|
17046
|
+
pivotColumns: pivotTable ? pivotTable.columns : void 0,
|
|
17047
|
+
compareRows: item.compareRows,
|
|
17048
|
+
columns: processedColumns.map((column) => {
|
|
17049
|
+
return {
|
|
17050
|
+
field: column.field,
|
|
17051
|
+
format: column.format,
|
|
17052
|
+
label: column.label,
|
|
17053
|
+
inferFormat: column.inferFormat
|
|
17054
|
+
};
|
|
17055
|
+
}),
|
|
17056
|
+
includeCustomFields: item.includeCustomFields,
|
|
17057
|
+
columnInternal,
|
|
17058
|
+
columnsWithCustomFields,
|
|
17059
|
+
chartType: item.chartType,
|
|
17060
|
+
dateField: item.dateField,
|
|
17061
|
+
pivot: pivotError ? void 0 : item.pivot ? {
|
|
17062
|
+
...item.pivot,
|
|
17063
|
+
aggregations: item.pivot.aggregations ?? [
|
|
17064
|
+
{
|
|
17065
|
+
valueField: item.pivot.valueField,
|
|
17066
|
+
valueFieldType: item.pivot.valueFieldType,
|
|
17067
|
+
valueField2: item.pivot.valueField2,
|
|
17068
|
+
valueField2Type: item.pivot.valueField2Type,
|
|
17069
|
+
aggregationType: item.pivot.aggregationType
|
|
17070
|
+
}
|
|
17071
|
+
],
|
|
17072
|
+
columnValues: item.distinctStrings
|
|
17073
|
+
} : void 0,
|
|
17074
|
+
yAxisFields: pivotTable ? extractPivotedYAxis(pivotTable, item) : item.yAxisFields,
|
|
17075
|
+
xAxisLabel: item.xAxisLabel,
|
|
17076
|
+
xAxisField: item.xAxisField,
|
|
17077
|
+
xAxisFormat: item.xAxisFormat,
|
|
17078
|
+
order: item.order,
|
|
17079
|
+
filtersApplied: item.filtersApplied,
|
|
17080
|
+
filterMap: item.filterMap,
|
|
17081
|
+
flags: item.flags,
|
|
17082
|
+
rowCount: item.rowCount ? parseInt(item.rowCount) : item.rows.length,
|
|
17083
|
+
pivotRowCount: pivotTable ? pivotTable.rowCount : void 0,
|
|
17084
|
+
template: item.template,
|
|
17085
|
+
sort: item.sort,
|
|
17086
|
+
itemQuery: item.itemQuery,
|
|
17087
|
+
queryString: item.queryString,
|
|
17088
|
+
pivotQuery: pivotTable?.pivotQuery,
|
|
17089
|
+
comparisonPivotQuery: pivotTable?.comparisonPivotQuery,
|
|
17090
|
+
referencedTables: item?.referencedTables || [],
|
|
17091
|
+
referencedColumns: item?.referencedColumns || {},
|
|
17092
|
+
error: item.error ?? pivotError,
|
|
17093
|
+
referenceLineYValues,
|
|
17094
|
+
referenceLines: item.referenceLines
|
|
17095
|
+
};
|
|
17096
|
+
}
|
|
17097
|
+
async function getPivotTable(report, dashboardFilters, dashboardName, getToken, client, eventTracking, dateBucketInitial, additionalProcessing, tenants, customFields) {
|
|
17098
|
+
if (!report) return void 0;
|
|
17099
|
+
const dateFilter = Object.values(dashboardFilters ?? {}).find(
|
|
17100
|
+
(filter) => filter.filterType === "date_range" || filter.operator === "BETWEEN"
|
|
17101
|
+
);
|
|
17102
|
+
if (dateFilter?.operator === "BETWEEN") {
|
|
17103
|
+
dateFilter.startDate = dateFilter.value[0];
|
|
17104
|
+
dateFilter.endDate = dateFilter.value[1];
|
|
17105
|
+
}
|
|
17106
|
+
const pivot = report?.pivot;
|
|
17107
|
+
const data = report || {};
|
|
17108
|
+
if (pivot && client) {
|
|
17109
|
+
if (report.rowCount === 0 || report.rows.length === 0) {
|
|
17110
|
+
const columns = [];
|
|
17111
|
+
if (pivot.rowField) {
|
|
17112
|
+
columns.push({
|
|
17113
|
+
field: pivot.rowField,
|
|
17114
|
+
label: snakeCaseToTitleCase(processColumnName(pivot.rowField)),
|
|
17115
|
+
format: pivot.rowFieldType || "string",
|
|
17116
|
+
jsType: convertFieldTypeToJSType(pivot.rowFieldType || "string"),
|
|
17117
|
+
fieldType: pivot.rowFieldType || "string",
|
|
17118
|
+
dataTypeID: fieldTypeToDataTypeID(pivot.rowFieldType || "string")
|
|
17119
|
+
});
|
|
17120
|
+
}
|
|
17121
|
+
for (const agg of pivot.aggregations ?? []) {
|
|
17122
|
+
if (agg.valueField) {
|
|
17123
|
+
columns.push({
|
|
17124
|
+
field: agg.valueField,
|
|
17125
|
+
label: snakeCaseToTitleCase(processColumnName(agg.valueField)),
|
|
17126
|
+
//FIXME: valueFieldType is not always the same as the format
|
|
17127
|
+
format: agg.valueFieldType ?? "whole_number",
|
|
17128
|
+
jsType: agg.valueFieldType ?? "number",
|
|
17129
|
+
fieldType: agg.valueFieldType ?? "number",
|
|
17130
|
+
dataTypeID: fieldTypeToDataTypeID(agg.valueFieldType ?? "number")
|
|
17131
|
+
});
|
|
17132
|
+
}
|
|
17133
|
+
}
|
|
17134
|
+
return {
|
|
17135
|
+
rows: [],
|
|
17136
|
+
rowCount: 0,
|
|
17137
|
+
pivotQuery: report.queryString ?? "",
|
|
17138
|
+
columns
|
|
17139
|
+
};
|
|
17140
|
+
}
|
|
17141
|
+
try {
|
|
17142
|
+
let dateBucket = dateBucketInitial;
|
|
17143
|
+
let filterDateRange = void 0;
|
|
17144
|
+
if (dateFilter && dateFilter.startDate && dateFilter.endDate) {
|
|
17145
|
+
filterDateRange = {
|
|
17146
|
+
start: dateFilter.startDate,
|
|
17147
|
+
end: dateFilter.endDate
|
|
17148
|
+
};
|
|
17149
|
+
} else if (report.dateRange) {
|
|
17150
|
+
filterDateRange = report.dateRange;
|
|
17151
|
+
}
|
|
17152
|
+
if (!dateBucket && filterDateRange) {
|
|
17153
|
+
dateBucket = getDateBucketFromRange(filterDateRange);
|
|
17154
|
+
}
|
|
17155
|
+
const pivotTable = await generatePivotWithSQL({
|
|
17156
|
+
pivot,
|
|
17157
|
+
report,
|
|
17158
|
+
client,
|
|
17159
|
+
dateBucket,
|
|
17160
|
+
dateFilter,
|
|
17161
|
+
dashboardName,
|
|
17162
|
+
tenants,
|
|
17163
|
+
additionalProcessing,
|
|
17164
|
+
getToken
|
|
17165
|
+
});
|
|
17166
|
+
return pivotTable;
|
|
17167
|
+
} catch (e) {
|
|
17168
|
+
eventTracking?.logError?.({
|
|
17169
|
+
type: "bug",
|
|
17170
|
+
// TODO: determine type
|
|
17171
|
+
severity: "high",
|
|
17172
|
+
message: "Error fetching pivot table",
|
|
17173
|
+
errorMessage: e.message,
|
|
17174
|
+
errorStack: e.stack,
|
|
17175
|
+
errorData: {
|
|
17176
|
+
caller: "getPivotTable",
|
|
17177
|
+
function: "getPivotTable"
|
|
17178
|
+
}
|
|
17179
|
+
});
|
|
17180
|
+
console.error("Error fetching pivot table", e);
|
|
17181
|
+
throw e;
|
|
17182
|
+
}
|
|
17183
|
+
}
|
|
17184
|
+
return pivot && data.rows ? generatePivotTable({
|
|
17185
|
+
pivot,
|
|
17186
|
+
report,
|
|
17187
|
+
client,
|
|
17188
|
+
uniqueValues: report.distinctStrings,
|
|
17189
|
+
dashboardName,
|
|
17190
|
+
tenants,
|
|
17191
|
+
dateFilter,
|
|
17192
|
+
additionalProcessing,
|
|
17193
|
+
getToken,
|
|
17194
|
+
eventTracking
|
|
17195
|
+
}) : void 0;
|
|
17196
|
+
}
|
|
17197
|
+
function extractPivotedYAxis(pivotTable, itemInfo, config = void 0) {
|
|
17198
|
+
if (!pivotTable) return itemInfo?.yAxisFields ?? [];
|
|
17199
|
+
const pivot = itemInfo?.pivot || config?.pivot;
|
|
17200
|
+
if (!pivot.columnField && !pivot.rowField) return itemInfo?.yAxisFields ?? [];
|
|
17201
|
+
const yAxisFields = config ? config.yAxisFields : itemInfo?.yAxisFields;
|
|
17202
|
+
return yAxisFields && yAxisFields.length > 0 ? generatePivotTableYAxis(pivot, pivotTable.columns, yAxisFields[0]) : yAxisFields;
|
|
17203
|
+
}
|
|
17204
|
+
async function getDashboard(dashboardName, client, getToken, tenants, flags) {
|
|
17205
|
+
const { data: resp } = await quillFetch({
|
|
17206
|
+
client,
|
|
17207
|
+
task: "dashboard",
|
|
17208
|
+
metadata: {
|
|
17209
|
+
name: dashboardName,
|
|
17210
|
+
clientId: client.publicKey,
|
|
17211
|
+
databaseType: client.databaseType,
|
|
17212
|
+
useNewNodeSql: true,
|
|
17213
|
+
tenants,
|
|
17214
|
+
flags
|
|
17215
|
+
},
|
|
17216
|
+
getToken
|
|
17217
|
+
});
|
|
17218
|
+
return {
|
|
17219
|
+
...resp,
|
|
17220
|
+
createdAt: resp.createdAt && new Date(resp.createdAt),
|
|
17221
|
+
dateFilter: resp.dateFilter ? {
|
|
17222
|
+
...resp.dateFilter,
|
|
17223
|
+
presetOptions: resp.dateFilter.presetOptions?.map(
|
|
17224
|
+
(preset) => ({
|
|
17225
|
+
...preset,
|
|
17226
|
+
loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
|
|
17227
|
+
loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
|
|
17228
|
+
})
|
|
17229
|
+
),
|
|
17230
|
+
defaultPresetRanges: resp.dateFilter.defaultPresetRanges?.map(
|
|
17231
|
+
(preset) => ({
|
|
17232
|
+
...preset,
|
|
17233
|
+
loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
|
|
17234
|
+
loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
|
|
17235
|
+
})
|
|
17236
|
+
)
|
|
17237
|
+
} : void 0
|
|
17238
|
+
};
|
|
17239
|
+
}
|
|
17240
|
+
|
|
17241
|
+
// src/utils/chartBuilder.ts
|
|
17242
|
+
var numberFormatOptions = [
|
|
17243
|
+
"whole_number",
|
|
17244
|
+
"one_decimal_place",
|
|
17245
|
+
"two_decimal_places",
|
|
17246
|
+
"dollar_amount",
|
|
17247
|
+
"dollar_cents",
|
|
17248
|
+
"percentage"
|
|
17249
|
+
];
|
|
17250
|
+
var dateFormatOptions = [
|
|
17251
|
+
"MMM_yyyy",
|
|
17252
|
+
"MMM_dd",
|
|
17253
|
+
"MMM_dd_yyyy",
|
|
17254
|
+
"MMM_dd_hh:mm_ap_pm",
|
|
17255
|
+
"hh_ap_pm",
|
|
17256
|
+
"date",
|
|
17257
|
+
"timestamptz"
|
|
17258
|
+
];
|
|
17259
|
+
var NUMBER_OPTIONS = [
|
|
17260
|
+
{ value: "whole_number", label: "whole number" },
|
|
17261
|
+
{ value: "one_decimal_place", label: "one decimal place" },
|
|
17262
|
+
{ value: "two_decimal_places", label: "two decimal places" },
|
|
17263
|
+
{ value: "dollar_amount", label: "dollar amount" },
|
|
17264
|
+
{ value: "dollar_cents", label: "dollar and cent amount" },
|
|
17265
|
+
{ value: "percent", label: "percentage" }
|
|
17266
|
+
];
|
|
17267
|
+
var DATE_OPTIONS = [
|
|
17268
|
+
{ value: "MMM_yyyy", label: "month" },
|
|
17269
|
+
{ value: "MMM_dd", label: "day" },
|
|
17270
|
+
{ value: "MMM_dd_yyyy", label: "day and year" },
|
|
17271
|
+
{ value: "MMM_dd_hh:mm_ap_pm", label: "day and time" },
|
|
17272
|
+
{ value: "hh_ap_pm", label: "hour" }
|
|
17273
|
+
];
|
|
17274
|
+
var ALL_FORMAT_OPTIONS = [
|
|
17275
|
+
...NUMBER_OPTIONS,
|
|
17276
|
+
...DATE_OPTIONS,
|
|
17277
|
+
{ value: "string", label: "string" }
|
|
17278
|
+
];
|
|
17279
|
+
function createInitialFormData(columns) {
|
|
17280
|
+
const firstNumberColumn = columns?.find(
|
|
17281
|
+
(col) => numberFormatOptions.includes(col.format)
|
|
17282
|
+
);
|
|
17283
|
+
const firstStringColumn = columns?.find(
|
|
17284
|
+
(col) => !numberFormatOptions.includes(col.format) && !dateFormatOptions.includes(col.format)
|
|
17285
|
+
);
|
|
17286
|
+
const firstDateColumn = columns?.find(
|
|
17287
|
+
(col) => dateFormatOptions.includes(col.format)
|
|
17288
|
+
);
|
|
17289
|
+
const xAxisField = firstStringColumn?.field || firstDateColumn?.field || firstNumberColumn?.field || columns?.[0]?.field || "";
|
|
17290
|
+
const xAxisFormat = firstStringColumn?.format || firstDateColumn?.format || firstNumberColumn?.format || columns?.[0]?.format || "string";
|
|
17291
|
+
const formEmptyState = {
|
|
17292
|
+
name: "",
|
|
17293
|
+
columns: columns.map((col) => {
|
|
17294
|
+
return { ...col, label: snakeAndCamelCaseToTitleCase(col.label) };
|
|
17295
|
+
}),
|
|
17296
|
+
xAxisField,
|
|
17297
|
+
xAxisFormat,
|
|
17298
|
+
yAxisFields: [
|
|
17299
|
+
{
|
|
17300
|
+
field: firstNumberColumn?.field || columns?.[0]?.field || "",
|
|
17301
|
+
label: "",
|
|
17302
|
+
format: firstNumberColumn?.format || columns?.[0]?.format || "string"
|
|
17303
|
+
}
|
|
17304
|
+
],
|
|
17305
|
+
xAxisLabel: "",
|
|
17306
|
+
chartType: firstNumberColumn ? "line" : "table",
|
|
17307
|
+
pivot: null,
|
|
17308
|
+
template: true,
|
|
17309
|
+
referenceLines: []
|
|
17310
|
+
};
|
|
17311
|
+
return formEmptyState;
|
|
17312
|
+
}
|
|
17313
|
+
|
|
17314
|
+
// src/utils/error.ts
|
|
17315
|
+
var DataLoadError = class extends Error {
|
|
17316
|
+
data;
|
|
17317
|
+
constructor(message, data) {
|
|
17318
|
+
super(message);
|
|
17319
|
+
this.name = "DataLoadError";
|
|
17320
|
+
this.data = data;
|
|
17321
|
+
}
|
|
17322
|
+
};
|
|
17323
|
+
|
|
17324
|
+
// src/utils/errorProcessing.ts
|
|
17325
|
+
function processFilterErrorList(resp) {
|
|
17326
|
+
if (!resp || !resp.filterErrorList || !Array.isArray(resp.filterErrorList)) {
|
|
17327
|
+
return;
|
|
17328
|
+
}
|
|
17329
|
+
}
|
|
17330
|
+
|
|
17331
|
+
// src/utils/queryConstructor.ts
|
|
17332
|
+
function replaceBigQuerySpecialCharacters(column) {
|
|
17333
|
+
return column.replaceAll("/", "quill_forward_slash");
|
|
17334
|
+
}
|
|
17335
|
+
function processColumnReference(column, databaseType, fallbackOnNull, isColumnFieldAlias, isValueFieldAlias) {
|
|
17336
|
+
switch (databaseType.toLowerCase()) {
|
|
17337
|
+
case "postgresql":
|
|
17338
|
+
case "clickhouse": {
|
|
17339
|
+
if (column === "") {
|
|
17340
|
+
return fallbackOnNull ? `"${fallbackOnNull}"` : `"_"`;
|
|
17341
|
+
}
|
|
17342
|
+
if (isColumnFieldAlias) {
|
|
17343
|
+
return `"${column.replaceAll('"', "")}"`;
|
|
17344
|
+
}
|
|
17345
|
+
const columnParts = column.split(".");
|
|
17346
|
+
if (columnParts.length > 1) {
|
|
17347
|
+
return `"` + columnParts.map((part) => part.replaceAll('"', "")).join('"."') + `"`;
|
|
17348
|
+
}
|
|
17349
|
+
return `"${column.replaceAll('"', "")}"`;
|
|
17350
|
+
}
|
|
17351
|
+
case "mysql": {
|
|
17352
|
+
if (column === "") {
|
|
17353
|
+
return fallbackOnNull ? `${fallbackOnNull}` : "_";
|
|
17354
|
+
}
|
|
17355
|
+
if (isColumnFieldAlias) {
|
|
17356
|
+
return `\`${column.replaceAll(`\``, "").replaceAll(`"`, "")}\``;
|
|
17357
|
+
}
|
|
17358
|
+
const columnParts = column.split(".");
|
|
17359
|
+
if (columnParts.length > 1) {
|
|
17360
|
+
return `\`` + columnParts.map((part) => part.replaceAll(`\``, "")).join("`.`") + `\``;
|
|
17361
|
+
}
|
|
16917
17362
|
return `\`${column.replaceAll(`\``, "")}\``;
|
|
16918
17363
|
}
|
|
16919
17364
|
case "snowflake": {
|
|
@@ -16975,51 +17420,6 @@ function processColumnReference(column, databaseType, fallbackOnNull, isColumnFi
|
|
|
16975
17420
|
function replaceSpacesWithUnderscores(column) {
|
|
16976
17421
|
return column.replaceAll(" ", "_");
|
|
16977
17422
|
}
|
|
16978
|
-
function processInterval(interval2, rowField, databaseType) {
|
|
16979
|
-
if (["postgresql", "snowflake", "clickhouse"].includes(
|
|
16980
|
-
databaseType.toLowerCase()
|
|
16981
|
-
)) {
|
|
16982
|
-
return `(${processColumnReference(rowField, databaseType)} + INTERVAL '${interval2}')`;
|
|
16983
|
-
} else if (databaseType.toLowerCase() === "mysql") {
|
|
16984
|
-
return `(${processColumnReference(rowField, databaseType)} + INTERVAL ${interval2})`;
|
|
16985
|
-
}
|
|
16986
|
-
return `TIMESTAMP_ADD(${processColumnReference(rowField, databaseType)}, INTERVAL ${interval2} )`;
|
|
16987
|
-
}
|
|
16988
|
-
function processDateTrunc(dateBucket, rowField, databaseType, comparisonInterval) {
|
|
16989
|
-
const dateField = comparisonInterval ? processInterval(comparisonInterval, rowField, databaseType) : processColumnReference(rowField, databaseType);
|
|
16990
|
-
if (["postgresql", "snowflake"].includes(databaseType.toLowerCase())) {
|
|
16991
|
-
return `date_trunc('${dateBucket}', ${dateField})`;
|
|
16992
|
-
}
|
|
16993
|
-
if (["clickhouse"].includes(databaseType.toLowerCase())) {
|
|
16994
|
-
return `dateTrunc('${dateBucket}', ${dateField})`;
|
|
16995
|
-
}
|
|
16996
|
-
if (["databricks"].includes(databaseType.toLowerCase())) {
|
|
16997
|
-
return `DATE_TRUNC('${dateBucket}', ${dateField})`;
|
|
16998
|
-
}
|
|
16999
|
-
if (["mysql"].includes(databaseType.toLowerCase())) {
|
|
17000
|
-
switch (dateBucket.toLowerCase()) {
|
|
17001
|
-
case "year":
|
|
17002
|
-
return `DATE_FORMAT(${dateField}, '%Y-01-01 00:00:00')`;
|
|
17003
|
-
case "month":
|
|
17004
|
-
return `DATE_FORMAT(${dateField}, '%Y-%m-01 00:00:00')`;
|
|
17005
|
-
case "week":
|
|
17006
|
-
return `DATE_FORMAT(${dateField}, '%Y-%U-1 00:00:00')`;
|
|
17007
|
-
case "day":
|
|
17008
|
-
default:
|
|
17009
|
-
return `DATE(${dateField})`;
|
|
17010
|
-
}
|
|
17011
|
-
}
|
|
17012
|
-
if (["mssql"].includes(databaseType.toLowerCase())) {
|
|
17013
|
-
return `DATETRUNC(${dateBucket}, ${dateField})`;
|
|
17014
|
-
}
|
|
17015
|
-
return `TIMESTAMP_TRUNC(${dateField}, ${dateBucket})`;
|
|
17016
|
-
}
|
|
17017
|
-
function processValueField(aggType, databaseType, valueField) {
|
|
17018
|
-
if (aggType === "min" || aggType === "max" || aggType?.toLowerCase() === "average")
|
|
17019
|
-
return `${processColumnReference(valueField, databaseType)} ELSE null`;
|
|
17020
|
-
if (aggType === "count") return `1 ELSE 0`;
|
|
17021
|
-
return valueField ? `${processColumnReference(valueField, databaseType)} ELSE 0` : `1 ELSE 0`;
|
|
17022
|
-
}
|
|
17023
17423
|
function generateCountQuery(fields, query, databaseType) {
|
|
17024
17424
|
let countQuery = [];
|
|
17025
17425
|
let cteQuery = `WITH querytable AS (${query.replace(";", "")}) `;
|
|
@@ -17054,1206 +17454,95 @@ function generateDistinctQuery(stringFields, query, databaseType) {
|
|
|
17054
17454
|
case "mssql":
|
|
17055
17455
|
return generateDistinctQueryMSSQL(stringFields, query);
|
|
17056
17456
|
case "databricks":
|
|
17057
|
-
return generateDistinctQueryDatabricks(stringFields, query);
|
|
17058
|
-
case "clickhouse":
|
|
17059
|
-
// works with default for now
|
|
17060
|
-
default:
|
|
17061
|
-
return generateDistinctQueryDefault(stringFields, query, databaseType);
|
|
17062
|
-
}
|
|
17063
|
-
}
|
|
17064
|
-
function generateDistinctQueryDefault(stringFields, query, databaseType) {
|
|
17065
|
-
const distinctQueries = stringFields.map((field) => {
|
|
17066
|
-
return `SELECT '${field}' AS ${processColumnReference("field", databaseType)}, ARRAY_AGG(DISTINCT ${field}) AS ${processColumnReference("string_values", databaseType)} FROM querytable`;
|
|
17067
|
-
});
|
|
17068
|
-
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17069
|
-
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17070
|
-
}
|
|
17071
|
-
function generateDistinctQueryMySQL(stringFields, query) {
|
|
17072
|
-
const distinctQueries = stringFields.map((field) => {
|
|
17073
|
-
return `
|
|
17074
|
-
SELECT '${field}' AS ${processColumnReference("field", "mysql")},
|
|
17075
|
-
JSON_ARRAYAGG(\`${field}\`) AS ${processColumnReference("string_values", "mysql")}
|
|
17076
|
-
FROM (SELECT DISTINCT \`${field}\` FROM querytable) AS distinct_${replaceSpacesWithUnderscores(field)}`;
|
|
17077
|
-
});
|
|
17078
|
-
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17079
|
-
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17080
|
-
}
|
|
17081
|
-
function generateDistinctQueryBigQuery(stringFields, query) {
|
|
17082
|
-
const distinctQueries = stringFields.map((field) => {
|
|
17083
|
-
return `
|
|
17084
|
-
SELECT '${field}' AS ${processColumnReference("field", "bigquery")},
|
|
17085
|
-
ARRAY_AGG(\`${field}\`) AS ${processColumnReference("string_values", "bigquery")}
|
|
17086
|
-
FROM (SELECT \`${field}\` FROM querytable WHERE \`${field}\` IS NOT NULL GROUP BY \`${field}\`) AS distinct_${replaceSpacesWithUnderscores(field)}`;
|
|
17087
|
-
});
|
|
17088
|
-
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17089
|
-
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17090
|
-
}
|
|
17091
|
-
function generateDistinctQueryPostgres(stringFields, query) {
|
|
17092
|
-
const distinctQueries = stringFields.map((field) => {
|
|
17093
|
-
return `SELECT '${field}' AS ${processColumnReference("field", "postgresql")}, to_json(ARRAY_AGG(DISTINCT "${field}")) AS ${processColumnReference("string_values", "postgresql")} FROM querytable`;
|
|
17094
|
-
});
|
|
17095
|
-
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17096
|
-
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17097
|
-
}
|
|
17098
|
-
function generateDistinctQuerySnowflake(stringFields, query) {
|
|
17099
|
-
const distinctQueries = stringFields.map((field) => {
|
|
17100
|
-
return `SELECT '${field}' AS "field", ARRAY_AGG(DISTINCT "${field}") AS "string_values" FROM querytable`;
|
|
17101
|
-
});
|
|
17102
|
-
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17103
|
-
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17104
|
-
}
|
|
17105
|
-
function generateDistinctQueryMSSQL(stringFields, query) {
|
|
17106
|
-
const escapeFieldName = (field) => field.replace(/'/g, "''");
|
|
17107
|
-
const distinctQueries = stringFields.map((field) => {
|
|
17108
|
-
return `
|
|
17109
|
-
SELECT
|
|
17110
|
-
'${escapeFieldName(field)}' AS field,
|
|
17111
|
-
STRING_AGG(${field}, ',') AS string_values
|
|
17112
|
-
FROM (
|
|
17113
|
-
SELECT ${field}
|
|
17114
|
-
FROM querytable
|
|
17115
|
-
WHERE ${field} IS NOT NULL
|
|
17116
|
-
GROUP BY ${field}
|
|
17117
|
-
) AS grouped
|
|
17118
|
-
`.replace(/\s+/g, " ").trim();
|
|
17119
|
-
});
|
|
17120
|
-
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17121
|
-
return `
|
|
17122
|
-
WITH querytable AS (
|
|
17123
|
-
${query.replace(";", "")}
|
|
17124
|
-
)
|
|
17125
|
-
${distinctQuery}`.replace(/\s+/g, " ").trim();
|
|
17126
|
-
}
|
|
17127
|
-
function generateDistinctQueryDatabricks(stringFields, query) {
|
|
17128
|
-
const distinctQueries = stringFields.map((field) => {
|
|
17129
|
-
return `SELECT '${field}' AS ${processColumnReference("field", "databricks")}, collect_set(\`${field}\`) AS ${processColumnReference("string_values", "databricks")} FROM querytable`;
|
|
17130
|
-
});
|
|
17131
|
-
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17132
|
-
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17133
|
-
}
|
|
17134
|
-
function generateMinMaxDateRangeQueries(columnFields, query, databaseType) {
|
|
17135
|
-
const max2 = "MAX";
|
|
17136
|
-
const min2 = "MIN";
|
|
17137
|
-
const cast = databaseType.toLowerCase() === "snowflake" ? "::TIMESTAMP_TZ" : "";
|
|
17138
|
-
const distinctQueries = columnFields.map((field) => {
|
|
17139
|
-
const wrappedField = ["postgresql", "clickhouse"].includes(
|
|
17140
|
-
databaseType.toLowerCase()
|
|
17141
|
-
) ? `"${field}"` : field;
|
|
17142
|
-
return `SELECT '${field}' AS field, ${min2}(${wrappedField})${cast} AS min_range, ${max2}(${wrappedField})${cast} AS max_range FROM querytable`;
|
|
17143
|
-
});
|
|
17144
|
-
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17145
|
-
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17146
|
-
}
|
|
17147
|
-
function generatePivotQuery(pivot, itemQuery, databaseType, distinctStrings, dateBucket) {
|
|
17148
|
-
if (!isValidPivot(pivot).valid) {
|
|
17149
|
-
return void 0;
|
|
17150
|
-
}
|
|
17151
|
-
if (pivot.columnField && distinctStrings && distinctStrings.length > 0) {
|
|
17152
|
-
return create2DPivotQuery(
|
|
17153
|
-
pivot,
|
|
17154
|
-
itemQuery,
|
|
17155
|
-
databaseType,
|
|
17156
|
-
distinctStrings,
|
|
17157
|
-
dateBucket
|
|
17158
|
-
);
|
|
17159
|
-
}
|
|
17160
|
-
if (pivot.rowField) {
|
|
17161
|
-
return create1DPivotQuery(pivot, itemQuery, dateBucket, databaseType);
|
|
17162
|
-
}
|
|
17163
|
-
return createAggregationValuePivot(pivot, itemQuery, databaseType);
|
|
17164
|
-
}
|
|
17165
|
-
function create2DPivotQuery(pivot, itemQuery, databaseType, columnFieldValues, dateBucket) {
|
|
17166
|
-
if (!pivot || !pivot.columnField) {
|
|
17167
|
-
return void 0;
|
|
17168
|
-
}
|
|
17169
|
-
if (isStringType(pivot.rowFieldType ?? "") || !pivot.rowFieldType) {
|
|
17170
|
-
return create2DStringPivotQuery(
|
|
17171
|
-
pivot,
|
|
17172
|
-
itemQuery,
|
|
17173
|
-
columnFieldValues,
|
|
17174
|
-
databaseType
|
|
17175
|
-
);
|
|
17176
|
-
}
|
|
17177
|
-
return create2DDatePivotQuery(
|
|
17178
|
-
pivot,
|
|
17179
|
-
itemQuery,
|
|
17180
|
-
columnFieldValues,
|
|
17181
|
-
databaseType,
|
|
17182
|
-
dateBucket
|
|
17183
|
-
);
|
|
17184
|
-
}
|
|
17185
|
-
function create2DStringPivotQuery(pivot, itemQuery, columnFieldValues, databaseType) {
|
|
17186
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17187
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17188
|
-
);
|
|
17189
|
-
if (!isValidBaseQuery || !pivot.columnField || !pivot.rowField)
|
|
17190
|
-
return void 0;
|
|
17191
|
-
const rowField = pivot.rowField;
|
|
17192
|
-
if (!pivot.aggregations?.[0]?.valueField && pivot.aggregations?.[0]?.aggregationType !== "count" && !pivot.valueField && pivot.aggregationType !== "count")
|
|
17193
|
-
throw new Error("No value field provided for pivot");
|
|
17194
|
-
if (!pivot.aggregations?.[0]?.aggregationType && !pivot.aggregationType)
|
|
17195
|
-
throw new Error("No aggregation type provided for pivot");
|
|
17196
|
-
const columnField = pivot.columnField;
|
|
17197
|
-
const rowFieldAlias = processColumnReference(
|
|
17198
|
-
rowField,
|
|
17199
|
-
databaseType,
|
|
17200
|
-
void 0,
|
|
17201
|
-
false,
|
|
17202
|
-
true
|
|
17203
|
-
);
|
|
17204
|
-
const columnFieldAlias = processColumnReference(
|
|
17205
|
-
columnField,
|
|
17206
|
-
databaseType,
|
|
17207
|
-
void 0,
|
|
17208
|
-
false,
|
|
17209
|
-
true
|
|
17210
|
-
);
|
|
17211
|
-
let caseWhens = [];
|
|
17212
|
-
let valueAliases = [];
|
|
17213
|
-
const seenAggs = {};
|
|
17214
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17215
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17216
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17217
|
-
} else {
|
|
17218
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17219
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17220
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17221
|
-
};
|
|
17222
|
-
}
|
|
17223
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString();
|
|
17224
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17225
|
-
const valueFieldAlias = processColumnReference(
|
|
17226
|
-
currentAgg.valueField || rowField || "count",
|
|
17227
|
-
databaseType,
|
|
17228
|
-
void 0,
|
|
17229
|
-
false,
|
|
17230
|
-
true
|
|
17231
|
-
);
|
|
17232
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17233
|
-
let value2AliasSubstring = "";
|
|
17234
|
-
const disambiguationField = Object.values(seenAggs[currentAgg.aggregationType ?? ""] ?? {}).reduce(
|
|
17235
|
-
(acc, v) => acc + v
|
|
17236
|
-
) > 1 ? `_${currentAgg.valueField}${disambiguationIndex}` : "";
|
|
17237
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationField}_${disambiguationField ? matchCasing(currentAgg.aggregationType, currentAgg.valueField) : currentAgg.aggregationType}` : "";
|
|
17238
|
-
const valueExpr = currentAgg.valueFieldType === "bool" ? `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END` : processValueField(
|
|
17239
|
-
currentAgg.aggregationType,
|
|
17240
|
-
databaseType,
|
|
17241
|
-
valueFieldAlias
|
|
17242
|
-
);
|
|
17243
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17244
|
-
if (!currentAgg.valueField)
|
|
17245
|
-
throw new Error("No value field provided for pivot");
|
|
17246
|
-
const valueField2Alias = processColumnReference(
|
|
17247
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17248
|
-
databaseType,
|
|
17249
|
-
void 0,
|
|
17250
|
-
false,
|
|
17251
|
-
true
|
|
17252
|
-
);
|
|
17253
|
-
const value2Expr = (currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool" ? `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END` : valueField2Alias;
|
|
17254
|
-
if (currentAgg.valueField === currentAgg.valueField2 || !currentAgg.valueField2) {
|
|
17255
|
-
caseWhens = [
|
|
17256
|
-
...caseWhens,
|
|
17257
|
-
...columnFieldValues.map((column) => {
|
|
17258
|
-
return `CAST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17259
|
-
column,
|
|
17260
|
-
databaseType
|
|
17261
|
-
)}' THEN ${valueExpr} END) AS FLOAT) / GREATEST(sum(${value2Expr}), 1) AS ${processColumnReference(
|
|
17262
|
-
column + disambiguation,
|
|
17263
|
-
databaseType,
|
|
17264
|
-
"_",
|
|
17265
|
-
true
|
|
17266
|
-
)}`;
|
|
17267
|
-
})
|
|
17268
|
-
];
|
|
17269
|
-
} else {
|
|
17270
|
-
value2AliasSubstring = `${processColumnReference(
|
|
17271
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17272
|
-
databaseType,
|
|
17273
|
-
void 0,
|
|
17274
|
-
true
|
|
17275
|
-
)} AS ${valueField2Alias}`;
|
|
17276
|
-
caseWhens = [
|
|
17277
|
-
...caseWhens,
|
|
17278
|
-
...columnFieldValues.map((column) => {
|
|
17279
|
-
return `CAST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17280
|
-
column,
|
|
17281
|
-
databaseType
|
|
17282
|
-
)}' THEN ${valueExpr} END) AS FLOAT) / GREATEST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17283
|
-
column,
|
|
17284
|
-
databaseType
|
|
17285
|
-
)}' THEN ${value2Expr} END), 1) AS ${processColumnReference(
|
|
17286
|
-
column + disambiguation,
|
|
17287
|
-
databaseType,
|
|
17288
|
-
"_",
|
|
17289
|
-
true
|
|
17290
|
-
)}`;
|
|
17291
|
-
})
|
|
17292
|
-
];
|
|
17293
|
-
}
|
|
17294
|
-
} else {
|
|
17295
|
-
caseWhens = [
|
|
17296
|
-
...caseWhens,
|
|
17297
|
-
...columnFieldValues.map((column) => {
|
|
17298
|
-
return `${processAggType(currentAgg.aggregationType, true)}(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17299
|
-
column,
|
|
17300
|
-
databaseType
|
|
17301
|
-
)}' THEN ${valueExpr} END) AS ${processColumnReference(column + disambiguation, databaseType, "_", true)}`;
|
|
17302
|
-
})
|
|
17303
|
-
];
|
|
17304
|
-
}
|
|
17305
|
-
if (valueAliasSubstring) valueAliases.push(valueAliasSubstring);
|
|
17306
|
-
if (value2AliasSubstring) valueAliases.push(value2AliasSubstring);
|
|
17307
|
-
});
|
|
17308
|
-
valueAliases = [
|
|
17309
|
-
`${processColumnReference(rowField, databaseType, void 0, true)} AS ${rowFieldAlias}`,
|
|
17310
|
-
...valueAliases,
|
|
17311
|
-
`${processColumnReference(columnField, databaseType, void 0, true)} AS ${columnFieldAlias}`
|
|
17312
|
-
];
|
|
17313
|
-
valueAliases = Array.from(new Set(valueAliases));
|
|
17314
|
-
const sortQuery = pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : "";
|
|
17315
|
-
const pivotQuery = `
|
|
17316
|
-
,quill_alias AS (
|
|
17317
|
-
SELECT ${valueAliases.length > 0 ? `${valueAliases.join(", ")}` : ""}
|
|
17318
|
-
FROM quill_base_table
|
|
17319
|
-
),
|
|
17320
|
-
quill_qt_cw AS (
|
|
17321
|
-
SELECT ${rowFieldAlias}
|
|
17322
|
-
${caseWhens.length > 0 ? `, ${caseWhens.join(", ")}` : ""}
|
|
17323
|
-
FROM quill_alias
|
|
17324
|
-
GROUP BY ${rowFieldAlias}
|
|
17325
|
-
),
|
|
17326
|
-
quill_base_pivot AS (
|
|
17327
|
-
SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} *
|
|
17328
|
-
FROM quill_qt_cw qt
|
|
17329
|
-
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""}
|
|
17330
|
-
)
|
|
17331
|
-
SELECT * FROM quill_base_pivot
|
|
17332
|
-
`.replace(/\s+/g, " ").trim();
|
|
17333
|
-
return itemQuery.replace(
|
|
17334
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17335
|
-
pivotQuery
|
|
17336
|
-
);
|
|
17337
|
-
}
|
|
17338
|
-
function create2DDatePivotQuery(pivot, itemQuery, columnFieldValues, databaseType, dateBucket = "month") {
|
|
17339
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17340
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17341
|
-
);
|
|
17342
|
-
if (!isValidBaseQuery || !pivot.columnField || !pivot.rowField) {
|
|
17343
|
-
return void 0;
|
|
17344
|
-
}
|
|
17345
|
-
if (!pivot.aggregations?.[0]?.valueField && pivot.aggregations?.[0]?.aggregationType !== "count" && !pivot.valueField && pivot.aggregationType !== "count")
|
|
17346
|
-
throw new Error("No value field provided for pivot");
|
|
17347
|
-
if (!pivot.aggregations?.[0]?.aggregationType && !pivot.aggregationType)
|
|
17348
|
-
throw new Error("No aggregation type provided for pivot");
|
|
17349
|
-
const rowField = pivot.rowField;
|
|
17350
|
-
const columnField = pivot.columnField;
|
|
17351
|
-
const rowFieldAlias = processColumnReference(
|
|
17352
|
-
rowField,
|
|
17353
|
-
databaseType,
|
|
17354
|
-
void 0,
|
|
17355
|
-
false,
|
|
17356
|
-
true
|
|
17357
|
-
);
|
|
17358
|
-
const columnFieldAlias = processColumnReference(
|
|
17359
|
-
columnField,
|
|
17360
|
-
databaseType,
|
|
17361
|
-
void 0,
|
|
17362
|
-
false,
|
|
17363
|
-
true
|
|
17364
|
-
);
|
|
17365
|
-
let caseWhens = [];
|
|
17366
|
-
let valueFieldAliases = [];
|
|
17367
|
-
const seenAggs = {};
|
|
17368
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17369
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17370
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17371
|
-
} else {
|
|
17372
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17373
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17374
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17375
|
-
};
|
|
17376
|
-
}
|
|
17377
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString();
|
|
17378
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17379
|
-
const valueFieldAlias = processColumnReference(
|
|
17380
|
-
currentAgg.valueField ?? rowField,
|
|
17381
|
-
databaseType,
|
|
17382
|
-
void 0,
|
|
17383
|
-
false,
|
|
17384
|
-
true
|
|
17385
|
-
);
|
|
17386
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17387
|
-
let value2AliasSubstring = "";
|
|
17388
|
-
const disambiguationField = Object.values(seenAggs[currentAgg.aggregationType ?? ""] ?? {}).reduce(
|
|
17389
|
-
(acc, v) => acc + v
|
|
17390
|
-
) > 1 ? `_${currentAgg.valueField}${disambiguationIndex}` : "";
|
|
17391
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationField}_${disambiguationField ? matchCasing(currentAgg.aggregationType, currentAgg.valueField) : currentAgg.aggregationType}` : "";
|
|
17392
|
-
const valueExpr = currentAgg.valueFieldType === "bool" ? `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END` : processValueField(
|
|
17393
|
-
currentAgg.aggregationType,
|
|
17394
|
-
databaseType,
|
|
17395
|
-
valueFieldAlias
|
|
17396
|
-
);
|
|
17397
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17398
|
-
if (!currentAgg.valueField)
|
|
17399
|
-
throw new Error("No value field provided for pivot");
|
|
17400
|
-
const valueField2Alias = processColumnReference(
|
|
17401
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17402
|
-
databaseType,
|
|
17403
|
-
void 0,
|
|
17404
|
-
false,
|
|
17405
|
-
true
|
|
17406
|
-
);
|
|
17407
|
-
const value2Expr = (currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool" ? `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END` : valueField2Alias;
|
|
17408
|
-
if (currentAgg.valueField === currentAgg.valueField2 || !currentAgg.valueField2) {
|
|
17409
|
-
caseWhens = [
|
|
17410
|
-
...caseWhens,
|
|
17411
|
-
...columnFieldValues.map((column) => {
|
|
17412
|
-
return `CAST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17413
|
-
column,
|
|
17414
|
-
databaseType
|
|
17415
|
-
)}' THEN ${valueExpr} END) AS FLOAT) / GREATEST(sum(${value2Expr}), 1) AS ${processColumnReference(
|
|
17416
|
-
column + disambiguation,
|
|
17417
|
-
databaseType,
|
|
17418
|
-
"_",
|
|
17419
|
-
true
|
|
17420
|
-
)}`;
|
|
17421
|
-
})
|
|
17422
|
-
];
|
|
17423
|
-
} else {
|
|
17424
|
-
value2AliasSubstring = `${processColumnReference(
|
|
17425
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17426
|
-
databaseType,
|
|
17427
|
-
void 0,
|
|
17428
|
-
true
|
|
17429
|
-
)} AS ${valueField2Alias}`;
|
|
17430
|
-
caseWhens = [
|
|
17431
|
-
...caseWhens,
|
|
17432
|
-
...columnFieldValues.map((column) => {
|
|
17433
|
-
return `CAST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17434
|
-
column,
|
|
17435
|
-
databaseType
|
|
17436
|
-
)}' THEN ${valueExpr} END) AS FLOAT) / GREATEST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17437
|
-
column,
|
|
17438
|
-
databaseType
|
|
17439
|
-
)}' THEN ${value2Expr} END), 1) AS ${processColumnReference(
|
|
17440
|
-
column + disambiguation,
|
|
17441
|
-
databaseType,
|
|
17442
|
-
"_",
|
|
17443
|
-
true
|
|
17444
|
-
)}`;
|
|
17445
|
-
})
|
|
17446
|
-
];
|
|
17447
|
-
}
|
|
17448
|
-
} else {
|
|
17449
|
-
caseWhens = [
|
|
17450
|
-
...caseWhens,
|
|
17451
|
-
...columnFieldValues.map((column) => {
|
|
17452
|
-
return `${processAggType(currentAgg.aggregationType, true)}(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17453
|
-
column,
|
|
17454
|
-
databaseType
|
|
17455
|
-
)}' THEN ${valueExpr} END) AS ${processColumnReference(column + disambiguation, databaseType, "_", true)}`;
|
|
17456
|
-
})
|
|
17457
|
-
];
|
|
17458
|
-
}
|
|
17459
|
-
if (valueAliasSubstring) valueFieldAliases.push(valueAliasSubstring);
|
|
17460
|
-
if (value2AliasSubstring) valueFieldAliases.push(value2AliasSubstring);
|
|
17461
|
-
});
|
|
17462
|
-
valueFieldAliases = [
|
|
17463
|
-
`${processColumnReference(rowField, databaseType, void 0, true)} AS ${rowFieldAlias}`,
|
|
17464
|
-
...valueFieldAliases,
|
|
17465
|
-
`${processColumnReference(columnField, databaseType, void 0, true)} AS ${columnFieldAlias}`
|
|
17466
|
-
];
|
|
17467
|
-
valueFieldAliases = Array.from(new Set(valueFieldAliases));
|
|
17468
|
-
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : ""}`;
|
|
17469
|
-
const pivotQuery = `
|
|
17470
|
-
, quill_alias AS (SELECT ${valueFieldAliases.length > 0 ? `${valueFieldAliases.join(", ")}` : ""} FROM quill_base_table),
|
|
17471
|
-
quill_qt_agg AS (SELECT ${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${rowFieldAlias}${caseWhens.length > 0 ? `, ${caseWhens.join(", ")}` : ""} FROM quill_alias GROUP BY ${databaseType.toLowerCase() === "clickhouse" ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)}),
|
|
17472
|
-
quill_base_pivot AS (SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} * FROM quill_qt_agg qt
|
|
17473
|
-
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""})
|
|
17474
|
-
SELECT * FROM quill_base_pivot
|
|
17475
|
-
`.replace(/\s+/g, " ").trim();
|
|
17476
|
-
return itemQuery.replace(
|
|
17477
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17478
|
-
pivotQuery
|
|
17479
|
-
);
|
|
17480
|
-
}
|
|
17481
|
-
function create1DPivotQuery(pivot, itemQuery, dateBucket = "month", databaseType) {
|
|
17482
|
-
if (isStringType(pivot.rowFieldType || "") || !pivot.rowFieldType) {
|
|
17483
|
-
return create1DStringPivotQuery(pivot, itemQuery, databaseType);
|
|
17484
|
-
}
|
|
17485
|
-
return create1DDatePivotQuery(pivot, itemQuery, dateBucket, databaseType);
|
|
17486
|
-
}
|
|
17487
|
-
function create1DStringPivotQuery(pivot, itemQuery, databaseType) {
|
|
17488
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17489
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17490
|
-
);
|
|
17491
|
-
if (!isValidBaseQuery) return void 0;
|
|
17492
|
-
const rowField = pivot.rowField;
|
|
17493
|
-
const rowAlias = processColumnReference(
|
|
17494
|
-
rowField,
|
|
17495
|
-
databaseType,
|
|
17496
|
-
void 0,
|
|
17497
|
-
true
|
|
17498
|
-
);
|
|
17499
|
-
let quillAggSelects = [rowAlias];
|
|
17500
|
-
let valueFieldAliases = [];
|
|
17501
|
-
const seenAggs = {};
|
|
17502
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17503
|
-
if (!currentAgg.valueField) currentAgg.valueField = void 0;
|
|
17504
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17505
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17506
|
-
} else {
|
|
17507
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17508
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17509
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17510
|
-
};
|
|
17511
|
-
}
|
|
17512
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString() ?? "";
|
|
17513
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17514
|
-
const valueFieldAlias = processColumnReference(
|
|
17515
|
-
currentAgg.valueField || rowField || "count",
|
|
17516
|
-
databaseType,
|
|
17517
|
-
void 0,
|
|
17518
|
-
false,
|
|
17519
|
-
true
|
|
17520
|
-
);
|
|
17521
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17522
|
-
let value2AliasSubstring = "";
|
|
17523
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationIndex}` + (currentAgg.aggregationType !== "count" ? `_${currentAgg.aggregationType}` : "") : "";
|
|
17524
|
-
let valueExpr = !currentAgg.valueField ? "*" : valueFieldAlias;
|
|
17525
|
-
if (currentAgg.valueFieldType === "bool") {
|
|
17526
|
-
valueExpr = `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END`;
|
|
17527
|
-
}
|
|
17528
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17529
|
-
let countPercentage = false;
|
|
17530
|
-
if (!currentAgg.valueField) {
|
|
17531
|
-
countPercentage = true;
|
|
17532
|
-
}
|
|
17533
|
-
const valueField2Alias = processColumnReference(
|
|
17534
|
-
currentAgg.valueField2 ?? currentAgg.valueField ?? "count",
|
|
17535
|
-
databaseType,
|
|
17536
|
-
void 0,
|
|
17537
|
-
false,
|
|
17538
|
-
true
|
|
17539
|
-
);
|
|
17540
|
-
let value2Expr = valueField2Alias;
|
|
17541
|
-
if ((currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool") {
|
|
17542
|
-
value2Expr = `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END`;
|
|
17543
|
-
}
|
|
17544
|
-
value2AliasSubstring = currentAgg.valueField2 && currentAgg.valueField !== currentAgg.valueField2 ? `${processColumnReference(currentAgg.valueField2, databaseType, void 0, true)} AS ${valueField2Alias}` : "";
|
|
17545
|
-
const percentageExpr = countPercentage ? "CAST(COUNT(*) AS FLOAT) / (SELECT COUNT(*) FROM quill_base_table)" : currentAgg.valueField === currentAgg.valueField2 || !currentAgg.valueField2 ? `CAST(sum(${valueExpr}) AS FLOAT) / ${(currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool" ? "COUNT(*)" : "SUM(sum(" + valueExpr + ")) OVER ()"}` : `CAST(sum(${valueExpr}) AS FLOAT) / GREATEST(sum(${value2Expr}), 1)`;
|
|
17546
|
-
quillAggSelects = [
|
|
17547
|
-
...quillAggSelects,
|
|
17548
|
-
`${percentageExpr} as ${processColumnReference(
|
|
17549
|
-
`${currentAgg.valueField ?? (disambiguation ? "count" : "percentage")}${disambiguation}`,
|
|
17550
|
-
databaseType,
|
|
17551
|
-
void 0,
|
|
17552
|
-
false,
|
|
17553
|
-
true
|
|
17554
|
-
)}`
|
|
17555
|
-
];
|
|
17556
|
-
} else {
|
|
17557
|
-
quillAggSelects = [
|
|
17558
|
-
...quillAggSelects,
|
|
17559
|
-
`${processAggType(currentAgg.aggregationType)}(${valueExpr}) AS ${processColumnReference(
|
|
17560
|
-
(currentAgg.valueField || "count") + disambiguation,
|
|
17561
|
-
databaseType
|
|
17562
|
-
)}`
|
|
17563
|
-
];
|
|
17564
|
-
}
|
|
17565
|
-
if (valueAliasSubstring) valueFieldAliases.push(valueAliasSubstring);
|
|
17566
|
-
if (value2AliasSubstring) valueFieldAliases.push(value2AliasSubstring);
|
|
17567
|
-
});
|
|
17568
|
-
valueFieldAliases = Array.from(new Set(valueFieldAliases));
|
|
17569
|
-
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : ""}`;
|
|
17570
|
-
const pivotQuery = `, quill_alias AS (
|
|
17571
|
-
SELECT ${processColumnReference(`${rowField}`, databaseType, void 0, true)} AS ${rowAlias}${valueFieldAliases.length > 0 ? `, ${valueFieldAliases.join(", ")}` : ""}
|
|
17572
|
-
FROM quill_base_table
|
|
17573
|
-
),
|
|
17574
|
-
quill_qt_cw AS (
|
|
17575
|
-
SELECT ${quillAggSelects.join(", ")} FROM quill_alias GROUP BY ${rowAlias}
|
|
17576
|
-
),
|
|
17577
|
-
quill_base_pivot AS (
|
|
17578
|
-
SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} *
|
|
17579
|
-
FROM quill_qt_cw qt ${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""}
|
|
17580
|
-
)
|
|
17581
|
-
SELECT * FROM quill_base_pivot`.replace(/\s+/g, " ").trim();
|
|
17582
|
-
return itemQuery.replace(
|
|
17583
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17584
|
-
pivotQuery
|
|
17585
|
-
);
|
|
17586
|
-
}
|
|
17587
|
-
function create1DDatePivotQuery(pivot, itemQuery, dateBucket = "month", databaseType) {
|
|
17588
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17589
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17590
|
-
);
|
|
17591
|
-
if (!isValidBaseQuery) {
|
|
17592
|
-
return void 0;
|
|
17593
|
-
}
|
|
17594
|
-
const rowField = pivot.rowField || "";
|
|
17595
|
-
const rowFieldAlias = processColumnReference(
|
|
17596
|
-
rowField,
|
|
17597
|
-
databaseType,
|
|
17598
|
-
void 0
|
|
17599
|
-
);
|
|
17600
|
-
let quillAggSelects = [
|
|
17601
|
-
`${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${processColumnReference(rowField, databaseType)}`
|
|
17602
|
-
];
|
|
17603
|
-
let valueFieldAliases = [];
|
|
17604
|
-
const seenAggs = {};
|
|
17605
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17606
|
-
if (!currentAgg.valueField) currentAgg.valueField = void 0;
|
|
17607
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17608
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17609
|
-
} else {
|
|
17610
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17611
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17612
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17613
|
-
};
|
|
17614
|
-
}
|
|
17615
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString() ?? "";
|
|
17616
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17617
|
-
const valueFieldAlias = processColumnReference(
|
|
17618
|
-
currentAgg.valueField || rowField || "count",
|
|
17619
|
-
databaseType,
|
|
17620
|
-
void 0,
|
|
17621
|
-
false,
|
|
17622
|
-
true
|
|
17623
|
-
);
|
|
17624
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17625
|
-
let value2AliasSubstring = "";
|
|
17626
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationIndex}` + (currentAgg.aggregationType !== "count" ? `_${currentAgg.aggregationType}` : "") : "";
|
|
17627
|
-
let valueExpr = !currentAgg.valueField ? "*" : valueFieldAlias;
|
|
17628
|
-
if (currentAgg.valueFieldType === "bool") {
|
|
17629
|
-
valueExpr = `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END`;
|
|
17630
|
-
}
|
|
17631
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17632
|
-
let countPercentage = false;
|
|
17633
|
-
if (!currentAgg.valueField) {
|
|
17634
|
-
countPercentage = true;
|
|
17635
|
-
}
|
|
17636
|
-
const valueField2Alias = processColumnReference(
|
|
17637
|
-
currentAgg.valueField2 ?? currentAgg.valueField ?? "count",
|
|
17638
|
-
databaseType,
|
|
17639
|
-
void 0,
|
|
17640
|
-
false,
|
|
17641
|
-
true
|
|
17642
|
-
);
|
|
17643
|
-
value2AliasSubstring = currentAgg.valueField2 && currentAgg.valueField !== currentAgg.valueField2 ? `${processColumnReference(currentAgg.valueField2, databaseType, void 0, true)} AS ${valueField2Alias}` : "";
|
|
17644
|
-
let value2Expr = valueField2Alias;
|
|
17645
|
-
if ((currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool") {
|
|
17646
|
-
value2Expr = `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END`;
|
|
17647
|
-
}
|
|
17648
|
-
const percentageExpr = countPercentage ? "CAST(COUNT(*) AS FLOAT) / (SELECT COUNT(*) FROM quill_base_table)" : currentAgg.valueField === currentAgg.valueField2 || !currentAgg.valueField2 ? `CAST(sum(${valueExpr}) AS FLOAT) / ${(currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool" ? "COUNT(*)" : "SUM(sum(" + valueExpr + ")) OVER ()"}` : `CAST(sum(${valueExpr}) AS FLOAT) / GREATEST(sum(${value2Expr}), 1)`;
|
|
17649
|
-
quillAggSelects = [
|
|
17650
|
-
...quillAggSelects,
|
|
17651
|
-
`${percentageExpr} as ${processColumnReference(
|
|
17652
|
-
`${currentAgg.valueField ?? (disambiguation ? "count" : "percentage")}${disambiguation}`,
|
|
17653
|
-
databaseType,
|
|
17654
|
-
void 0,
|
|
17655
|
-
false,
|
|
17656
|
-
true
|
|
17657
|
-
)}`
|
|
17658
|
-
];
|
|
17659
|
-
} else {
|
|
17660
|
-
quillAggSelects = [
|
|
17661
|
-
...quillAggSelects,
|
|
17662
|
-
`${processAggType(currentAgg.aggregationType)}(${valueExpr}) AS ${processColumnReference((currentAgg.valueField || "count") + disambiguation, databaseType)}`
|
|
17663
|
-
];
|
|
17664
|
-
}
|
|
17665
|
-
if (valueAliasSubstring) valueFieldAliases.push(valueAliasSubstring);
|
|
17666
|
-
if (value2AliasSubstring) valueFieldAliases.push(value2AliasSubstring);
|
|
17667
|
-
});
|
|
17668
|
-
valueFieldAliases = Array.from(new Set(valueFieldAliases));
|
|
17669
|
-
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : ""}`;
|
|
17670
|
-
const pivotQuery = `, quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, void 0, true)} AS ${rowFieldAlias}${valueFieldAliases.length > 0 ? `, ${valueFieldAliases.join(", ")}` : ""}
|
|
17671
|
-
FROM quill_base_table),
|
|
17672
|
-
quill_qt_agg AS (SELECT ${quillAggSelects.join(", ")}
|
|
17673
|
-
FROM quill_alias GROUP BY ${databaseType.toLowerCase() === "clickhouse" ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)}),
|
|
17674
|
-
quill_base_pivot AS (SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} * FROM quill_qt_agg qt
|
|
17675
|
-
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""})
|
|
17676
|
-
SELECT * FROM quill_base_pivot
|
|
17677
|
-
`.replace(/\s+/g, " ").trim();
|
|
17678
|
-
return itemQuery.replace(
|
|
17679
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17680
|
-
pivotQuery
|
|
17681
|
-
);
|
|
17682
|
-
}
|
|
17683
|
-
function createAggregationValuePivot(pivot, itemQuery, databaseType) {
|
|
17684
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17685
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17686
|
-
);
|
|
17687
|
-
if (!isValidBaseQuery) return void 0;
|
|
17688
|
-
let quillAggSelects = [];
|
|
17689
|
-
let valueFieldAliases = [];
|
|
17690
|
-
const seenAggs = {};
|
|
17691
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17692
|
-
if (!currentAgg.valueField) currentAgg.valueField = void 0;
|
|
17693
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17694
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17695
|
-
} else {
|
|
17696
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17697
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17698
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17699
|
-
};
|
|
17700
|
-
}
|
|
17701
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString() ?? "";
|
|
17702
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17703
|
-
const valueFieldAlias = processColumnReference(
|
|
17704
|
-
currentAgg.valueField || "count",
|
|
17705
|
-
databaseType,
|
|
17706
|
-
void 0,
|
|
17707
|
-
false,
|
|
17708
|
-
true
|
|
17709
|
-
);
|
|
17710
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17711
|
-
let value2AliasSubstring = "";
|
|
17712
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationIndex}_${currentAgg.aggregationType}` : "";
|
|
17713
|
-
let valueExpr = !currentAgg.valueField ? "*" : valueFieldAlias;
|
|
17714
|
-
valueExpr = currentAgg.valueFieldType === "bool" ? `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END` : valueExpr;
|
|
17715
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17716
|
-
if (!currentAgg.valueField) {
|
|
17717
|
-
throw new Error("No value field provided for percentage aggregation");
|
|
17718
|
-
}
|
|
17719
|
-
const valueField2Alias = processColumnReference(
|
|
17720
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17721
|
-
databaseType,
|
|
17722
|
-
void 0,
|
|
17723
|
-
false,
|
|
17724
|
-
true
|
|
17725
|
-
);
|
|
17726
|
-
const value2Expr = (currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool" ? `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END` : valueField2Alias;
|
|
17727
|
-
value2AliasSubstring = currentAgg.valueField2 && currentAgg.valueField !== currentAgg.valueField2 ? `${processColumnReference(currentAgg.valueField2, databaseType, void 0, true)} AS ${valueField2Alias}` : "";
|
|
17728
|
-
const percentageExpr = currentAgg.valueField === currentAgg.valueField2 || !currentAgg.valueField2 ? `CAST(sum(${valueExpr}) AS FLOAT) / ${(currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool" ? "COUNT(*)" : "SUM(sum(" + valueExpr + ")) OVER ()"}` : `CAST(sum(${valueExpr}) AS FLOAT) / GREATEST(sum(${value2Expr}), 1)`;
|
|
17729
|
-
quillAggSelects = [
|
|
17730
|
-
...quillAggSelects,
|
|
17731
|
-
`${percentageExpr} as ${processColumnReference(
|
|
17732
|
-
`${currentAgg.valueField ?? ""}${disambiguation}`,
|
|
17733
|
-
databaseType,
|
|
17734
|
-
void 0,
|
|
17735
|
-
false,
|
|
17736
|
-
true
|
|
17737
|
-
)}`
|
|
17738
|
-
];
|
|
17739
|
-
} else {
|
|
17740
|
-
quillAggSelects = [
|
|
17741
|
-
...quillAggSelects,
|
|
17742
|
-
`${processAggType(currentAgg.aggregationType)}(${valueExpr}) AS ${processColumnReference(
|
|
17743
|
-
(currentAgg.valueField || "count") + disambiguation,
|
|
17744
|
-
databaseType
|
|
17745
|
-
)}`
|
|
17746
|
-
];
|
|
17747
|
-
}
|
|
17748
|
-
if (valueAliasSubstring) valueFieldAliases.push(valueAliasSubstring);
|
|
17749
|
-
if (value2AliasSubstring) valueFieldAliases.push(value2AliasSubstring);
|
|
17750
|
-
});
|
|
17751
|
-
valueFieldAliases = Array.from(new Set(valueFieldAliases));
|
|
17752
|
-
if (valueFieldAliases.length === 0) {
|
|
17753
|
-
valueFieldAliases = ["*"];
|
|
17754
|
-
}
|
|
17755
|
-
const sortQuery = pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : "";
|
|
17756
|
-
const pivotQuery = `, quill_alias AS (
|
|
17757
|
-
SELECT ${valueFieldAliases.join(", ")} FROM quill_base_table
|
|
17758
|
-
),
|
|
17759
|
-
quill_qt_agg AS (
|
|
17760
|
-
SELECT ${quillAggSelects.join(", ")} FROM quill_alias
|
|
17761
|
-
),
|
|
17762
|
-
quill_base_pivot AS (
|
|
17763
|
-
SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} * FROM quill_qt_agg qt
|
|
17764
|
-
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""}
|
|
17765
|
-
)
|
|
17766
|
-
SELECT * FROM quill_base_pivot`.replace(/\s+/g, " ").trim();
|
|
17767
|
-
return itemQuery.replace(
|
|
17768
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17769
|
-
pivotQuery
|
|
17770
|
-
);
|
|
17771
|
-
}
|
|
17772
|
-
function additionalProcessingOnPivotQuery(pivot, query, additionalProcessing, databaseType = "postgresql") {
|
|
17773
|
-
if (!additionalProcessing || !query) return query;
|
|
17774
|
-
const isValidBaseQuery = query.match(
|
|
17775
|
-
/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/
|
|
17776
|
-
);
|
|
17777
|
-
if (!isValidBaseQuery) {
|
|
17778
|
-
return void 0;
|
|
17779
|
-
}
|
|
17780
|
-
if (!pivot.aggregations || pivot.aggregations.length === 0) {
|
|
17781
|
-
if (pivot.aggregationType) {
|
|
17782
|
-
pivot.aggregations = [
|
|
17783
|
-
{
|
|
17784
|
-
aggregationType: pivot.aggregationType,
|
|
17785
|
-
valueField: pivot.valueField,
|
|
17786
|
-
valueField2: pivot.valueField2
|
|
17787
|
-
}
|
|
17788
|
-
];
|
|
17789
|
-
} else {
|
|
17790
|
-
throw new Error("No aggregations provided for pivot");
|
|
17791
|
-
}
|
|
17792
|
-
}
|
|
17793
|
-
let rowsPerPage = 0;
|
|
17794
|
-
let currentInterval = 0;
|
|
17795
|
-
let offset = 0;
|
|
17796
|
-
let limit = 1e3;
|
|
17797
|
-
let sortQuery = "";
|
|
17798
|
-
if (additionalProcessing.page) {
|
|
17799
|
-
const page = additionalProcessing.page.page || 0;
|
|
17800
|
-
if (additionalProcessing.page.rowsPerRequest) {
|
|
17801
|
-
limit = additionalProcessing.page.rowsPerRequest;
|
|
17802
|
-
}
|
|
17803
|
-
rowsPerPage = additionalProcessing.page.rowsPerPage || 0;
|
|
17804
|
-
currentInterval = page ? Math.floor(page / (limit / rowsPerPage)) : 0;
|
|
17805
|
-
offset = currentInterval * limit;
|
|
17806
|
-
}
|
|
17807
|
-
const disambiguation = pivot.aggregations.length > 1 ? `_${matchCasing(pivot.aggregations?.[0]?.aggregationType, pivot.aggregations?.[0]?.valueField)}` : "";
|
|
17808
|
-
if (additionalProcessing.sort) {
|
|
17809
|
-
sortQuery = `ORDER BY ${processColumnReference(additionalProcessing.sort.field, databaseType, void 0, true)} ${additionalProcessing.sort.direction || ""}`;
|
|
17810
|
-
} else {
|
|
17811
|
-
const valueFieldAlias = processColumnReference(
|
|
17812
|
-
(pivot.aggregations?.[0]?.valueField ?? "") + disambiguation,
|
|
17813
|
-
databaseType,
|
|
17814
|
-
void 0,
|
|
17815
|
-
false,
|
|
17816
|
-
true
|
|
17817
|
-
);
|
|
17818
|
-
const defaultSortField = pivot.sortField || pivot.rowField || valueFieldAlias;
|
|
17819
|
-
const defaultSortDirection = pivot.sortDirection || "";
|
|
17820
|
-
if (defaultSortField !== `"_"`) {
|
|
17821
|
-
sortQuery = `ORDER BY ${processColumnReference(defaultSortField, databaseType, void 0, true)} ${defaultSortDirection}`;
|
|
17822
|
-
} else {
|
|
17823
|
-
sortQuery = "";
|
|
17824
|
-
}
|
|
17825
|
-
}
|
|
17826
|
-
const additionalProcessingQuery = `
|
|
17827
|
-
SELECT *
|
|
17828
|
-
FROM quill_base_pivot ${sortQuery}${databaseType.toLowerCase() === "mssql" ? ` OFFSET ${offset} ROWS FETCH NEXT ${limit} ROWS ONLY` : ` LIMIT ${limit} OFFSET ${offset}`}
|
|
17829
|
-
`.replace(/\s+/g, " ").trim();
|
|
17830
|
-
return query.replace(
|
|
17831
|
-
/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/,
|
|
17832
|
-
additionalProcessingQuery
|
|
17833
|
-
);
|
|
17834
|
-
}
|
|
17835
|
-
function generateRowCountQuery(query, databaseType) {
|
|
17836
|
-
if (!query) return query;
|
|
17837
|
-
const isValidBaseQuery = query.match(
|
|
17838
|
-
/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/
|
|
17839
|
-
);
|
|
17840
|
-
if (!isValidBaseQuery) {
|
|
17841
|
-
return void 0;
|
|
17842
|
-
}
|
|
17843
|
-
const rowCountQuery = `, subview_row_count_cte AS (SELECT * FROM quill_base_pivot)
|
|
17844
|
-
SELECT count(*) as ${processColumnReference("row_count", databaseType || "postgresql", void 0, true)} FROM subview_row_count_cte
|
|
17845
|
-
`.replace(/\s+/g, " ").trim();
|
|
17846
|
-
return query.replace(
|
|
17847
|
-
/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/,
|
|
17848
|
-
rowCountQuery
|
|
17849
|
-
);
|
|
17850
|
-
}
|
|
17851
|
-
|
|
17852
|
-
// src/utils/pivotConstructor.ts
|
|
17853
|
-
async function generatePivotWithSQL({
|
|
17854
|
-
pivot,
|
|
17855
|
-
report,
|
|
17856
|
-
client,
|
|
17857
|
-
dateBucket,
|
|
17858
|
-
dateFilter,
|
|
17859
|
-
distinctStrings,
|
|
17860
|
-
dashboardName,
|
|
17861
|
-
tenants,
|
|
17862
|
-
additionalProcessing,
|
|
17863
|
-
pivotQuery,
|
|
17864
|
-
comparisonPivotQuery,
|
|
17865
|
-
getPivotRowCount = true,
|
|
17866
|
-
caller,
|
|
17867
|
-
getToken
|
|
17868
|
-
}) {
|
|
17869
|
-
let sqlQuery = pivotQuery;
|
|
17870
|
-
let comparisonPivotSql = comparisonPivotQuery;
|
|
17871
|
-
const databaseType = client.databaseType || "postgresql";
|
|
17872
|
-
if (!pivotQuery && pivot.columnField && !pivot.columnValues && !distinctStrings) {
|
|
17873
|
-
if (!report?.rows) {
|
|
17874
|
-
throw new Error("No distinct strings provided for column field");
|
|
17875
|
-
} else {
|
|
17876
|
-
distinctStrings = Array.from(
|
|
17877
|
-
new Set(
|
|
17878
|
-
report.rows.map((row) => row[pivot.columnField]).filter((value) => value !== null && value !== void 0)
|
|
17879
|
-
)
|
|
17880
|
-
);
|
|
17881
|
-
}
|
|
17882
|
-
}
|
|
17883
|
-
if (!pivot.aggregations?.length && pivot.aggregationType) {
|
|
17884
|
-
pivot.aggregations = [
|
|
17885
|
-
{
|
|
17886
|
-
aggregationType: pivot.aggregationType,
|
|
17887
|
-
valueField: pivot.valueField,
|
|
17888
|
-
valueFieldType: pivot.valueFieldType,
|
|
17889
|
-
valueField2: pivot.valueField2,
|
|
17890
|
-
valueField2Type: pivot.valueField2Type
|
|
17891
|
-
}
|
|
17892
|
-
];
|
|
17893
|
-
}
|
|
17894
|
-
let comparisonInterval = void 0;
|
|
17895
|
-
if (dateFilter && dateFilter.comparisonRange) {
|
|
17896
|
-
comparisonInterval = getComparisonInterval(
|
|
17897
|
-
{
|
|
17898
|
-
startDate: dateFilter.comparisonRange.startDate,
|
|
17899
|
-
endDate: dateFilter.comparisonRange.endDate
|
|
17900
|
-
},
|
|
17901
|
-
dateBucket
|
|
17902
|
-
);
|
|
17903
|
-
}
|
|
17904
|
-
if (pivot.rowField && !pivot.rowFieldType) {
|
|
17905
|
-
const rowColumn = report?.columns.find(
|
|
17906
|
-
(column) => column.field === pivot.rowField
|
|
17907
|
-
);
|
|
17908
|
-
pivot.rowFieldType = rowColumn?.format || "string";
|
|
17909
|
-
}
|
|
17910
|
-
const filteredDistinctStrings = distinctStrings?.filter(
|
|
17911
|
-
(value) => value !== null && value !== void 0 && value !== ""
|
|
17912
|
-
);
|
|
17913
|
-
const pivotColumnFields = filteredDistinctStrings?.slice(
|
|
17914
|
-
0,
|
|
17915
|
-
MAX_PIVOT_UNIQUE_VALUES
|
|
17916
|
-
);
|
|
17917
|
-
if (!pivotQuery && report) {
|
|
17918
|
-
if (!report.itemQuery) {
|
|
17919
|
-
throw Error("No item query found in report");
|
|
17920
|
-
}
|
|
17921
|
-
const itemQuery = report.itemQuery[0];
|
|
17922
|
-
const comparisonQuery = report.itemQuery[1];
|
|
17923
|
-
if (!itemQuery) {
|
|
17924
|
-
throw Error("No item query found in report");
|
|
17925
|
-
}
|
|
17926
|
-
sqlQuery = generatePivotQuery(
|
|
17927
|
-
pivot,
|
|
17928
|
-
itemQuery,
|
|
17929
|
-
databaseType,
|
|
17930
|
-
pivotColumnFields,
|
|
17931
|
-
dateBucket
|
|
17932
|
-
);
|
|
17933
|
-
comparisonPivotSql = comparisonQuery ? generatePivotQuery(
|
|
17934
|
-
pivot,
|
|
17935
|
-
comparisonQuery,
|
|
17936
|
-
databaseType,
|
|
17937
|
-
pivotColumnFields,
|
|
17938
|
-
dateBucket
|
|
17939
|
-
) : "";
|
|
17940
|
-
}
|
|
17941
|
-
if (!sqlQuery) {
|
|
17942
|
-
throw "Error generating pivot query";
|
|
17943
|
-
}
|
|
17944
|
-
const paginatedSqlQuery = additionalProcessingOnPivotQuery(
|
|
17945
|
-
pivot,
|
|
17946
|
-
sqlQuery,
|
|
17947
|
-
additionalProcessing,
|
|
17948
|
-
client.databaseType
|
|
17949
|
-
);
|
|
17950
|
-
const paginatedComparisonQuery = comparisonPivotSql ? additionalProcessingOnPivotQuery(
|
|
17951
|
-
pivot,
|
|
17952
|
-
comparisonPivotSql,
|
|
17953
|
-
additionalProcessing,
|
|
17954
|
-
client.databaseType
|
|
17955
|
-
) : "";
|
|
17956
|
-
const preQueries = [paginatedSqlQuery];
|
|
17957
|
-
getPivotRowCount = getPivotRowCount && (report?.chartType === "table" || caller === "ReportBuilder");
|
|
17958
|
-
if (getPivotRowCount) {
|
|
17959
|
-
const pivotRowCountQuery = generateRowCountQuery(
|
|
17960
|
-
sqlQuery,
|
|
17961
|
-
client.databaseType
|
|
17962
|
-
);
|
|
17963
|
-
preQueries.push(pivotRowCountQuery);
|
|
17964
|
-
}
|
|
17965
|
-
if (paginatedComparisonQuery) {
|
|
17966
|
-
preQueries.push(paginatedComparisonQuery);
|
|
17967
|
-
}
|
|
17968
|
-
const { data: resp } = await quillFetch({
|
|
17969
|
-
client,
|
|
17970
|
-
task: "query",
|
|
17971
|
-
metadata: {
|
|
17972
|
-
preQueries,
|
|
17973
|
-
clientId: client.publicKey,
|
|
17974
|
-
databaseType,
|
|
17975
|
-
runQueryConfig: {
|
|
17976
|
-
overridePost: true,
|
|
17977
|
-
convertDatatypes: true
|
|
17978
|
-
},
|
|
17979
|
-
useNewNodeSql: true,
|
|
17980
|
-
dashboardName,
|
|
17981
|
-
tenants
|
|
17982
|
-
},
|
|
17983
|
-
urlParameters: `caller=generatePivot&task=query`,
|
|
17984
|
-
credentials: "same-origin",
|
|
17985
|
-
getToken
|
|
17986
|
-
});
|
|
17987
|
-
if (resp.success === false) {
|
|
17988
|
-
throw resp.errorMessage;
|
|
17989
|
-
}
|
|
17990
|
-
const queryResponseRows = resp?.queryResults?.[0]?.rows || [];
|
|
17991
|
-
const queryResponseFields = resp?.queryResults?.[0]?.fields || [];
|
|
17992
|
-
const queryComparisonResponseRows = (getPivotRowCount ? resp?.queryResults?.[2]?.rows : resp?.queryResults?.[1]?.rows) || [];
|
|
17993
|
-
const queryComparisonResponseFields = (getPivotRowCount ? resp?.queryResults?.[2]?.fields : resp?.queryResults?.[1]?.fields) || [];
|
|
17994
|
-
parseValueFromBigQueryDates(queryResponseRows, queryResponseFields);
|
|
17995
|
-
parseValueFromBigQueryDates(
|
|
17996
|
-
queryComparisonResponseRows,
|
|
17997
|
-
queryComparisonResponseFields
|
|
17998
|
-
);
|
|
17999
|
-
const responseRows = mergeComparisonPivotRows({
|
|
18000
|
-
pivot,
|
|
18001
|
-
rows: queryResponseRows,
|
|
18002
|
-
compRows: queryComparisonResponseRows,
|
|
18003
|
-
databaseType,
|
|
18004
|
-
dateBucket,
|
|
18005
|
-
comparisonInterval,
|
|
18006
|
-
columnFieldValues: pivotColumnFields
|
|
18007
|
-
});
|
|
18008
|
-
const responseFields = mergeComparisonPivotColumns({
|
|
18009
|
-
pivot,
|
|
18010
|
-
rows: queryResponseFields,
|
|
18011
|
-
compRows: queryComparisonResponseFields
|
|
18012
|
-
});
|
|
18013
|
-
const rows = pivot.rowField ? responseRows.map(
|
|
18014
|
-
(row) => !row[pivot.rowField] ? { ...row, [pivot.rowField]: "-" } : row
|
|
18015
|
-
) : responseRows;
|
|
18016
|
-
if (pivot.columnField && client.databaseType?.toLowerCase() === "bigquery") {
|
|
18017
|
-
rows.forEach((row) => {
|
|
18018
|
-
Object.keys(row).forEach((key) => {
|
|
18019
|
-
const processedKey = processColumnName(key);
|
|
18020
|
-
if (processedKey !== key) {
|
|
18021
|
-
row[processedKey] = row[key];
|
|
18022
|
-
delete row[key];
|
|
18023
|
-
}
|
|
18024
|
-
});
|
|
18025
|
-
});
|
|
18026
|
-
}
|
|
18027
|
-
const columns = responseFields?.map((field) => ({
|
|
18028
|
-
field: processColumnName(field.name),
|
|
18029
|
-
label: snakeCaseToTitleCase(
|
|
18030
|
-
processColumnName(field.name.replace("comparison_", "comparison "))
|
|
18031
|
-
),
|
|
18032
|
-
format: field.name === pivot.rowField ? "string" : (
|
|
18033
|
-
// This scary equation is calculating which aggregation a column is associated with.
|
|
18034
|
-
// Eg you have 7 columns and 2 aggregations, you can assume column 0 is the row field, 1-3 is aggregation 0, and 4-6 is aggregation 1.
|
|
18035
|
-
// pivot.aggregations?.[
|
|
18036
|
-
// Math.floor(
|
|
18037
|
-
// (index - 1) /
|
|
18038
|
-
// Math.floor(
|
|
18039
|
-
// (responseFields.length - 1) /
|
|
18040
|
-
// (pivot.aggregations?.length ?? 1),
|
|
18041
|
-
// ),
|
|
18042
|
-
// )
|
|
18043
|
-
// ]?.aggregationType === 'percentage'
|
|
18044
|
-
pivot.aggregations?.find(
|
|
18045
|
-
(agg) => agg.valueField === field.name || `${agg.valueField}_percentage` === field.name || !agg.valueField && agg.aggregationType === "percentage" && field.name.endsWith("percentage")
|
|
18046
|
-
)?.aggregationType === "percentage" ? "percent" : "whole_number"
|
|
18047
|
-
),
|
|
18048
|
-
fieldType: field.fieldType,
|
|
18049
|
-
jsType: field.jsType,
|
|
18050
|
-
dataTypeID: field.dataTypeID
|
|
18051
|
-
})).filter(
|
|
18052
|
-
(field, index) => field.field !== "comparison_" + pivot.rowField || index === 0
|
|
18053
|
-
).sort((a, b) => {
|
|
18054
|
-
if (a.field === pivot.rowField) {
|
|
18055
|
-
return -1;
|
|
18056
|
-
}
|
|
18057
|
-
if (b.field === pivot.rowField) {
|
|
18058
|
-
return 1;
|
|
18059
|
-
}
|
|
18060
|
-
return 0;
|
|
18061
|
-
});
|
|
18062
|
-
if (pivot.rowField && !isStringType(pivot.rowFieldType || "")) {
|
|
18063
|
-
rows.forEach((row) => {
|
|
18064
|
-
row.__quillRawDate = typeof row[pivot.rowField || ""] === "object" ? row[pivot.rowField || ""].value : row[pivot.rowField || ""];
|
|
18065
|
-
let value = typeof row[pivot.rowField || ""] === "object" ? row[pivot.rowField || ""].value : row[pivot.rowField || ""];
|
|
18066
|
-
if (dateBucket === "week" && dateFilter?.startDate && dateFilter?.endDate) {
|
|
18067
|
-
const rowDate = new Date(value);
|
|
18068
|
-
if (rowDate < dateFilter.startDate) {
|
|
18069
|
-
value = dateFilter.startDate.toISOString();
|
|
18070
|
-
} else if (rowDate > dateFilter.endDate) {
|
|
18071
|
-
value = dateFilter.endDate.toISOString();
|
|
18072
|
-
}
|
|
18073
|
-
}
|
|
18074
|
-
const dateString = getDateString(
|
|
18075
|
-
value,
|
|
18076
|
-
dateFilter?.startDate && dateFilter?.endDate ? { start: dateFilter.startDate, end: dateFilter.endDate } : void 0,
|
|
18077
|
-
dateBucket,
|
|
18078
|
-
databaseType
|
|
18079
|
-
);
|
|
18080
|
-
row[pivot.rowField || ""] = dateString;
|
|
18081
|
-
});
|
|
18082
|
-
if (pivot.rowField && pivot.rowFieldType && !isStringType(pivot.rowFieldType) && dateFilter?.startDate && dateFilter?.endDate) {
|
|
18083
|
-
const dateSet = new Set(
|
|
18084
|
-
rows.map((row) => row[pivot.rowField || ""])
|
|
18085
|
-
);
|
|
18086
|
-
for (let date = dateFilter.startDate; date <= dateFilter.endDate; date = new Date(date.getTime() + 24 * 60 * 60 * 1e3)) {
|
|
18087
|
-
const formattedDate = getDateString(
|
|
18088
|
-
date.toISOString(),
|
|
18089
|
-
{ start: dateFilter.startDate, end: dateFilter.endDate },
|
|
18090
|
-
dateBucket,
|
|
18091
|
-
databaseType
|
|
18092
|
-
);
|
|
18093
|
-
if (!dateSet.has(formattedDate)) {
|
|
18094
|
-
const newRow = {};
|
|
18095
|
-
newRow[pivot.rowField] = formattedDate;
|
|
18096
|
-
newRow.__quillRawDate = date.toISOString();
|
|
18097
|
-
rows.push(newRow);
|
|
18098
|
-
dateSet.add(formattedDate);
|
|
18099
|
-
}
|
|
18100
|
-
}
|
|
18101
|
-
}
|
|
18102
|
-
if (!pivot.sort) {
|
|
18103
|
-
rows.sort((a, b) => {
|
|
18104
|
-
if (a.__quillRawDate < b.__quillRawDate) {
|
|
18105
|
-
return -1;
|
|
18106
|
-
}
|
|
18107
|
-
if (a.__quillRawDate > b.__quillRawDate) {
|
|
18108
|
-
return 1;
|
|
18109
|
-
}
|
|
18110
|
-
return 0;
|
|
18111
|
-
});
|
|
18112
|
-
}
|
|
18113
|
-
}
|
|
18114
|
-
columns?.forEach((column, index) => {
|
|
18115
|
-
if (column.label && ["null", "undefined"].includes(column.label.toLowerCase()) && !pivot.columnField && !pivot.aggregations?.[index]?.valueField && pivot.aggregations?.[index]?.aggregationType === "count") {
|
|
18116
|
-
column.label = "Count";
|
|
18117
|
-
}
|
|
18118
|
-
});
|
|
18119
|
-
const numericColumns = columns?.filter(
|
|
18120
|
-
(column) => column.format === "whole_number" || column.format === "percentage"
|
|
18121
|
-
);
|
|
18122
|
-
rows.forEach((row) => {
|
|
18123
|
-
numericColumns?.forEach((column) => {
|
|
18124
|
-
row[column.field] = row[column.field] ?? 0;
|
|
18125
|
-
});
|
|
18126
|
-
});
|
|
18127
|
-
return {
|
|
18128
|
-
rows,
|
|
18129
|
-
columns: columns ?? [],
|
|
18130
|
-
rowCount: getPivotRowCount ? Number(resp?.queryResults?.[1]?.rows?.[0]?.["row_count"]) ?? rows.length : 0,
|
|
18131
|
-
pivotQuery: sqlQuery,
|
|
18132
|
-
comparisonPivotQuery: comparisonPivotSql
|
|
18133
|
-
};
|
|
18134
|
-
}
|
|
18135
|
-
function generatePivotTableYAxis(pivot, cols, yAxisField) {
|
|
18136
|
-
if (pivot?.aggregationType === "count") {
|
|
18137
|
-
return [
|
|
18138
|
-
{
|
|
18139
|
-
field: pivot.valueField ?? "count",
|
|
18140
|
-
label: yAxisField.label,
|
|
18141
|
-
format: yAxisField.format
|
|
18142
|
-
}
|
|
18143
|
-
];
|
|
18144
|
-
}
|
|
18145
|
-
return [
|
|
18146
|
-
{
|
|
18147
|
-
field: pivot.valueField ?? "count",
|
|
18148
|
-
label: yAxisField.label,
|
|
18149
|
-
format: yAxisField.format
|
|
18150
|
-
}
|
|
18151
|
-
];
|
|
18152
|
-
}
|
|
18153
|
-
function generatePivotTitle(pivot) {
|
|
18154
|
-
if (pivot.rowField && !pivot.valueField && pivot.aggregations?.[0]) {
|
|
18155
|
-
return snakeAndCamelCaseToTitleCase(
|
|
18156
|
-
`${pivot.aggregations[0].aggregationType} of ${pivot.rowField}${pivot.columnField ? ` by ${pivot.columnField}` : ""}
|
|
18157
|
-
`
|
|
18158
|
-
);
|
|
18159
|
-
} else if (!pivot.rowField && pivot.aggregations?.[0]?.valueField) {
|
|
18160
|
-
return snakeAndCamelCaseToTitleCase(
|
|
18161
|
-
`${pivot.aggregations[0].aggregationType} of ${pivot.aggregations[0].valueField}
|
|
18162
|
-
`
|
|
18163
|
-
);
|
|
18164
|
-
}
|
|
18165
|
-
return snakeAndCamelCaseToTitleCase(
|
|
18166
|
-
`${pivot.aggregations?.[0]?.aggregationType ?? "Aggregation"} of ${pivot.aggregations?.[0]?.valueField ?? "value"}${pivot.rowField ? ` by ${pivot.rowField}` : ""}${pivot.columnField ? ` and ${pivot.columnField}` : ""}`
|
|
18167
|
-
);
|
|
18168
|
-
}
|
|
18169
|
-
async function generatePivotTable({
|
|
18170
|
-
pivot,
|
|
18171
|
-
dateBucket,
|
|
18172
|
-
dateFilter,
|
|
18173
|
-
report,
|
|
18174
|
-
client,
|
|
18175
|
-
getToken,
|
|
18176
|
-
eventTracking,
|
|
18177
|
-
uniqueValues,
|
|
18178
|
-
dashboardName,
|
|
18179
|
-
tenants,
|
|
18180
|
-
additionalProcessing,
|
|
18181
|
-
caller,
|
|
18182
|
-
pivotQuery
|
|
18183
|
-
}) {
|
|
18184
|
-
try {
|
|
18185
|
-
if (report && client) {
|
|
18186
|
-
const pivotTable = await generatePivotWithSQL({
|
|
18187
|
-
pivotQuery,
|
|
18188
|
-
pivot,
|
|
18189
|
-
report,
|
|
18190
|
-
client,
|
|
18191
|
-
dateBucket,
|
|
18192
|
-
dateFilter,
|
|
18193
|
-
distinctStrings: pivot.columnField && uniqueValues?.[pivot.columnField] ? uniqueValues[pivot.columnField] : [],
|
|
18194
|
-
dashboardName,
|
|
18195
|
-
tenants,
|
|
18196
|
-
additionalProcessing,
|
|
18197
|
-
caller,
|
|
18198
|
-
getToken
|
|
18199
|
-
});
|
|
18200
|
-
return pivotTable;
|
|
18201
|
-
}
|
|
18202
|
-
} catch (e) {
|
|
18203
|
-
eventTracking?.logError?.({
|
|
18204
|
-
type: "bug",
|
|
18205
|
-
// TODO: determine type
|
|
18206
|
-
severity: "high",
|
|
18207
|
-
message: "Error generating pivot table",
|
|
18208
|
-
errorMessage: e.message,
|
|
18209
|
-
errorStack: e.stack,
|
|
18210
|
-
errorData: {
|
|
18211
|
-
caller: "PivotModal",
|
|
18212
|
-
function: "generatePivotTable"
|
|
18213
|
-
}
|
|
18214
|
-
});
|
|
18215
|
-
throw Error(`Failed to generate pivot table with SQL: ${e}`);
|
|
17457
|
+
return generateDistinctQueryDatabricks(stringFields, query);
|
|
17458
|
+
case "clickhouse":
|
|
17459
|
+
// works with default for now
|
|
17460
|
+
default:
|
|
17461
|
+
return generateDistinctQueryDefault(stringFields, query, databaseType);
|
|
18216
17462
|
}
|
|
18217
|
-
throw Error("Failed to generate pivot table: invalid report");
|
|
18218
17463
|
}
|
|
18219
|
-
|
|
18220
|
-
|
|
18221
|
-
|
|
18222
|
-
|
|
18223
|
-
|
|
18224
|
-
}
|
|
17464
|
+
function generateDistinctQueryDefault(stringFields, query, databaseType) {
|
|
17465
|
+
const distinctQueries = stringFields.map((field) => {
|
|
17466
|
+
return `SELECT '${field}' AS ${processColumnReference("field", databaseType)}, ARRAY_AGG(DISTINCT ${field}) AS ${processColumnReference("string_values", databaseType)} FROM querytable`;
|
|
17467
|
+
});
|
|
17468
|
+
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17469
|
+
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
18225
17470
|
}
|
|
18226
|
-
|
|
18227
|
-
|
|
18228
|
-
|
|
18229
|
-
|
|
18230
|
-
|
|
18231
|
-
|
|
18232
|
-
};
|
|
18233
|
-
|
|
18234
|
-
|
|
18235
|
-
rowsPerPage: 10,
|
|
18236
|
-
rowsPerRequest: 50
|
|
18237
|
-
};
|
|
18238
|
-
function shouldFetchMore(pagination, page, maxPage, currentRowCount) {
|
|
18239
|
-
if (!pagination || currentRowCount && currentRowCount >= pagination.rowsPerPage * (page + 1)) {
|
|
18240
|
-
return false;
|
|
18241
|
-
}
|
|
18242
|
-
const indexAdjustedPage = page;
|
|
18243
|
-
const pageInterval = Math.floor(
|
|
18244
|
-
indexAdjustedPage * pagination.rowsPerPage / pagination.rowsPerRequest
|
|
18245
|
-
);
|
|
18246
|
-
const indexAdjustedPreviousPage = maxPage;
|
|
18247
|
-
const previousPageInterval = Math.floor(
|
|
18248
|
-
indexAdjustedPreviousPage * pagination.rowsPerPage / pagination.rowsPerRequest
|
|
18249
|
-
);
|
|
18250
|
-
return pageInterval > previousPageInterval;
|
|
17471
|
+
function generateDistinctQueryMySQL(stringFields, query) {
|
|
17472
|
+
const distinctQueries = stringFields.map((field) => {
|
|
17473
|
+
return `
|
|
17474
|
+
SELECT '${field}' AS ${processColumnReference("field", "mysql")},
|
|
17475
|
+
JSON_ARRAYAGG(\`${field}\`) AS ${processColumnReference("string_values", "mysql")}
|
|
17476
|
+
FROM (SELECT DISTINCT \`${field}\` FROM querytable) AS distinct_${replaceSpacesWithUnderscores(field)}`;
|
|
17477
|
+
});
|
|
17478
|
+
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17479
|
+
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
18251
17480
|
}
|
|
18252
|
-
function
|
|
18253
|
-
|
|
18254
|
-
return
|
|
18255
|
-
|
|
18256
|
-
|
|
17481
|
+
function generateDistinctQueryBigQuery(stringFields, query) {
|
|
17482
|
+
const distinctQueries = stringFields.map((field) => {
|
|
17483
|
+
return `
|
|
17484
|
+
SELECT '${field}' AS ${processColumnReference("field", "bigquery")},
|
|
17485
|
+
ARRAY_AGG(\`${field}\`) AS ${processColumnReference("string_values", "bigquery")}
|
|
17486
|
+
FROM (SELECT \`${field}\` FROM querytable WHERE \`${field}\` IS NOT NULL GROUP BY \`${field}\`) AS distinct_${replaceSpacesWithUnderscores(field)}`;
|
|
17487
|
+
});
|
|
17488
|
+
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17489
|
+
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17490
|
+
}
|
|
17491
|
+
function generateDistinctQueryPostgres(stringFields, query) {
|
|
17492
|
+
const distinctQueries = stringFields.map((field) => {
|
|
17493
|
+
return `SELECT '${field}' AS ${processColumnReference("field", "postgresql")}, to_json(ARRAY_AGG(DISTINCT "${field}")) AS ${processColumnReference("string_values", "postgresql")} FROM querytable`;
|
|
17494
|
+
});
|
|
17495
|
+
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17496
|
+
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17497
|
+
}
|
|
17498
|
+
function generateDistinctQuerySnowflake(stringFields, query) {
|
|
17499
|
+
const distinctQueries = stringFields.map((field) => {
|
|
17500
|
+
return `SELECT '${field}' AS "field", ARRAY_AGG(DISTINCT "${field}") AS "string_values" FROM querytable`;
|
|
17501
|
+
});
|
|
17502
|
+
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17503
|
+
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17504
|
+
}
|
|
17505
|
+
function generateDistinctQueryMSSQL(stringFields, query) {
|
|
17506
|
+
const escapeFieldName = (field) => field.replace(/'/g, "''");
|
|
17507
|
+
const distinctQueries = stringFields.map((field) => {
|
|
17508
|
+
return `
|
|
17509
|
+
SELECT
|
|
17510
|
+
'${escapeFieldName(field)}' AS field,
|
|
17511
|
+
STRING_AGG(${field}, ',') AS string_values
|
|
17512
|
+
FROM (
|
|
17513
|
+
SELECT ${field}
|
|
17514
|
+
FROM querytable
|
|
17515
|
+
WHERE ${field} IS NOT NULL
|
|
17516
|
+
GROUP BY ${field}
|
|
17517
|
+
) AS grouped
|
|
17518
|
+
`.replace(/\s+/g, " ").trim();
|
|
17519
|
+
});
|
|
17520
|
+
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17521
|
+
return `
|
|
17522
|
+
WITH querytable AS (
|
|
17523
|
+
${query.replace(";", "")}
|
|
17524
|
+
)
|
|
17525
|
+
${distinctQuery}`.replace(/\s+/g, " ").trim();
|
|
17526
|
+
}
|
|
17527
|
+
function generateDistinctQueryDatabricks(stringFields, query) {
|
|
17528
|
+
const distinctQueries = stringFields.map((field) => {
|
|
17529
|
+
return `SELECT '${field}' AS ${processColumnReference("field", "databricks")}, collect_set(\`${field}\`) AS ${processColumnReference("string_values", "databricks")} FROM querytable`;
|
|
17530
|
+
});
|
|
17531
|
+
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17532
|
+
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17533
|
+
}
|
|
17534
|
+
function generateMinMaxDateRangeQueries(columnFields, query, databaseType) {
|
|
17535
|
+
const max2 = "MAX";
|
|
17536
|
+
const min2 = "MIN";
|
|
17537
|
+
const cast = databaseType.toLowerCase() === "snowflake" ? "::TIMESTAMP_TZ" : "";
|
|
17538
|
+
const distinctQueries = columnFields.map((field) => {
|
|
17539
|
+
const wrappedField = ["postgresql", "clickhouse"].includes(
|
|
17540
|
+
databaseType.toLowerCase()
|
|
17541
|
+
) ? processColumnReference(field, databaseType) : field;
|
|
17542
|
+
return `SELECT '${field}' AS ${processColumnReference("field", databaseType)}, ${min2}(${wrappedField})${cast} AS ${processColumnReference("min_range", databaseType)}, ${max2}(${wrappedField})${cast} AS ${processColumnReference("max_range", databaseType)} FROM querytable`;
|
|
17543
|
+
});
|
|
17544
|
+
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17545
|
+
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
18257
17546
|
}
|
|
18258
17547
|
|
|
18259
17548
|
// src/utils/tableProcessing.ts
|
|
@@ -18894,595 +18183,110 @@ var fetchResultsByReport = async ({
|
|
|
18894
18183
|
if (e instanceof Error && e.name === "AbortError") {
|
|
18895
18184
|
throw e;
|
|
18896
18185
|
}
|
|
18897
|
-
eventTracking?.logError?.({
|
|
18898
|
-
type: "bug",
|
|
18899
|
-
// TODO: determine type
|
|
18900
|
-
severity: "high",
|
|
18901
|
-
message: "Error fetching results by report",
|
|
18902
|
-
errorMessage: e.message,
|
|
18903
|
-
errorStack: e.stack,
|
|
18904
|
-
errorData: {
|
|
18905
|
-
caller: "fetchResultsByReport",
|
|
18906
|
-
function: "fetchResultsByReport"
|
|
18907
|
-
}
|
|
18908
|
-
});
|
|
18909
|
-
rows = [];
|
|
18910
|
-
columns = [];
|
|
18911
|
-
rowCount = 0;
|
|
18912
|
-
error = e.message;
|
|
18913
|
-
}
|
|
18914
|
-
if (client.databaseType && client.databaseType.toLowerCase() === "bigquery") {
|
|
18915
|
-
parseValueFromBigQueryDates(rows, columns);
|
|
18916
|
-
}
|
|
18917
|
-
return { rows, columns, rowCount, error };
|
|
18918
|
-
};
|
|
18919
|
-
var fetchTableByAST = async (ast, client, getToken, tenants, eventTracking, dashboardName, processing, customFields, rowsOnly, rowCountOnly) => {
|
|
18920
|
-
let rows = [];
|
|
18921
|
-
let columns = [];
|
|
18922
|
-
let rowCount;
|
|
18923
|
-
let error;
|
|
18924
|
-
let itemQuery;
|
|
18925
|
-
let referencedTables;
|
|
18926
|
-
try {
|
|
18927
|
-
const fetchResp = await quillFetch({
|
|
18928
|
-
client,
|
|
18929
|
-
task: "patterns",
|
|
18930
|
-
metadata: {
|
|
18931
|
-
clientId: client.publicKey,
|
|
18932
|
-
ast,
|
|
18933
|
-
customFields,
|
|
18934
|
-
additionalProcessing: processing,
|
|
18935
|
-
useUpdatedDataGathering: true,
|
|
18936
|
-
useNewNodeSql: true,
|
|
18937
|
-
rowsOnly,
|
|
18938
|
-
rowCountOnly,
|
|
18939
|
-
dashboardName,
|
|
18940
|
-
tenants
|
|
18941
|
-
},
|
|
18942
|
-
getToken
|
|
18943
|
-
});
|
|
18944
|
-
const resp = await parseFetchResponse(
|
|
18945
|
-
client,
|
|
18946
|
-
"patterns",
|
|
18947
|
-
fetchResp,
|
|
18948
|
-
getToken
|
|
18949
|
-
);
|
|
18950
|
-
if (resp.errorMessage || resp.name === "error") {
|
|
18951
|
-
throw new Error(resp.errorMessage);
|
|
18952
|
-
}
|
|
18953
|
-
processFilterErrorList(resp);
|
|
18954
|
-
if (resp.rowCount !== void 0) {
|
|
18955
|
-
rowCount = resp.rowCount;
|
|
18956
|
-
}
|
|
18957
|
-
const gatheredRows = resp.rows && resp.rows.length ? resp.rows : [];
|
|
18958
|
-
columns = resp.fields.map((elem) => convertPostgresColumn(elem));
|
|
18959
|
-
rows = gatheredRows;
|
|
18960
|
-
itemQuery = resp.itemQuery;
|
|
18961
|
-
referencedTables = resp.referencedTables;
|
|
18962
|
-
if (customFields) {
|
|
18963
|
-
const tables = referencedTables ?? [];
|
|
18964
|
-
tables.forEach((table) => {
|
|
18965
|
-
const _customFields = customFields?.[table] ?? [];
|
|
18966
|
-
columns.forEach((col) => {
|
|
18967
|
-
if (_customFields.some((field) => {
|
|
18968
|
-
return field.field === col.field;
|
|
18969
|
-
})) {
|
|
18970
|
-
col.inferFormat = true;
|
|
18971
|
-
}
|
|
18972
|
-
});
|
|
18973
|
-
});
|
|
18974
|
-
}
|
|
18975
|
-
} catch (e) {
|
|
18976
|
-
eventTracking?.logError?.({
|
|
18977
|
-
type: "bug",
|
|
18978
|
-
// TODO: determine type
|
|
18979
|
-
severity: "high",
|
|
18980
|
-
message: "Error fetching table by AST",
|
|
18981
|
-
errorMessage: e.message,
|
|
18982
|
-
errorStack: e.stack,
|
|
18983
|
-
errorData: {
|
|
18984
|
-
caller: "fetchTableByAST",
|
|
18985
|
-
function: "fetchTableByAST"
|
|
18986
|
-
}
|
|
18987
|
-
});
|
|
18988
|
-
rows = [];
|
|
18989
|
-
columns = [];
|
|
18990
|
-
rowCount = 0;
|
|
18991
|
-
error = e.message;
|
|
18992
|
-
}
|
|
18993
|
-
if (client.databaseType && client.databaseType.toLowerCase() === "bigquery") {
|
|
18994
|
-
parseValueFromBigQueryDates(rows, columns);
|
|
18995
|
-
}
|
|
18996
|
-
return { rows, columns, rowCount, error, itemQuery, referencedTables };
|
|
18997
|
-
};
|
|
18998
|
-
|
|
18999
|
-
// src/utils/dashboard.ts
|
|
19000
|
-
var defaultDashboardItem = {
|
|
19001
|
-
id: "",
|
|
19002
|
-
name: "",
|
|
19003
|
-
dashboardName: "",
|
|
19004
|
-
rows: [],
|
|
19005
|
-
compareRows: [],
|
|
19006
|
-
columns: [],
|
|
19007
|
-
chartType: "",
|
|
19008
|
-
pivot: null,
|
|
19009
|
-
yAxisFields: [],
|
|
19010
|
-
xAxisLabel: "",
|
|
19011
|
-
xAxisField: "",
|
|
19012
|
-
xAxisFormat: "string",
|
|
19013
|
-
order: -1,
|
|
19014
|
-
filtersApplied: [],
|
|
19015
|
-
queryString: "",
|
|
19016
|
-
rowCount: 0,
|
|
19017
|
-
columnInternal: []
|
|
19018
|
-
};
|
|
19019
|
-
async function cleanDashboardItem({
|
|
19020
|
-
item,
|
|
19021
|
-
dashboardFilters,
|
|
19022
|
-
getToken,
|
|
19023
|
-
eventTracking,
|
|
19024
|
-
client,
|
|
19025
|
-
dateBucket,
|
|
19026
|
-
additionalProcessing,
|
|
19027
|
-
customFields,
|
|
19028
|
-
skipPivotFetch,
|
|
19029
|
-
tenants
|
|
19030
|
-
}) {
|
|
19031
|
-
if (!item) return defaultDashboardItem;
|
|
19032
|
-
if (!item.rows) {
|
|
19033
|
-
return {
|
|
19034
|
-
...defaultDashboardItem,
|
|
19035
|
-
id: item._id,
|
|
19036
|
-
name: item.name
|
|
19037
|
-
};
|
|
19038
|
-
}
|
|
19039
|
-
const fields = item.fields || [];
|
|
19040
|
-
const columnsWithCustomFields = [...item.columns ?? []];
|
|
19041
|
-
if (item.includeCustomFields && item.rows?.length > 0) {
|
|
19042
|
-
const tables = item.referencedTables ?? [];
|
|
19043
|
-
tables.forEach((table) => {
|
|
19044
|
-
const _customFields = customFields?.[table] ?? [];
|
|
19045
|
-
_customFields.forEach((field) => {
|
|
19046
|
-
const isJsonCustomField = !!field.refColumn;
|
|
19047
|
-
if (item.rows[0][field.field] !== void 0 && !item.columns.some((col) => col.field === field.field)) {
|
|
19048
|
-
const result_field = fields.find((f) => f.name === field.field);
|
|
19049
|
-
const converted_field = convertPostgresColumn(result_field ?? {});
|
|
19050
|
-
columnsWithCustomFields.push({
|
|
19051
|
-
field: field.field,
|
|
19052
|
-
format: converted_field.format,
|
|
19053
|
-
label: snakeAndCamelCaseToTitleCase(field.field),
|
|
19054
|
-
fieldType: converted_field.fieldType,
|
|
19055
|
-
dataTypeID: converted_field.dataTypeID,
|
|
19056
|
-
jsType: converted_field.jsType,
|
|
19057
|
-
inferFormat: isJsonCustomField
|
|
19058
|
-
});
|
|
19059
|
-
}
|
|
19060
|
-
});
|
|
19061
|
-
});
|
|
19062
|
-
}
|
|
19063
|
-
const processedColumns = item.columns.map((col) => {
|
|
19064
|
-
return { ...col, label: snakeAndCamelCaseToTitleCase(col.label) };
|
|
19065
|
-
});
|
|
19066
|
-
const columnInternal = (item.includeCustomFields ? columnsWithCustomFields : item.columns).map((col) => {
|
|
19067
|
-
const field = item.fields?.find((f) => f.name === col.field);
|
|
19068
|
-
const converted_field = convertPostgresColumn(field ?? {});
|
|
19069
|
-
return {
|
|
19070
|
-
fieldType: converted_field.fieldType,
|
|
19071
|
-
dataTypeID: converted_field.dataTypeID,
|
|
19072
|
-
jsType: converted_field.jsType,
|
|
19073
|
-
...col,
|
|
19074
|
-
label: snakeAndCamelCaseToTitleCase(col.label)
|
|
19075
|
-
};
|
|
19076
|
-
});
|
|
19077
|
-
let pivotTable;
|
|
19078
|
-
let pivotError;
|
|
19079
|
-
try {
|
|
19080
|
-
const shouldPaginatePivotAsTable = item.chartType === "table";
|
|
19081
|
-
const pivotChartProcessing = {
|
|
19082
|
-
page: DEFAULT_PAGINATION
|
|
19083
|
-
};
|
|
19084
|
-
pivotTable = await getPivotTable(
|
|
19085
|
-
{
|
|
19086
|
-
...item,
|
|
19087
|
-
pivot: item.pivot && !skipPivotFetch ? {
|
|
19088
|
-
...item.pivot,
|
|
19089
|
-
aggregations: item.pivot.aggregations ?? [
|
|
19090
|
-
{
|
|
19091
|
-
valueField: item.pivot.valueField,
|
|
19092
|
-
valueFieldType: item.pivot.valueFieldType,
|
|
19093
|
-
valueField2: item.pivot.valueField2,
|
|
19094
|
-
valueField2Type: item.pivot.valueField2Type,
|
|
19095
|
-
aggregationType: item.pivot.aggregationType
|
|
19096
|
-
}
|
|
19097
|
-
]
|
|
19098
|
-
} : void 0
|
|
19099
|
-
},
|
|
19100
|
-
dashboardFilters,
|
|
19101
|
-
item.dashboardName,
|
|
19102
|
-
getToken,
|
|
19103
|
-
client,
|
|
19104
|
-
eventTracking,
|
|
19105
|
-
dateBucket,
|
|
19106
|
-
shouldPaginatePivotAsTable ? additionalProcessing : pivotChartProcessing,
|
|
19107
|
-
tenants,
|
|
19108
|
-
customFields
|
|
19109
|
-
);
|
|
19110
|
-
} catch (e) {
|
|
19111
|
-
pivotTable = void 0;
|
|
19112
|
-
eventTracking?.logError?.({
|
|
19113
|
-
type: "bug",
|
|
19114
|
-
// TODO: determine type
|
|
19115
|
-
severity: "high",
|
|
19116
|
-
message: "Error fetching pivot table",
|
|
19117
|
-
errorMessage: e.message,
|
|
19118
|
-
errorStack: e.stack,
|
|
19119
|
-
errorData: {
|
|
19120
|
-
caller: "cleanDashboardItem",
|
|
19121
|
-
function: "cleanDashboardItem"
|
|
19122
|
-
}
|
|
19123
|
-
});
|
|
19124
|
-
console.error("Error fetching pivot table", e);
|
|
19125
|
-
pivotError = "Error fetching pivot table";
|
|
19126
|
-
}
|
|
19127
|
-
const referenceLineYValues = [];
|
|
19128
|
-
for (const key in item) {
|
|
19129
|
-
if (key.startsWith("referenceLine_")) {
|
|
19130
|
-
const field = key.slice(14);
|
|
19131
|
-
if (!item[key] || !item[key][0]) continue;
|
|
19132
|
-
const value = Object.values(item[key][0])[0];
|
|
19133
|
-
referenceLineYValues.push({ label: field, query: [value, value] });
|
|
19134
|
-
}
|
|
19135
|
-
}
|
|
19136
|
-
if (item.referenceLines) {
|
|
19137
|
-
for (const referenceLine of item.referenceLines) {
|
|
19138
|
-
if (Array.isArray(referenceLine.query)) {
|
|
19139
|
-
referenceLineYValues.push({
|
|
19140
|
-
label: referenceLine.label,
|
|
19141
|
-
query: referenceLine.query
|
|
19142
|
-
});
|
|
19143
|
-
} else if (referenceLine.query === "") {
|
|
19144
|
-
referenceLineYValues.push({
|
|
19145
|
-
label: referenceLine.label,
|
|
19146
|
-
query: (pivotTable?.rows ? pivotTable.rows : item.rows).map(
|
|
19147
|
-
(row) => Number(row[referenceLine.label]) || 0
|
|
19148
|
-
)
|
|
19149
|
-
});
|
|
19150
|
-
}
|
|
19151
|
-
}
|
|
19152
|
-
}
|
|
19153
|
-
return {
|
|
19154
|
-
id: item._id ?? item.id,
|
|
19155
|
-
name: item.name,
|
|
19156
|
-
dashboardName: item.dashboardName,
|
|
19157
|
-
// section: item.section,
|
|
19158
|
-
rows: item.rows,
|
|
19159
|
-
pivotRows: pivotTable ? pivotTable.rows : void 0,
|
|
19160
|
-
pivotColumns: pivotTable ? pivotTable.columns : void 0,
|
|
19161
|
-
compareRows: item.compareRows,
|
|
19162
|
-
columns: processedColumns.map((column) => {
|
|
19163
|
-
return {
|
|
19164
|
-
field: column.field,
|
|
19165
|
-
format: column.format,
|
|
19166
|
-
label: column.label,
|
|
19167
|
-
inferFormat: column.inferFormat
|
|
19168
|
-
};
|
|
19169
|
-
}),
|
|
19170
|
-
includeCustomFields: item.includeCustomFields,
|
|
19171
|
-
columnInternal,
|
|
19172
|
-
columnsWithCustomFields,
|
|
19173
|
-
chartType: item.chartType,
|
|
19174
|
-
dateField: item.dateField,
|
|
19175
|
-
pivot: pivotError ? void 0 : item.pivot ? {
|
|
19176
|
-
...item.pivot,
|
|
19177
|
-
aggregations: item.pivot.aggregations ?? [
|
|
19178
|
-
{
|
|
19179
|
-
valueField: item.pivot.valueField,
|
|
19180
|
-
valueFieldType: item.pivot.valueFieldType,
|
|
19181
|
-
valueField2: item.pivot.valueField2,
|
|
19182
|
-
valueField2Type: item.pivot.valueField2Type,
|
|
19183
|
-
aggregationType: item.pivot.aggregationType
|
|
19184
|
-
}
|
|
19185
|
-
],
|
|
19186
|
-
columnValues: item.distinctStrings
|
|
19187
|
-
} : void 0,
|
|
19188
|
-
yAxisFields: pivotTable ? extractPivotedYAxis(pivotTable, item) : item.yAxisFields,
|
|
19189
|
-
xAxisLabel: item.xAxisLabel,
|
|
19190
|
-
xAxisField: item.xAxisField,
|
|
19191
|
-
xAxisFormat: item.xAxisFormat,
|
|
19192
|
-
order: item.order,
|
|
19193
|
-
filtersApplied: item.filtersApplied,
|
|
19194
|
-
filterMap: item.filterMap,
|
|
19195
|
-
flags: item.flags,
|
|
19196
|
-
rowCount: item.rowCount ? parseInt(item.rowCount) : item.rows.length,
|
|
19197
|
-
pivotRowCount: pivotTable ? pivotTable.rowCount : void 0,
|
|
19198
|
-
template: item.template,
|
|
19199
|
-
sort: item.sort,
|
|
19200
|
-
itemQuery: item.itemQuery,
|
|
19201
|
-
queryString: item.queryString,
|
|
19202
|
-
pivotQuery: pivotTable?.pivotQuery,
|
|
19203
|
-
comparisonPivotQuery: pivotTable?.comparisonPivotQuery,
|
|
19204
|
-
referencedTables: item?.referencedTables || [],
|
|
19205
|
-
referencedColumns: item?.referencedColumns || {},
|
|
19206
|
-
error: item.error ?? pivotError,
|
|
19207
|
-
referenceLineYValues,
|
|
19208
|
-
referenceLines: item.referenceLines
|
|
19209
|
-
};
|
|
19210
|
-
}
|
|
19211
|
-
async function getPivotTable(report, dashboardFilters, dashboardName, getToken, client, eventTracking, dateBucketInitial, additionalProcessing, tenants, customFields) {
|
|
19212
|
-
if (!report) return void 0;
|
|
19213
|
-
const dateFilter = Object.values(dashboardFilters ?? {}).find(
|
|
19214
|
-
(filter) => filter.filterType === "date_range" || filter.operator === "BETWEEN"
|
|
19215
|
-
);
|
|
19216
|
-
if (dateFilter?.operator === "BETWEEN") {
|
|
19217
|
-
dateFilter.startDate = dateFilter.value[0];
|
|
19218
|
-
dateFilter.endDate = dateFilter.value[1];
|
|
19219
|
-
}
|
|
19220
|
-
const pivot = report?.pivot;
|
|
19221
|
-
const data = report || {};
|
|
19222
|
-
if (pivot && client) {
|
|
19223
|
-
if (report.rowCount === 0 || report.rows.length === 0) {
|
|
19224
|
-
const columns = [];
|
|
19225
|
-
if (pivot.rowField) {
|
|
19226
|
-
columns.push({
|
|
19227
|
-
field: pivot.rowField,
|
|
19228
|
-
label: snakeCaseToTitleCase(processColumnName(pivot.rowField)),
|
|
19229
|
-
format: pivot.rowFieldType || "string",
|
|
19230
|
-
jsType: convertFieldTypeToJSType(pivot.rowFieldType || "string"),
|
|
19231
|
-
fieldType: pivot.rowFieldType || "string",
|
|
19232
|
-
dataTypeID: fieldTypeToDataTypeID(pivot.rowFieldType || "string")
|
|
19233
|
-
});
|
|
19234
|
-
}
|
|
19235
|
-
for (const agg of pivot.aggregations ?? []) {
|
|
19236
|
-
if (agg.valueField) {
|
|
19237
|
-
columns.push({
|
|
19238
|
-
field: agg.valueField,
|
|
19239
|
-
label: snakeCaseToTitleCase(processColumnName(agg.valueField)),
|
|
19240
|
-
//FIXME: valueFieldType is not always the same as the format
|
|
19241
|
-
format: agg.valueFieldType ?? "whole_number",
|
|
19242
|
-
jsType: agg.valueFieldType ?? "number",
|
|
19243
|
-
fieldType: agg.valueFieldType ?? "number",
|
|
19244
|
-
dataTypeID: fieldTypeToDataTypeID(agg.valueFieldType ?? "number")
|
|
19245
|
-
});
|
|
19246
|
-
}
|
|
19247
|
-
}
|
|
19248
|
-
const pivotQuery = generatePivotQuery(
|
|
19249
|
-
pivot,
|
|
19250
|
-
report.itemQuery?.[0],
|
|
19251
|
-
client.databaseType
|
|
19252
|
-
);
|
|
19253
|
-
return {
|
|
19254
|
-
rows: [],
|
|
19255
|
-
rowCount: 0,
|
|
19256
|
-
pivotQuery: pivotQuery ?? "",
|
|
19257
|
-
columns
|
|
19258
|
-
};
|
|
19259
|
-
}
|
|
19260
|
-
try {
|
|
19261
|
-
let dateBucket = dateBucketInitial;
|
|
19262
|
-
let filterDateRange = void 0;
|
|
19263
|
-
if (dateFilter && dateFilter.startDate && dateFilter.endDate) {
|
|
19264
|
-
filterDateRange = {
|
|
19265
|
-
start: dateFilter.startDate,
|
|
19266
|
-
end: dateFilter.endDate
|
|
19267
|
-
};
|
|
19268
|
-
} else if (report.dateRange) {
|
|
19269
|
-
filterDateRange = report.dateRange;
|
|
19270
|
-
}
|
|
19271
|
-
if (!dateBucket && filterDateRange) {
|
|
19272
|
-
dateBucket = getDateBucketFromRange(filterDateRange);
|
|
19273
|
-
}
|
|
19274
|
-
if (pivot.columnField && !report.distinctStrings) {
|
|
19275
|
-
const columnFieldColumn = (report.columnsWithCustomFields ?? report.columns).find((col) => col.field === pivot.columnField);
|
|
19276
|
-
if (!columnFieldColumn) {
|
|
19277
|
-
console.error(
|
|
19278
|
-
"could not find pivot column field on report",
|
|
19279
|
-
pivot.columnField
|
|
19280
|
-
);
|
|
19281
|
-
}
|
|
19282
|
-
const unique = await getUniqueValuesByQuery({
|
|
19283
|
-
columns: [columnFieldColumn],
|
|
19284
|
-
query: report.queryString,
|
|
19285
|
-
client,
|
|
19286
|
-
getToken,
|
|
19287
|
-
dashboardName,
|
|
19288
|
-
tenants,
|
|
19289
|
-
customFields: customFields ?? {},
|
|
19290
|
-
eventTracking
|
|
19291
|
-
});
|
|
19292
|
-
report.distinctStrings = unique?.[pivot.columnField] ?? [];
|
|
19293
|
-
}
|
|
19294
|
-
if (pivot.columnField && !report.distinctStrings) {
|
|
19295
|
-
const columnFieldColumn = (report.columnsWithCustomFields ?? report.columns).find((col) => col.field === pivot.columnField);
|
|
19296
|
-
if (!columnFieldColumn) {
|
|
19297
|
-
console.error(
|
|
19298
|
-
"could not find pivot column field on report",
|
|
19299
|
-
pivot.columnField
|
|
19300
|
-
);
|
|
19301
|
-
}
|
|
19302
|
-
const unique = await getUniqueValuesByQuery({
|
|
19303
|
-
columns: [columnFieldColumn],
|
|
19304
|
-
query: report.queryString,
|
|
19305
|
-
client,
|
|
19306
|
-
getToken,
|
|
19307
|
-
dashboardName,
|
|
19308
|
-
tenants,
|
|
19309
|
-
customFields: customFields ?? {},
|
|
19310
|
-
eventTracking
|
|
19311
|
-
});
|
|
19312
|
-
report.distinctStrings = unique?.[pivot.columnField] ?? [];
|
|
18186
|
+
eventTracking?.logError?.({
|
|
18187
|
+
type: "bug",
|
|
18188
|
+
// TODO: determine type
|
|
18189
|
+
severity: "high",
|
|
18190
|
+
message: "Error fetching results by report",
|
|
18191
|
+
errorMessage: e.message,
|
|
18192
|
+
errorStack: e.stack,
|
|
18193
|
+
errorData: {
|
|
18194
|
+
caller: "fetchResultsByReport",
|
|
18195
|
+
function: "fetchResultsByReport"
|
|
19313
18196
|
}
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
|
|
19319
|
-
|
|
19320
|
-
|
|
18197
|
+
});
|
|
18198
|
+
rows = [];
|
|
18199
|
+
columns = [];
|
|
18200
|
+
rowCount = 0;
|
|
18201
|
+
error = e.message;
|
|
18202
|
+
}
|
|
18203
|
+
if (client.databaseType && client.databaseType.toLowerCase() === "bigquery") {
|
|
18204
|
+
parseValueFromBigQueryDates(rows, columns);
|
|
18205
|
+
}
|
|
18206
|
+
return { rows, columns, rowCount, error };
|
|
18207
|
+
};
|
|
18208
|
+
var fetchTableByAST = async (ast, client, getToken, tenants, eventTracking, dashboardName, processing, customFields, rowsOnly, rowCountOnly) => {
|
|
18209
|
+
let rows = [];
|
|
18210
|
+
let columns = [];
|
|
18211
|
+
let rowCount;
|
|
18212
|
+
let error;
|
|
18213
|
+
let itemQuery;
|
|
18214
|
+
let referencedTables;
|
|
18215
|
+
try {
|
|
18216
|
+
const fetchResp = await quillFetch({
|
|
18217
|
+
client,
|
|
18218
|
+
task: "patterns",
|
|
18219
|
+
metadata: {
|
|
18220
|
+
clientId: client.publicKey,
|
|
18221
|
+
ast,
|
|
18222
|
+
customFields,
|
|
18223
|
+
additionalProcessing: processing,
|
|
18224
|
+
useUpdatedDataGathering: true,
|
|
18225
|
+
useNewNodeSql: true,
|
|
18226
|
+
rowsOnly,
|
|
18227
|
+
rowCountOnly,
|
|
19321
18228
|
dashboardName,
|
|
19322
|
-
tenants
|
|
19323
|
-
|
|
19324
|
-
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
|
|
19328
|
-
|
|
19329
|
-
|
|
19330
|
-
|
|
19331
|
-
|
|
19332
|
-
|
|
19333
|
-
|
|
19334
|
-
|
|
19335
|
-
|
|
19336
|
-
|
|
19337
|
-
|
|
19338
|
-
|
|
18229
|
+
tenants
|
|
18230
|
+
},
|
|
18231
|
+
getToken
|
|
18232
|
+
});
|
|
18233
|
+
const resp = await parseFetchResponse(
|
|
18234
|
+
client,
|
|
18235
|
+
"patterns",
|
|
18236
|
+
fetchResp,
|
|
18237
|
+
getToken
|
|
18238
|
+
);
|
|
18239
|
+
if (resp.errorMessage || resp.name === "error") {
|
|
18240
|
+
throw new Error(resp.errorMessage);
|
|
18241
|
+
}
|
|
18242
|
+
processFilterErrorList(resp);
|
|
18243
|
+
if (resp.rowCount !== void 0) {
|
|
18244
|
+
rowCount = resp.rowCount;
|
|
18245
|
+
}
|
|
18246
|
+
const gatheredRows = resp.rows && resp.rows.length ? resp.rows : [];
|
|
18247
|
+
columns = resp.fields.map((elem) => convertPostgresColumn(elem));
|
|
18248
|
+
rows = gatheredRows;
|
|
18249
|
+
itemQuery = resp.itemQuery;
|
|
18250
|
+
referencedTables = resp.referencedTables;
|
|
18251
|
+
if (customFields) {
|
|
18252
|
+
const tables = referencedTables ?? [];
|
|
18253
|
+
tables.forEach((table) => {
|
|
18254
|
+
const _customFields = customFields?.[table] ?? [];
|
|
18255
|
+
columns.forEach((col) => {
|
|
18256
|
+
if (_customFields.some((field) => {
|
|
18257
|
+
return field.field === col.field;
|
|
18258
|
+
})) {
|
|
18259
|
+
col.inferFormat = true;
|
|
18260
|
+
}
|
|
18261
|
+
});
|
|
19339
18262
|
});
|
|
19340
|
-
console.error("Error fetching pivot table", e);
|
|
19341
|
-
throw e;
|
|
19342
18263
|
}
|
|
19343
|
-
}
|
|
19344
|
-
|
|
19345
|
-
|
|
19346
|
-
|
|
19347
|
-
|
|
19348
|
-
|
|
19349
|
-
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19354
|
-
eventTracking
|
|
19355
|
-
}) : void 0;
|
|
19356
|
-
}
|
|
19357
|
-
function extractPivotedYAxis(pivotTable, itemInfo, config = void 0) {
|
|
19358
|
-
if (!pivotTable) return itemInfo?.yAxisFields ?? [];
|
|
19359
|
-
const pivot = itemInfo?.pivot || config?.pivot;
|
|
19360
|
-
if (!pivot.columnField && !pivot.rowField) return itemInfo?.yAxisFields ?? [];
|
|
19361
|
-
const yAxisFields = config ? config.yAxisFields : itemInfo?.yAxisFields;
|
|
19362
|
-
return yAxisFields && yAxisFields.length > 0 ? generatePivotTableYAxis(pivot, pivotTable.columns, yAxisFields[0]) : yAxisFields;
|
|
19363
|
-
}
|
|
19364
|
-
async function getDashboard(dashboardName, client, getToken, tenants, flags) {
|
|
19365
|
-
const { data: resp } = await quillFetch({
|
|
19366
|
-
client,
|
|
19367
|
-
task: "dashboard",
|
|
19368
|
-
metadata: {
|
|
19369
|
-
name: dashboardName,
|
|
19370
|
-
clientId: client.publicKey,
|
|
19371
|
-
databaseType: client.databaseType,
|
|
19372
|
-
useNewNodeSql: true,
|
|
19373
|
-
tenants,
|
|
19374
|
-
flags
|
|
19375
|
-
},
|
|
19376
|
-
getToken
|
|
19377
|
-
});
|
|
19378
|
-
return {
|
|
19379
|
-
...resp,
|
|
19380
|
-
createdAt: resp.createdAt && new Date(resp.createdAt),
|
|
19381
|
-
dateFilter: resp.dateFilter ? {
|
|
19382
|
-
...resp.dateFilter,
|
|
19383
|
-
presetOptions: resp.dateFilter.presetOptions?.map(
|
|
19384
|
-
(preset) => ({
|
|
19385
|
-
...preset,
|
|
19386
|
-
loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
|
|
19387
|
-
loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
|
|
19388
|
-
})
|
|
19389
|
-
),
|
|
19390
|
-
defaultPresetRanges: resp.dateFilter.defaultPresetRanges?.map(
|
|
19391
|
-
(preset) => ({
|
|
19392
|
-
...preset,
|
|
19393
|
-
loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
|
|
19394
|
-
loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
|
|
19395
|
-
})
|
|
19396
|
-
)
|
|
19397
|
-
} : void 0
|
|
19398
|
-
};
|
|
19399
|
-
}
|
|
19400
|
-
|
|
19401
|
-
// src/utils/chartBuilder.ts
|
|
19402
|
-
var numberFormatOptions = [
|
|
19403
|
-
"whole_number",
|
|
19404
|
-
"one_decimal_place",
|
|
19405
|
-
"two_decimal_places",
|
|
19406
|
-
"dollar_amount",
|
|
19407
|
-
"dollar_cents",
|
|
19408
|
-
"percentage"
|
|
19409
|
-
];
|
|
19410
|
-
var dateFormatOptions = [
|
|
19411
|
-
"MMM_yyyy",
|
|
19412
|
-
"MMM_dd",
|
|
19413
|
-
"MMM_dd_yyyy",
|
|
19414
|
-
"MMM_dd_hh:mm_ap_pm",
|
|
19415
|
-
"hh_ap_pm",
|
|
19416
|
-
"date",
|
|
19417
|
-
"timestamptz"
|
|
19418
|
-
];
|
|
19419
|
-
var NUMBER_OPTIONS = [
|
|
19420
|
-
{ value: "whole_number", label: "whole number" },
|
|
19421
|
-
{ value: "one_decimal_place", label: "one decimal place" },
|
|
19422
|
-
{ value: "two_decimal_places", label: "two decimal places" },
|
|
19423
|
-
{ value: "dollar_amount", label: "dollar amount" },
|
|
19424
|
-
{ value: "dollar_cents", label: "dollar and cent amount" },
|
|
19425
|
-
{ value: "percent", label: "percentage" }
|
|
19426
|
-
];
|
|
19427
|
-
var DATE_OPTIONS = [
|
|
19428
|
-
{ value: "MMM_yyyy", label: "month" },
|
|
19429
|
-
{ value: "MMM_dd", label: "day" },
|
|
19430
|
-
{ value: "MMM_dd_yyyy", label: "day and year" },
|
|
19431
|
-
{ value: "MMM_dd_hh:mm_ap_pm", label: "day and time" },
|
|
19432
|
-
{ value: "hh_ap_pm", label: "hour" }
|
|
19433
|
-
];
|
|
19434
|
-
var ALL_FORMAT_OPTIONS = [
|
|
19435
|
-
...NUMBER_OPTIONS,
|
|
19436
|
-
...DATE_OPTIONS,
|
|
19437
|
-
{ value: "string", label: "string" }
|
|
19438
|
-
];
|
|
19439
|
-
function createInitialFormData(columns) {
|
|
19440
|
-
const firstNumberColumn = columns?.find(
|
|
19441
|
-
(col) => numberFormatOptions.includes(col.format)
|
|
19442
|
-
);
|
|
19443
|
-
const firstStringColumn = columns?.find(
|
|
19444
|
-
(col) => !numberFormatOptions.includes(col.format) && !dateFormatOptions.includes(col.format)
|
|
19445
|
-
);
|
|
19446
|
-
const firstDateColumn = columns?.find(
|
|
19447
|
-
(col) => dateFormatOptions.includes(col.format)
|
|
19448
|
-
);
|
|
19449
|
-
const xAxisField = firstStringColumn?.field || firstDateColumn?.field || firstNumberColumn?.field || columns?.[0]?.field || "";
|
|
19450
|
-
const xAxisFormat = firstStringColumn?.format || firstDateColumn?.format || firstNumberColumn?.format || columns?.[0]?.format || "string";
|
|
19451
|
-
const formEmptyState = {
|
|
19452
|
-
name: "",
|
|
19453
|
-
columns: columns.map((col) => {
|
|
19454
|
-
return { ...col, label: snakeAndCamelCaseToTitleCase(col.label) };
|
|
19455
|
-
}),
|
|
19456
|
-
xAxisField,
|
|
19457
|
-
xAxisFormat,
|
|
19458
|
-
yAxisFields: [
|
|
19459
|
-
{
|
|
19460
|
-
field: firstNumberColumn?.field || columns?.[0]?.field || "",
|
|
19461
|
-
label: "",
|
|
19462
|
-
format: firstNumberColumn?.format || columns?.[0]?.format || "string"
|
|
18264
|
+
} catch (e) {
|
|
18265
|
+
eventTracking?.logError?.({
|
|
18266
|
+
type: "bug",
|
|
18267
|
+
// TODO: determine type
|
|
18268
|
+
severity: "high",
|
|
18269
|
+
message: "Error fetching table by AST",
|
|
18270
|
+
errorMessage: e.message,
|
|
18271
|
+
errorStack: e.stack,
|
|
18272
|
+
errorData: {
|
|
18273
|
+
caller: "fetchTableByAST",
|
|
18274
|
+
function: "fetchTableByAST"
|
|
19463
18275
|
}
|
|
19464
|
-
|
|
19465
|
-
|
|
19466
|
-
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
referenceLines: []
|
|
19470
|
-
};
|
|
19471
|
-
return formEmptyState;
|
|
19472
|
-
}
|
|
19473
|
-
|
|
19474
|
-
// src/utils/error.ts
|
|
19475
|
-
var DataLoadError = class extends Error {
|
|
19476
|
-
data;
|
|
19477
|
-
constructor(message, data) {
|
|
19478
|
-
super(message);
|
|
19479
|
-
this.name = "DataLoadError";
|
|
19480
|
-
this.data = data;
|
|
18276
|
+
});
|
|
18277
|
+
rows = [];
|
|
18278
|
+
columns = [];
|
|
18279
|
+
rowCount = 0;
|
|
18280
|
+
error = e.message;
|
|
19481
18281
|
}
|
|
18282
|
+
if (client.databaseType && client.databaseType.toLowerCase() === "bigquery") {
|
|
18283
|
+
parseValueFromBigQueryDates(rows, columns);
|
|
18284
|
+
}
|
|
18285
|
+
return { rows, columns, rowCount, error, itemQuery, referencedTables };
|
|
19482
18286
|
};
|
|
19483
18287
|
|
|
19484
18288
|
// src/components/ReportBuilder/convert.ts
|
|
19485
|
-
var
|
|
18289
|
+
var import_date_fns7 = require("date-fns");
|
|
19486
18290
|
function recursiveSearchAndReplace(node, search, replace) {
|
|
19487
18291
|
if (typeof node !== "object") {
|
|
19488
18292
|
return;
|
|
@@ -19791,7 +18595,7 @@ function convertStringComparison(node, databaseType) {
|
|
|
19791
18595
|
searchAndReplace(element);
|
|
19792
18596
|
});
|
|
19793
18597
|
} else if (typeof obj === "object" && obj !== null) {
|
|
19794
|
-
if (obj.type === "binary_expr" && (obj.operator === "=" && !(0,
|
|
18598
|
+
if (obj.type === "binary_expr" && (obj.operator === "=" && !(0, import_date_fns7.isValid)((0, import_date_fns7.parseISO)(obj.right.value)) || // don't do it on date objects
|
|
19795
18599
|
obj.operator === "LIKE" || obj.operator === "ILIKE") && obj.left && (obj.left.type === "column_ref" || obj.left.type === "double_quote_string") && obj.right && obj.right.type === "single_quote_string") {
|
|
19796
18600
|
obj.operator = "LIKE";
|
|
19797
18601
|
obj.left = {
|
|
@@ -23132,6 +21936,29 @@ var import_jspdf = __toESM(require("jspdf"), 1);
|
|
|
23132
21936
|
|
|
23133
21937
|
// src/hooks/useDashboard.ts
|
|
23134
21938
|
var import_react2 = require("react");
|
|
21939
|
+
|
|
21940
|
+
// src/utils/merge.ts
|
|
21941
|
+
var import_date_fns8 = require("date-fns");
|
|
21942
|
+
var import_date_fns_tz2 = require("date-fns-tz");
|
|
21943
|
+
function mergeComparisonRange(resp) {
|
|
21944
|
+
if (resp.chartType === "table") return resp;
|
|
21945
|
+
const compRows = resp.compareRows;
|
|
21946
|
+
if (!compRows) return resp;
|
|
21947
|
+
const newRows = resp.rows.map((row, i) => {
|
|
21948
|
+
if (i < compRows.length) {
|
|
21949
|
+
const compRow = compRows[i];
|
|
21950
|
+
const newRow = { ...row };
|
|
21951
|
+
for (const [key, value] of Object.entries(compRow)) {
|
|
21952
|
+
newRow[`comparison_${key}`] = value;
|
|
21953
|
+
}
|
|
21954
|
+
return newRow;
|
|
21955
|
+
}
|
|
21956
|
+
return row;
|
|
21957
|
+
});
|
|
21958
|
+
return { ...resp, rows: newRows };
|
|
21959
|
+
}
|
|
21960
|
+
|
|
21961
|
+
// src/hooks/useDashboard.ts
|
|
23135
21962
|
var useDashboardInternal = (dashboardName, customFilters) => {
|
|
23136
21963
|
const [dashboard] = (0, import_react2.useContext)(DashboardContext);
|
|
23137
21964
|
const {
|
|
@@ -38940,6 +37767,9 @@ var import_react46 = __toESM(require("@monaco-editor/react"), 1);
|
|
|
38940
37767
|
|
|
38941
37768
|
// src/ChartBuilder.tsx
|
|
38942
37769
|
var import_react43 = require("react");
|
|
37770
|
+
var import_core = require("@dnd-kit/core");
|
|
37771
|
+
var import_sortable = require("@dnd-kit/sortable");
|
|
37772
|
+
var import_utilities = require("@dnd-kit/utilities");
|
|
38943
37773
|
|
|
38944
37774
|
// src/internals/ReportBuilder/PivotModal.tsx
|
|
38945
37775
|
var import_react40 = require("react");
|
|
@@ -42182,6 +41012,173 @@ var CHART_TO_LABELS = {
|
|
|
42182
41012
|
"World map": { xAxisLabel: "Country", yAxisLabel: "Value" },
|
|
42183
41013
|
gauge: { xAxisLabel: "Value" }
|
|
42184
41014
|
};
|
|
41015
|
+
function SortableColumnItem({
|
|
41016
|
+
column,
|
|
41017
|
+
index,
|
|
41018
|
+
rows,
|
|
41019
|
+
columns,
|
|
41020
|
+
handleChange,
|
|
41021
|
+
deleteRef,
|
|
41022
|
+
deleteButtonMargin,
|
|
41023
|
+
handleRemoveField,
|
|
41024
|
+
SelectComponent,
|
|
41025
|
+
TextInputComponent,
|
|
41026
|
+
DeleteButtonComponent
|
|
41027
|
+
}) {
|
|
41028
|
+
const { attributes, listeners, setNodeRef, transform, transition: transition2 } = (0, import_sortable.useSortable)({ id: column.field });
|
|
41029
|
+
const style2 = {
|
|
41030
|
+
transform: import_utilities.CSS.Transform.toString(transform),
|
|
41031
|
+
transition: transition2
|
|
41032
|
+
};
|
|
41033
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { style: style2, ref: setNodeRef, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
41034
|
+
"div",
|
|
41035
|
+
{
|
|
41036
|
+
style: {
|
|
41037
|
+
display: "flex",
|
|
41038
|
+
alignItems: "center",
|
|
41039
|
+
gap: 4
|
|
41040
|
+
},
|
|
41041
|
+
children: [
|
|
41042
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
41043
|
+
"div",
|
|
41044
|
+
{
|
|
41045
|
+
style: {
|
|
41046
|
+
cursor: "grab",
|
|
41047
|
+
display: "flex",
|
|
41048
|
+
gap: 2,
|
|
41049
|
+
flexDirection: "row",
|
|
41050
|
+
paddingTop: 8,
|
|
41051
|
+
paddingBottom: 8,
|
|
41052
|
+
paddingLeft: 8,
|
|
41053
|
+
paddingRight: 8,
|
|
41054
|
+
borderRadius: 4
|
|
41055
|
+
},
|
|
41056
|
+
className: "handle",
|
|
41057
|
+
...attributes,
|
|
41058
|
+
...listeners,
|
|
41059
|
+
children: [
|
|
41060
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("style", { children: `.handle{background:white;} .handle:hover{background:rgba(0,0,0,0.03);}` }),
|
|
41061
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { style: { display: "flex", gap: 2, flexDirection: "column" }, children: [
|
|
41062
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41063
|
+
"div",
|
|
41064
|
+
{
|
|
41065
|
+
style: {
|
|
41066
|
+
width: 3,
|
|
41067
|
+
height: 3,
|
|
41068
|
+
borderRadius: 3,
|
|
41069
|
+
background: "#9CA0A7"
|
|
41070
|
+
}
|
|
41071
|
+
}
|
|
41072
|
+
),
|
|
41073
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41074
|
+
"div",
|
|
41075
|
+
{
|
|
41076
|
+
style: {
|
|
41077
|
+
width: 3,
|
|
41078
|
+
height: 3,
|
|
41079
|
+
borderRadius: 3,
|
|
41080
|
+
background: "#9CA0A7"
|
|
41081
|
+
}
|
|
41082
|
+
}
|
|
41083
|
+
),
|
|
41084
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41085
|
+
"div",
|
|
41086
|
+
{
|
|
41087
|
+
style: {
|
|
41088
|
+
width: 3,
|
|
41089
|
+
height: 3,
|
|
41090
|
+
borderRadius: 3,
|
|
41091
|
+
background: "#9CA0A7"
|
|
41092
|
+
}
|
|
41093
|
+
}
|
|
41094
|
+
)
|
|
41095
|
+
] }),
|
|
41096
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { style: { display: "flex", gap: 2, flexDirection: "column" }, children: [
|
|
41097
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41098
|
+
"div",
|
|
41099
|
+
{
|
|
41100
|
+
style: {
|
|
41101
|
+
width: 3,
|
|
41102
|
+
height: 3,
|
|
41103
|
+
borderRadius: 3,
|
|
41104
|
+
background: "#9CA0A7"
|
|
41105
|
+
}
|
|
41106
|
+
}
|
|
41107
|
+
),
|
|
41108
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41109
|
+
"div",
|
|
41110
|
+
{
|
|
41111
|
+
style: {
|
|
41112
|
+
width: 3,
|
|
41113
|
+
height: 3,
|
|
41114
|
+
borderRadius: 3,
|
|
41115
|
+
background: "#9CA0A7"
|
|
41116
|
+
}
|
|
41117
|
+
}
|
|
41118
|
+
),
|
|
41119
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41120
|
+
"div",
|
|
41121
|
+
{
|
|
41122
|
+
style: {
|
|
41123
|
+
width: 3,
|
|
41124
|
+
height: 3,
|
|
41125
|
+
borderRadius: 3,
|
|
41126
|
+
background: "#9CA0A7"
|
|
41127
|
+
}
|
|
41128
|
+
}
|
|
41129
|
+
)
|
|
41130
|
+
] })
|
|
41131
|
+
]
|
|
41132
|
+
}
|
|
41133
|
+
),
|
|
41134
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { style: { flex: 1, display: "flex", gap: 12 }, children: [
|
|
41135
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41136
|
+
SelectComponent,
|
|
41137
|
+
{
|
|
41138
|
+
value: column.field,
|
|
41139
|
+
onChange: (e) => handleChange(e.target.value, "columns.field", index),
|
|
41140
|
+
options: rows[0] ? Object.keys(rows[0]).map((elem) => ({
|
|
41141
|
+
label: elem,
|
|
41142
|
+
value: elem
|
|
41143
|
+
})) : columns.map((elem) => ({
|
|
41144
|
+
label: elem.field,
|
|
41145
|
+
value: elem.field
|
|
41146
|
+
})),
|
|
41147
|
+
width: 200,
|
|
41148
|
+
hideEmptyOption: true
|
|
41149
|
+
}
|
|
41150
|
+
),
|
|
41151
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41152
|
+
TextInputComponent,
|
|
41153
|
+
{
|
|
41154
|
+
id: `chart-builder-column-label-${index}`,
|
|
41155
|
+
width: 200,
|
|
41156
|
+
value: column.label,
|
|
41157
|
+
placeholder: "Column Label",
|
|
41158
|
+
onChange: (e) => handleChange(e.target.value, "columns.label", index)
|
|
41159
|
+
}
|
|
41160
|
+
),
|
|
41161
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41162
|
+
SelectComponent,
|
|
41163
|
+
{
|
|
41164
|
+
value: column.format,
|
|
41165
|
+
onChange: (e) => handleChange(e.target.value, "columns.format", index),
|
|
41166
|
+
options: ALL_FORMAT_OPTIONS,
|
|
41167
|
+
width: 200,
|
|
41168
|
+
hideEmptyOption: true
|
|
41169
|
+
}
|
|
41170
|
+
),
|
|
41171
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { ref: deleteRef, style: { marginLeft: deleteButtonMargin }, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
41172
|
+
DeleteButtonComponent,
|
|
41173
|
+
{
|
|
41174
|
+
onClick: () => handleRemoveField("columns", index)
|
|
41175
|
+
}
|
|
41176
|
+
) })
|
|
41177
|
+
] })
|
|
41178
|
+
]
|
|
41179
|
+
}
|
|
41180
|
+
) });
|
|
41181
|
+
}
|
|
42185
41182
|
function getPivotMetricOptions(pivot, selectedPivotTable, chartType) {
|
|
42186
41183
|
if (["metric", "gauge"].includes(chartType) && selectedPivotTable) {
|
|
42187
41184
|
return selectedPivotTable.columns.map((elem) => ({
|
|
@@ -42390,7 +41387,6 @@ function ChartBuilder({
|
|
|
42390
41387
|
}, [reportId]);
|
|
42391
41388
|
const [windowWidth, setWindowWidth] = (0, import_react43.useState)(1200);
|
|
42392
41389
|
const [rows, setRows] = (0, import_react43.useState)(report?.rows ?? []);
|
|
42393
|
-
const [itemQuery, setItemQuery] = (0, import_react43.useState)(report?.itemQuery);
|
|
42394
41390
|
const [rowCount, setRowCount] = (0, import_react43.useState)(report?.rowCount ?? 0);
|
|
42395
41391
|
const [maxPage, setMaxPage] = (0, import_react43.useState)(0);
|
|
42396
41392
|
const [isLoading, setIsLoading] = (0, import_react43.useState)(false);
|
|
@@ -43120,7 +42116,7 @@ function ChartBuilder({
|
|
|
43120
42116
|
pivot,
|
|
43121
42117
|
dateBucket,
|
|
43122
42118
|
dateFilter,
|
|
43123
|
-
report: report ? { ...report, ...tableInfo
|
|
42119
|
+
report: report ? { ...report, ...tableInfo } : void 0,
|
|
43124
42120
|
client,
|
|
43125
42121
|
uniqueValues,
|
|
43126
42122
|
dashboardName: destinationDashboardName,
|
|
@@ -43281,7 +42277,6 @@ function ChartBuilder({
|
|
|
43281
42277
|
setCurrentProcessing(processing);
|
|
43282
42278
|
setRows(tableInfo.rows);
|
|
43283
42279
|
setProcessedColumns(processColumns(tableInfo.columns));
|
|
43284
|
-
setItemQuery(tableInfo.itemQuery);
|
|
43285
42280
|
fetchRowCount(processing, overrideFilters);
|
|
43286
42281
|
if (formData.pivot) {
|
|
43287
42282
|
try {
|
|
@@ -43647,6 +42642,26 @@ function ChartBuilder({
|
|
|
43647
42642
|
);
|
|
43648
42643
|
setFormData({ ...formData, [fieldName]: updatedArray });
|
|
43649
42644
|
};
|
|
42645
|
+
const columnDragSensors = (0, import_core.useSensors)(
|
|
42646
|
+
(0, import_core.useSensor)(import_core.PointerSensor),
|
|
42647
|
+
(0, import_core.useSensor)(import_core.KeyboardSensor, {
|
|
42648
|
+
coordinateGetter: import_sortable.sortableKeyboardCoordinates
|
|
42649
|
+
})
|
|
42650
|
+
);
|
|
42651
|
+
const handleColumnDragEnd = (event) => {
|
|
42652
|
+
const { active, over } = event;
|
|
42653
|
+
if (!active || !over) return;
|
|
42654
|
+
if (active.id !== over.id) {
|
|
42655
|
+
const oldIndex = formData.columns.findIndex(
|
|
42656
|
+
(col) => col.field === active.id
|
|
42657
|
+
);
|
|
42658
|
+
const newIndex = formData.columns.findIndex(
|
|
42659
|
+
(col) => col.field === over.id
|
|
42660
|
+
);
|
|
42661
|
+
const newColumns = (0, import_sortable.arrayMove)(formData.columns, oldIndex, newIndex);
|
|
42662
|
+
setFormData({ ...formData, columns: newColumns });
|
|
42663
|
+
}
|
|
42664
|
+
};
|
|
43650
42665
|
const handleSubmit = (event) => {
|
|
43651
42666
|
event.preventDefault();
|
|
43652
42667
|
};
|
|
@@ -44167,7 +43182,7 @@ function ChartBuilder({
|
|
|
44167
43182
|
uniqueValuesIsLoading: initialUniqueValuesIsLoading,
|
|
44168
43183
|
initialSelectedPivotTable: selectedPivotTable,
|
|
44169
43184
|
pivotRecommendationsEnabled,
|
|
44170
|
-
report
|
|
43185
|
+
report,
|
|
44171
43186
|
dashboardName: destinationDashboardName || "",
|
|
44172
43187
|
dateFilter: filtersEnabled ? currentDashboardFilters?.find(
|
|
44173
43188
|
(f) => f.filterType === "date_range"
|
|
@@ -44555,141 +43570,98 @@ function ChartBuilder({
|
|
|
44555
43570
|
formData.pivot && selectedPivotTable && selectedPivotTable.columns && formData.chartType === "table" ? (
|
|
44556
43571
|
// THIS CASE IF FOR PIVOT TABLES ONLY
|
|
44557
43572
|
selectedPivotTable.columns.map(
|
|
44558
|
-
(column, index) => /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
44559
|
-
|
|
44560
|
-
|
|
44561
|
-
|
|
44562
|
-
|
|
44563
|
-
|
|
44564
|
-
|
|
44565
|
-
|
|
44566
|
-
|
|
44567
|
-
e.target.value,
|
|
44568
|
-
"pivot.field",
|
|
44569
|
-
index
|
|
44570
|
-
),
|
|
44571
|
-
options: selectedPivotTable.columns.map(
|
|
44572
|
-
(elem) => ({
|
|
44573
|
-
label: elem.field,
|
|
44574
|
-
value: elem.field
|
|
44575
|
-
})
|
|
44576
|
-
),
|
|
44577
|
-
disabled: index === 0,
|
|
44578
|
-
width: 200,
|
|
44579
|
-
hideEmptyOption: true
|
|
44580
|
-
}
|
|
43573
|
+
(column, index) => /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(ChartBuilderInputRowContainer, { children: [
|
|
43574
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
43575
|
+
SelectComponent,
|
|
43576
|
+
{
|
|
43577
|
+
value: column.field,
|
|
43578
|
+
onChange: (e) => handleChange(
|
|
43579
|
+
e.target.value,
|
|
43580
|
+
"pivot.field",
|
|
43581
|
+
index
|
|
44581
43582
|
),
|
|
44582
|
-
|
|
44583
|
-
|
|
44584
|
-
|
|
44585
|
-
|
|
44586
|
-
|
|
44587
|
-
value: column.label,
|
|
44588
|
-
placeholder: "Column Label",
|
|
44589
|
-
onChange: (e) => handleChange(
|
|
44590
|
-
e.target.value,
|
|
44591
|
-
"pivot.label",
|
|
44592
|
-
index
|
|
44593
|
-
)
|
|
44594
|
-
}
|
|
43583
|
+
options: selectedPivotTable.columns.map(
|
|
43584
|
+
(elem) => ({
|
|
43585
|
+
label: elem.field,
|
|
43586
|
+
value: elem.field
|
|
43587
|
+
})
|
|
44595
43588
|
),
|
|
44596
|
-
|
|
44597
|
-
|
|
44598
|
-
|
|
44599
|
-
|
|
44600
|
-
|
|
44601
|
-
|
|
44602
|
-
|
|
44603
|
-
|
|
44604
|
-
|
|
44605
|
-
|
|
44606
|
-
|
|
44607
|
-
|
|
44608
|
-
|
|
44609
|
-
|
|
44610
|
-
|
|
44611
|
-
|
|
44612
|
-
{ label: "string", value: "string" }
|
|
44613
|
-
],
|
|
44614
|
-
width: 200,
|
|
44615
|
-
hideEmptyOption: true
|
|
44616
|
-
}
|
|
43589
|
+
disabled: index === 0,
|
|
43590
|
+
width: 200,
|
|
43591
|
+
hideEmptyOption: true
|
|
43592
|
+
}
|
|
43593
|
+
),
|
|
43594
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
43595
|
+
TextInputComponent,
|
|
43596
|
+
{
|
|
43597
|
+
id: `chart-builder-column-label-${index}`,
|
|
43598
|
+
width: 200,
|
|
43599
|
+
value: column.label,
|
|
43600
|
+
placeholder: "Column Label",
|
|
43601
|
+
onChange: (e) => handleChange(
|
|
43602
|
+
e.target.value,
|
|
43603
|
+
"pivot.label",
|
|
43604
|
+
index
|
|
44617
43605
|
)
|
|
44618
|
-
|
|
44619
|
-
|
|
44620
|
-
|
|
44621
|
-
|
|
43606
|
+
}
|
|
43607
|
+
),
|
|
43608
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
43609
|
+
SelectComponent,
|
|
43610
|
+
{
|
|
43611
|
+
value: (
|
|
43612
|
+
// The first index use rowField for the rest of them use value fields
|
|
43613
|
+
column.format
|
|
43614
|
+
),
|
|
43615
|
+
onChange: (e) => handleChange(
|
|
43616
|
+
e.target.value,
|
|
43617
|
+
"pivot.format",
|
|
43618
|
+
index
|
|
43619
|
+
),
|
|
43620
|
+
options: formData.pivot && index === 0 && selectedPivotTable?.columns.length > 1 ? isDateField(
|
|
43621
|
+
formData.pivot.rowFieldType || ""
|
|
43622
|
+
) ? [{ label: "date", value: "string" }] : [{ label: "string", value: "string" }] : [
|
|
43623
|
+
...NUMBER_OPTIONS,
|
|
43624
|
+
{ label: "string", value: "string" }
|
|
43625
|
+
],
|
|
43626
|
+
width: 200,
|
|
43627
|
+
hideEmptyOption: true
|
|
43628
|
+
}
|
|
43629
|
+
)
|
|
43630
|
+
] }, "column" + index)
|
|
44622
43631
|
)
|
|
44623
|
-
) :
|
|
44624
|
-
|
|
44625
|
-
|
|
44626
|
-
|
|
44627
|
-
|
|
44628
|
-
|
|
44629
|
-
|
|
44630
|
-
|
|
44631
|
-
|
|
44632
|
-
|
|
44633
|
-
|
|
44634
|
-
|
|
44635
|
-
|
|
44636
|
-
|
|
44637
|
-
|
|
44638
|
-
|
|
44639
|
-
|
|
44640
|
-
|
|
44641
|
-
|
|
44642
|
-
|
|
44643
|
-
|
|
44644
|
-
|
|
44645
|
-
|
|
44646
|
-
|
|
44647
|
-
|
|
44648
|
-
|
|
44649
|
-
|
|
44650
|
-
|
|
44651
|
-
|
|
44652
|
-
width: 200,
|
|
44653
|
-
value: column.label,
|
|
44654
|
-
placeholder: "Column Label",
|
|
44655
|
-
onChange: (e) => handleChange(
|
|
44656
|
-
e.target.value,
|
|
44657
|
-
"columns.label",
|
|
44658
|
-
index
|
|
44659
|
-
)
|
|
44660
|
-
}
|
|
44661
|
-
),
|
|
44662
|
-
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
44663
|
-
SelectComponent,
|
|
44664
|
-
{
|
|
44665
|
-
value: column.format,
|
|
44666
|
-
onChange: (e) => handleChange(
|
|
44667
|
-
e.target.value,
|
|
44668
|
-
"columns.format",
|
|
44669
|
-
index
|
|
44670
|
-
),
|
|
44671
|
-
options: ALL_FORMAT_OPTIONS,
|
|
44672
|
-
width: 200,
|
|
44673
|
-
hideEmptyOption: true
|
|
44674
|
-
}
|
|
44675
|
-
),
|
|
44676
|
-
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
44677
|
-
"div",
|
|
44678
|
-
{
|
|
44679
|
-
ref: deleteRef,
|
|
44680
|
-
style: { marginLeft: deleteButtonMargin },
|
|
44681
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
44682
|
-
DeleteButtonComponent,
|
|
44683
|
-
{
|
|
44684
|
-
onClick: () => handleRemoveField("columns", index)
|
|
44685
|
-
}
|
|
44686
|
-
)
|
|
44687
|
-
}
|
|
43632
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
43633
|
+
import_core.DndContext,
|
|
43634
|
+
{
|
|
43635
|
+
sensors: columnDragSensors,
|
|
43636
|
+
collisionDetection: import_core.closestCenter,
|
|
43637
|
+
onDragEnd: handleColumnDragEnd,
|
|
43638
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
43639
|
+
import_sortable.SortableContext,
|
|
43640
|
+
{
|
|
43641
|
+
items: formData.columns.map((col) => col.field),
|
|
43642
|
+
strategy: import_sortable.verticalListSortingStrategy,
|
|
43643
|
+
children: formData.columns.map(
|
|
43644
|
+
(column, index) => /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
|
|
43645
|
+
SortableColumnItem,
|
|
43646
|
+
{
|
|
43647
|
+
column,
|
|
43648
|
+
index,
|
|
43649
|
+
rows,
|
|
43650
|
+
columns,
|
|
43651
|
+
handleChange,
|
|
43652
|
+
deleteRef,
|
|
43653
|
+
deleteButtonMargin,
|
|
43654
|
+
handleRemoveField,
|
|
43655
|
+
SelectComponent,
|
|
43656
|
+
TextInputComponent,
|
|
43657
|
+
DeleteButtonComponent
|
|
43658
|
+
},
|
|
43659
|
+
column.field
|
|
43660
|
+
)
|
|
44688
43661
|
)
|
|
44689
|
-
|
|
44690
|
-
|
|
44691
|
-
|
|
44692
|
-
)
|
|
43662
|
+
}
|
|
43663
|
+
)
|
|
43664
|
+
}
|
|
44693
43665
|
),
|
|
44694
43666
|
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { children: !// hide when pivoted and chartType === 'table'
|
|
44695
43667
|
(formData.pivot && selectedPivotTable && selectedPivotTable.columns && formData.chartType === "table") && /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
@@ -48858,9 +47830,9 @@ var useReportBuilder = ({
|
|
|
48858
47830
|
|
|
48859
47831
|
// src/components/ReportBuilder/AddColumnModal.tsx
|
|
48860
47832
|
var import_react48 = require("react");
|
|
48861
|
-
var
|
|
48862
|
-
var
|
|
48863
|
-
var
|
|
47833
|
+
var import_core2 = require("@dnd-kit/core");
|
|
47834
|
+
var import_sortable2 = require("@dnd-kit/sortable");
|
|
47835
|
+
var import_utilities2 = require("@dnd-kit/utilities");
|
|
48864
47836
|
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
48865
47837
|
function AddColumnModal({
|
|
48866
47838
|
onSave,
|
|
@@ -48929,10 +47901,10 @@ function AddColumnModal({
|
|
|
48929
47901
|
setTimeout(() => setInitialLoad(false), 200);
|
|
48930
47902
|
}
|
|
48931
47903
|
}, [schemaLoading]);
|
|
48932
|
-
const sensors = (0,
|
|
48933
|
-
(0,
|
|
48934
|
-
(0,
|
|
48935
|
-
coordinateGetter:
|
|
47904
|
+
const sensors = (0, import_core2.useSensors)(
|
|
47905
|
+
(0, import_core2.useSensor)(import_core2.PointerSensor),
|
|
47906
|
+
(0, import_core2.useSensor)(import_core2.KeyboardSensor, {
|
|
47907
|
+
coordinateGetter: import_sortable2.sortableKeyboardCoordinates
|
|
48936
47908
|
})
|
|
48937
47909
|
);
|
|
48938
47910
|
function handleDragEnd(event) {
|
|
@@ -48942,7 +47914,7 @@ function AddColumnModal({
|
|
|
48942
47914
|
setOrderedColumnNames((orderedColumnNames2) => {
|
|
48943
47915
|
const oldIndex = orderedColumnNames2.indexOf(active.id);
|
|
48944
47916
|
const newIndex = orderedColumnNames2.indexOf(over.id);
|
|
48945
|
-
return (0,
|
|
47917
|
+
return (0, import_sortable2.arrayMove)(orderedColumnNames2, oldIndex, newIndex);
|
|
48946
47918
|
});
|
|
48947
47919
|
}
|
|
48948
47920
|
}
|
|
@@ -48986,16 +47958,16 @@ function AddColumnModal({
|
|
|
48986
47958
|
}
|
|
48987
47959
|
),
|
|
48988
47960
|
schemaLoading || initialLoad ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(LoadingComponent, {}) : schema.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
48989
|
-
|
|
47961
|
+
import_core2.DndContext,
|
|
48990
47962
|
{
|
|
48991
47963
|
sensors,
|
|
48992
|
-
collisionDetection:
|
|
47964
|
+
collisionDetection: import_core2.closestCenter,
|
|
48993
47965
|
onDragEnd: handleDragEnd,
|
|
48994
47966
|
children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
48995
|
-
|
|
47967
|
+
import_sortable2.SortableContext,
|
|
48996
47968
|
{
|
|
48997
47969
|
items: orderedColumnNames,
|
|
48998
|
-
strategy:
|
|
47970
|
+
strategy: import_sortable2.verticalListSortingStrategy,
|
|
48999
47971
|
children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
|
|
49000
47972
|
"div",
|
|
49001
47973
|
{
|
|
@@ -49203,9 +48175,9 @@ var SortableItem = ({
|
|
|
49203
48175
|
selectedColumns,
|
|
49204
48176
|
SelectColumn
|
|
49205
48177
|
}) => {
|
|
49206
|
-
const { attributes, listeners, setNodeRef, transform, transition: transition2 } = (0,
|
|
48178
|
+
const { attributes, listeners, setNodeRef, transform, transition: transition2 } = (0, import_sortable2.useSortable)({ id: id2 });
|
|
49207
48179
|
const style2 = {
|
|
49208
|
-
transform:
|
|
48180
|
+
transform: import_utilities2.CSS.Transform.toString(transform),
|
|
49209
48181
|
transition: transition2
|
|
49210
48182
|
};
|
|
49211
48183
|
const handleSelect = () => {
|
|
@@ -49234,11 +48206,11 @@ var SortableItem = ({
|
|
|
49234
48206
|
};
|
|
49235
48207
|
|
|
49236
48208
|
// src/components/ReportBuilder/DraggableColumns.tsx
|
|
49237
|
-
var
|
|
48209
|
+
var import_core3 = require("@dnd-kit/core");
|
|
49238
48210
|
|
|
49239
48211
|
// src/components/ReportBuilder/DraggableItem.tsx
|
|
49240
|
-
var
|
|
49241
|
-
var
|
|
48212
|
+
var import_sortable3 = require("@dnd-kit/sortable");
|
|
48213
|
+
var import_utilities3 = require("@dnd-kit/utilities");
|
|
49242
48214
|
var import_jsx_runtime68 = require("react/jsx-runtime");
|
|
49243
48215
|
function DraggableItem({
|
|
49244
48216
|
id: id2,
|
|
@@ -49247,9 +48219,9 @@ function DraggableItem({
|
|
|
49247
48219
|
DraggableColumnComponent,
|
|
49248
48220
|
loading
|
|
49249
48221
|
}) {
|
|
49250
|
-
const { attributes, listeners, setNodeRef, transform, transition: transition2 } = (0,
|
|
48222
|
+
const { attributes, listeners, setNodeRef, transform, transition: transition2 } = (0, import_sortable3.useSortable)({ id: id2 });
|
|
49251
48223
|
const style2 = {
|
|
49252
|
-
transform:
|
|
48224
|
+
transform: import_utilities3.CSS.Transform.toString(transform),
|
|
49253
48225
|
transition: transition2
|
|
49254
48226
|
};
|
|
49255
48227
|
return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { style: { ...style2 }, ref: setNodeRef, children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
|
|
@@ -49274,7 +48246,7 @@ function DraggableItem({
|
|
|
49274
48246
|
}
|
|
49275
48247
|
|
|
49276
48248
|
// src/components/ReportBuilder/DraggableColumns.tsx
|
|
49277
|
-
var
|
|
48249
|
+
var import_sortable4 = require("@dnd-kit/sortable");
|
|
49278
48250
|
var import_react49 = require("react");
|
|
49279
48251
|
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
49280
48252
|
function DraggableColumns({
|
|
@@ -49283,10 +48255,10 @@ function DraggableColumns({
|
|
|
49283
48255
|
DraggableColumnComponent,
|
|
49284
48256
|
loading
|
|
49285
48257
|
}) {
|
|
49286
|
-
const sensors = (0,
|
|
49287
|
-
(0,
|
|
49288
|
-
(0,
|
|
49289
|
-
coordinateGetter:
|
|
48258
|
+
const sensors = (0, import_core3.useSensors)(
|
|
48259
|
+
(0, import_core3.useSensor)(import_core3.PointerSensor),
|
|
48260
|
+
(0, import_core3.useSensor)(import_core3.KeyboardSensor, {
|
|
48261
|
+
coordinateGetter: import_sortable4.sortableKeyboardCoordinates
|
|
49290
48262
|
})
|
|
49291
48263
|
);
|
|
49292
48264
|
const columnNames = (0, import_react49.useMemo)(() => {
|
|
@@ -49303,7 +48275,7 @@ function DraggableColumns({
|
|
|
49303
48275
|
if (active.id !== over.id) {
|
|
49304
48276
|
const oldIndex = columnNames.findIndex((c) => c.endsWith(active.id));
|
|
49305
48277
|
const newIndex = columnNames.findIndex((c) => c.endsWith(over.id));
|
|
49306
|
-
const newOrder = (0,
|
|
48278
|
+
const newOrder = (0, import_sortable4.arrayMove)(columnNames, oldIndex, newIndex);
|
|
49307
48279
|
const orderToColumns = newOrder.map((name2) => {
|
|
49308
48280
|
const [table, field] = name2.split(".");
|
|
49309
48281
|
return columns.find(
|
|
@@ -49320,16 +48292,16 @@ function DraggableColumns({
|
|
|
49320
48292
|
onColumnOrderChange(newColumns);
|
|
49321
48293
|
}
|
|
49322
48294
|
return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
49323
|
-
|
|
48295
|
+
import_core3.DndContext,
|
|
49324
48296
|
{
|
|
49325
48297
|
sensors,
|
|
49326
|
-
collisionDetection:
|
|
48298
|
+
collisionDetection: import_core3.closestCenter,
|
|
49327
48299
|
onDragEnd: handleDragEnd,
|
|
49328
48300
|
children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
|
|
49329
|
-
|
|
48301
|
+
import_sortable4.SortableContext,
|
|
49330
48302
|
{
|
|
49331
48303
|
items: columnNames,
|
|
49332
|
-
strategy:
|
|
48304
|
+
strategy: import_sortable4.verticalListSortingStrategy,
|
|
49333
48305
|
children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
|
|
49334
48306
|
"div",
|
|
49335
48307
|
{
|