@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.js
CHANGED
|
@@ -14787,21 +14787,6 @@ function isDateFormat(xAxisFormat) {
|
|
|
14787
14787
|
const isDate = DATE_FORMATS.includes(xAxisFormat);
|
|
14788
14788
|
return isDate;
|
|
14789
14789
|
}
|
|
14790
|
-
function getComparisonInterval(comparisonRange, dateBucket) {
|
|
14791
|
-
const dayCount = differenceInDays2(
|
|
14792
|
-
comparisonRange.endDate,
|
|
14793
|
-
comparisonRange.startDate
|
|
14794
|
-
);
|
|
14795
|
-
if (!isNaN(dayCount)) {
|
|
14796
|
-
if (dateBucket === "month") {
|
|
14797
|
-
return Math.floor(dayCount / 30) + " month";
|
|
14798
|
-
} else if (dateBucket === "year") {
|
|
14799
|
-
return Math.floor(dayCount / 365) + " year";
|
|
14800
|
-
} else {
|
|
14801
|
-
return dayCount + " day";
|
|
14802
|
-
}
|
|
14803
|
-
}
|
|
14804
|
-
}
|
|
14805
14790
|
function getDateBucketFromRange(dateRange) {
|
|
14806
14791
|
const difference = differenceInDays2(dateRange.end, dateRange.start);
|
|
14807
14792
|
if (difference < 14) {
|
|
@@ -16615,311 +16600,765 @@ function parseValueFromBigQueryDates(rows, columns) {
|
|
|
16615
16600
|
});
|
|
16616
16601
|
}
|
|
16617
16602
|
|
|
16618
|
-
// src/utils/
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
|
|
16624
|
-
|
|
16625
|
-
|
|
16626
|
-
|
|
16627
|
-
|
|
16628
|
-
|
|
16629
|
-
|
|
16630
|
-
|
|
16631
|
-
|
|
16632
|
-
|
|
16633
|
-
|
|
16634
|
-
|
|
16635
|
-
|
|
16636
|
-
|
|
16603
|
+
// src/utils/pivotConstructor.ts
|
|
16604
|
+
async function generatePivotWithSQL({
|
|
16605
|
+
pivot,
|
|
16606
|
+
report,
|
|
16607
|
+
client,
|
|
16608
|
+
dateBucket,
|
|
16609
|
+
dateFilter,
|
|
16610
|
+
distinctStrings,
|
|
16611
|
+
dashboardName,
|
|
16612
|
+
tenants,
|
|
16613
|
+
additionalProcessing,
|
|
16614
|
+
pivotQuery,
|
|
16615
|
+
comparisonPivotQuery,
|
|
16616
|
+
getPivotRowCount = true,
|
|
16617
|
+
caller,
|
|
16618
|
+
getToken
|
|
16619
|
+
}) {
|
|
16620
|
+
const databaseType = client.databaseType || "postgresql";
|
|
16621
|
+
if (!pivot.aggregations?.length && pivot.aggregationType) {
|
|
16622
|
+
pivot.aggregations = [
|
|
16623
|
+
{
|
|
16624
|
+
aggregationType: pivot.aggregationType,
|
|
16625
|
+
valueField: pivot.valueField,
|
|
16626
|
+
valueFieldType: pivot.valueFieldType,
|
|
16627
|
+
valueField2: pivot.valueField2,
|
|
16628
|
+
valueField2Type: pivot.valueField2Type
|
|
16637
16629
|
}
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16630
|
+
];
|
|
16631
|
+
}
|
|
16632
|
+
const pivotConfig = {
|
|
16633
|
+
rowField: pivot.rowField,
|
|
16634
|
+
rowFieldType: pivot.rowFieldType,
|
|
16635
|
+
columnField: pivot.columnField,
|
|
16636
|
+
aggregations: pivot.aggregations?.map((agg) => ({
|
|
16637
|
+
aggregationType: agg.aggregationType,
|
|
16638
|
+
valueField: agg.valueField,
|
|
16639
|
+
valueFieldType: agg.valueFieldType
|
|
16640
|
+
}))
|
|
16641
|
+
};
|
|
16642
|
+
const resp = await quillFetch({
|
|
16643
|
+
client,
|
|
16644
|
+
task: "pivot-template",
|
|
16645
|
+
metadata: {
|
|
16646
|
+
clientId: client.clientId,
|
|
16647
|
+
pivot: pivotConfig,
|
|
16648
|
+
itemQuery: report?.queryString,
|
|
16649
|
+
dashboardName,
|
|
16650
|
+
tenants
|
|
16651
|
+
},
|
|
16652
|
+
credentials: "same-origin",
|
|
16653
|
+
getToken
|
|
16641
16654
|
});
|
|
16642
|
-
|
|
16643
|
-
|
|
16644
|
-
function dateAdder(date, interval2) {
|
|
16645
|
-
const match = interval2.match(/^(\d+)\s+(day|month|year)$/);
|
|
16646
|
-
if (!match) {
|
|
16647
|
-
throw new Error(`Invalid interval format: ${interval2}`);
|
|
16655
|
+
if (resp.data?.success === false) {
|
|
16656
|
+
throw resp.data.errorMessage;
|
|
16648
16657
|
}
|
|
16649
|
-
const
|
|
16650
|
-
|
|
16651
|
-
|
|
16658
|
+
const queryResponseRows = resp.data?.rows || resp.queries?.queryResults?.[0]?.rows || [];
|
|
16659
|
+
const queryResponseFields = resp.data?.fields || resp.queries?.queryResults?.[0]?.fields || [];
|
|
16660
|
+
const rowCount = resp.queries?.queryResults?.[1]?.rows?.[0]?.row_count || 0;
|
|
16661
|
+
parseValueFromBigQueryDates(queryResponseRows, queryResponseFields);
|
|
16662
|
+
const responseRows = queryResponseRows;
|
|
16663
|
+
const responseFields = queryResponseFields;
|
|
16664
|
+
const rows = pivot.rowField ? responseRows.map(
|
|
16665
|
+
(row) => !row[pivot.rowField] ? { ...row, [pivot.rowField]: "-" } : row
|
|
16666
|
+
) : responseRows;
|
|
16667
|
+
if (pivot.columnField && client.databaseType?.toLowerCase() === "bigquery") {
|
|
16668
|
+
rows.forEach((row) => {
|
|
16669
|
+
Object.keys(row).forEach((key) => {
|
|
16670
|
+
const processedKey = processColumnName(key);
|
|
16671
|
+
if (processedKey !== key) {
|
|
16672
|
+
row[processedKey] = row[key];
|
|
16673
|
+
delete row[key];
|
|
16674
|
+
}
|
|
16675
|
+
});
|
|
16676
|
+
});
|
|
16652
16677
|
}
|
|
16653
|
-
const
|
|
16654
|
-
|
|
16655
|
-
|
|
16656
|
-
|
|
16657
|
-
|
|
16658
|
-
|
|
16659
|
-
|
|
16660
|
-
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
|
|
16678
|
+
const columns = responseFields?.map((field) => ({
|
|
16679
|
+
field: processColumnName(field.field || field.name),
|
|
16680
|
+
label: snakeCaseToTitleCase(
|
|
16681
|
+
processColumnName(
|
|
16682
|
+
(field.field || field.name).replace("comparison_", "comparison ")
|
|
16683
|
+
)
|
|
16684
|
+
),
|
|
16685
|
+
format: (field.field || field.name) === pivot.rowField ? "string" : pivot.aggregations?.find(
|
|
16686
|
+
(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")
|
|
16687
|
+
)?.aggregationType === "percentage" ? "percent" : "whole_number",
|
|
16688
|
+
fieldType: field.fieldType,
|
|
16689
|
+
jsType: field.jsType,
|
|
16690
|
+
dataTypeID: field.dataTypeID
|
|
16691
|
+
})).filter(
|
|
16692
|
+
(field, index) => field.field !== "comparison_" + pivot.rowField || index === 0
|
|
16693
|
+
).sort((a, b) => {
|
|
16694
|
+
if (a.field === pivot.rowField) {
|
|
16695
|
+
return -1;
|
|
16696
|
+
}
|
|
16697
|
+
if (b.field === pivot.rowField) {
|
|
16698
|
+
return 1;
|
|
16699
|
+
}
|
|
16700
|
+
return 0;
|
|
16701
|
+
});
|
|
16702
|
+
if (pivot.rowField && !isStringType(pivot.rowFieldType || "")) {
|
|
16703
|
+
rows.forEach((row) => {
|
|
16704
|
+
row.__quillRawDate = typeof row[pivot.rowField || ""] === "object" ? row[pivot.rowField || ""].value : row[pivot.rowField || ""];
|
|
16705
|
+
let value = typeof row[pivot.rowField || ""] === "object" ? row[pivot.rowField || ""].value : row[pivot.rowField || ""];
|
|
16706
|
+
if (dateBucket === "week" && dateFilter?.startDate && dateFilter?.endDate) {
|
|
16707
|
+
const rowDate = new Date(value);
|
|
16708
|
+
if (rowDate < dateFilter.startDate) {
|
|
16709
|
+
value = dateFilter.startDate.toISOString();
|
|
16710
|
+
} else if (rowDate > dateFilter.endDate) {
|
|
16711
|
+
value = dateFilter.endDate.toISOString();
|
|
16712
|
+
}
|
|
16713
|
+
}
|
|
16714
|
+
const dateString = getDateString(
|
|
16715
|
+
value,
|
|
16716
|
+
dateFilter?.startDate && dateFilter?.endDate ? { start: dateFilter.startDate, end: dateFilter.endDate } : void 0,
|
|
16717
|
+
dateBucket,
|
|
16718
|
+
databaseType
|
|
16719
|
+
);
|
|
16720
|
+
row[pivot.rowField || ""] = dateString;
|
|
16721
|
+
});
|
|
16722
|
+
if (pivot.rowField && pivot.rowFieldType && !isStringType(pivot.rowFieldType) && dateFilter?.startDate && dateFilter?.endDate) {
|
|
16723
|
+
const dateSet = new Set(
|
|
16724
|
+
rows.map((row) => row[pivot.rowField || ""])
|
|
16725
|
+
);
|
|
16726
|
+
for (let date = dateFilter.startDate; date <= dateFilter.endDate; date = new Date(date.getTime() + 24 * 60 * 60 * 1e3)) {
|
|
16727
|
+
const formattedDate = getDateString(
|
|
16728
|
+
date.toISOString(),
|
|
16729
|
+
{ start: dateFilter.startDate, end: dateFilter.endDate },
|
|
16730
|
+
dateBucket,
|
|
16731
|
+
databaseType
|
|
16732
|
+
);
|
|
16733
|
+
if (!dateSet.has(formattedDate)) {
|
|
16734
|
+
const newRow = {};
|
|
16735
|
+
newRow[pivot.rowField] = formattedDate;
|
|
16736
|
+
newRow.__quillRawDate = date.toISOString();
|
|
16737
|
+
rows.push(newRow);
|
|
16738
|
+
dateSet.add(formattedDate);
|
|
16739
|
+
}
|
|
16740
|
+
}
|
|
16741
|
+
}
|
|
16742
|
+
if (!pivot.sort) {
|
|
16743
|
+
rows.sort((a, b) => {
|
|
16744
|
+
if (a.__quillRawDate < b.__quillRawDate) {
|
|
16745
|
+
return -1;
|
|
16746
|
+
}
|
|
16747
|
+
if (a.__quillRawDate > b.__quillRawDate) {
|
|
16748
|
+
return 1;
|
|
16749
|
+
}
|
|
16750
|
+
return 0;
|
|
16751
|
+
});
|
|
16752
|
+
}
|
|
16664
16753
|
}
|
|
16754
|
+
columns?.forEach((column, index) => {
|
|
16755
|
+
if (column.label && ["null", "undefined"].includes(column.label.toLowerCase()) && !pivot.columnField && !pivot.aggregations?.[index]?.valueField && pivot.aggregations?.[index]?.aggregationType === "count") {
|
|
16756
|
+
column.label = "Count";
|
|
16757
|
+
}
|
|
16758
|
+
});
|
|
16759
|
+
const numericColumns = columns?.filter(
|
|
16760
|
+
(column) => column.format === "whole_number" || column.format === "percentage"
|
|
16761
|
+
);
|
|
16762
|
+
rows.forEach((row) => {
|
|
16763
|
+
numericColumns?.forEach((column) => {
|
|
16764
|
+
row[column.field] = row[column.field] ?? 0;
|
|
16765
|
+
});
|
|
16766
|
+
});
|
|
16767
|
+
return {
|
|
16768
|
+
rows,
|
|
16769
|
+
columns: columns ?? [],
|
|
16770
|
+
rowCount: rowCount || rows.length,
|
|
16771
|
+
pivotQuery: report?.queryString || "",
|
|
16772
|
+
comparisonPivotQuery: comparisonPivotQuery || ""
|
|
16773
|
+
};
|
|
16665
16774
|
}
|
|
16666
|
-
function
|
|
16667
|
-
|
|
16668
|
-
|
|
16669
|
-
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16674
|
-
|
|
16675
|
-
case "day":
|
|
16676
|
-
return startOfDay3(zonedDate);
|
|
16677
|
-
case "year":
|
|
16678
|
-
return startOfYear(zonedDate);
|
|
16679
|
-
default:
|
|
16680
|
-
throw new Error(`Unsupported granularity: ${granularity}`);
|
|
16775
|
+
function generatePivotTableYAxis(pivot, cols, yAxisField) {
|
|
16776
|
+
if (pivot?.aggregationType === "count") {
|
|
16777
|
+
return [
|
|
16778
|
+
{
|
|
16779
|
+
field: pivot.valueField ?? "count",
|
|
16780
|
+
label: yAxisField.label,
|
|
16781
|
+
format: yAxisField.format
|
|
16782
|
+
}
|
|
16783
|
+
];
|
|
16681
16784
|
}
|
|
16785
|
+
return [
|
|
16786
|
+
{
|
|
16787
|
+
field: pivot.valueField ?? "count",
|
|
16788
|
+
label: yAxisField.label,
|
|
16789
|
+
format: yAxisField.format
|
|
16790
|
+
}
|
|
16791
|
+
];
|
|
16682
16792
|
}
|
|
16683
|
-
function
|
|
16684
|
-
pivot
|
|
16685
|
-
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
|
|
16690
|
-
|
|
16793
|
+
function generatePivotTitle(pivot) {
|
|
16794
|
+
if (pivot.rowField && !pivot.valueField && pivot.aggregations?.[0]) {
|
|
16795
|
+
return snakeAndCamelCaseToTitleCase(
|
|
16796
|
+
`${pivot.aggregations[0].aggregationType} of ${pivot.rowField}${pivot.columnField ? ` by ${pivot.columnField}` : ""}
|
|
16797
|
+
`
|
|
16798
|
+
);
|
|
16799
|
+
} else if (!pivot.rowField && pivot.aggregations?.[0]?.valueField) {
|
|
16800
|
+
return snakeAndCamelCaseToTitleCase(
|
|
16801
|
+
`${pivot.aggregations[0].aggregationType} of ${pivot.aggregations[0].valueField}
|
|
16802
|
+
`
|
|
16803
|
+
);
|
|
16804
|
+
}
|
|
16805
|
+
return snakeAndCamelCaseToTitleCase(
|
|
16806
|
+
`${pivot.aggregations?.[0]?.aggregationType ?? "Aggregation"} of ${pivot.aggregations?.[0]?.valueField ?? "value"}${pivot.rowField ? ` by ${pivot.rowField}` : ""}${pivot.columnField ? ` and ${pivot.columnField}` : ""}`
|
|
16807
|
+
);
|
|
16691
16808
|
}
|
|
16692
|
-
function
|
|
16809
|
+
async function generatePivotTable({
|
|
16693
16810
|
pivot,
|
|
16694
|
-
rows,
|
|
16695
|
-
compRows,
|
|
16696
|
-
databaseType,
|
|
16697
16811
|
dateBucket,
|
|
16698
|
-
|
|
16699
|
-
|
|
16812
|
+
dateFilter,
|
|
16813
|
+
report,
|
|
16814
|
+
client,
|
|
16815
|
+
getToken,
|
|
16816
|
+
eventTracking,
|
|
16817
|
+
uniqueValues,
|
|
16818
|
+
dashboardName,
|
|
16819
|
+
tenants,
|
|
16820
|
+
additionalProcessing,
|
|
16821
|
+
caller,
|
|
16822
|
+
pivotQuery
|
|
16700
16823
|
}) {
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
|
|
16707
|
-
|
|
16708
|
-
|
|
16709
|
-
|
|
16710
|
-
|
|
16711
|
-
|
|
16712
|
-
|
|
16713
|
-
|
|
16714
|
-
|
|
16715
|
-
|
|
16716
|
-
|
|
16717
|
-
|
|
16718
|
-
|
|
16719
|
-
|
|
16720
|
-
|
|
16721
|
-
|
|
16824
|
+
try {
|
|
16825
|
+
if (report && client) {
|
|
16826
|
+
const pivotTable = await generatePivotWithSQL({
|
|
16827
|
+
pivotQuery,
|
|
16828
|
+
pivot,
|
|
16829
|
+
report,
|
|
16830
|
+
client,
|
|
16831
|
+
dateBucket,
|
|
16832
|
+
dateFilter,
|
|
16833
|
+
dashboardName,
|
|
16834
|
+
tenants,
|
|
16835
|
+
additionalProcessing,
|
|
16836
|
+
caller,
|
|
16837
|
+
getToken
|
|
16838
|
+
});
|
|
16839
|
+
return pivotTable;
|
|
16840
|
+
}
|
|
16841
|
+
} catch (e) {
|
|
16842
|
+
eventTracking?.logError?.({
|
|
16843
|
+
type: "bug",
|
|
16844
|
+
// TODO: determine type
|
|
16845
|
+
severity: "high",
|
|
16846
|
+
message: "Error generating pivot table",
|
|
16847
|
+
errorMessage: e.message,
|
|
16848
|
+
errorStack: e.stack,
|
|
16849
|
+
errorData: {
|
|
16850
|
+
caller: "PivotModal",
|
|
16851
|
+
function: "generatePivotTable"
|
|
16852
|
+
}
|
|
16853
|
+
});
|
|
16854
|
+
throw Error(`Failed to generate pivot table with SQL: ${e}`);
|
|
16722
16855
|
}
|
|
16723
|
-
|
|
16856
|
+
throw Error("Failed to generate pivot table: invalid report");
|
|
16724
16857
|
}
|
|
16725
|
-
|
|
16726
|
-
|
|
16727
|
-
|
|
16728
|
-
|
|
16729
|
-
|
|
16730
|
-
|
|
16858
|
+
|
|
16859
|
+
// src/utils/paginationProcessing.ts
|
|
16860
|
+
var DEFAULT_PAGINATION = {
|
|
16861
|
+
page: 0,
|
|
16862
|
+
rowsPerPage: 10,
|
|
16863
|
+
rowsPerRequest: 600
|
|
16864
|
+
};
|
|
16865
|
+
var DEFAULT_TABLE_PAGINATION = {
|
|
16866
|
+
page: 0,
|
|
16867
|
+
rowsPerPage: 10,
|
|
16868
|
+
rowsPerRequest: 50
|
|
16869
|
+
};
|
|
16870
|
+
function shouldFetchMore(pagination, page, maxPage, currentRowCount) {
|
|
16871
|
+
if (!pagination || currentRowCount && currentRowCount >= pagination.rowsPerPage * (page + 1)) {
|
|
16872
|
+
return false;
|
|
16731
16873
|
}
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
-
comparisonInterval
|
|
16874
|
+
const indexAdjustedPage = page;
|
|
16875
|
+
const pageInterval = Math.floor(
|
|
16876
|
+
indexAdjustedPage * pagination.rowsPerPage / pagination.rowsPerRequest
|
|
16877
|
+
);
|
|
16878
|
+
const indexAdjustedPreviousPage = maxPage;
|
|
16879
|
+
const previousPageInterval = Math.floor(
|
|
16880
|
+
indexAdjustedPreviousPage * pagination.rowsPerPage / pagination.rowsPerRequest
|
|
16740
16881
|
);
|
|
16882
|
+
return pageInterval > previousPageInterval;
|
|
16741
16883
|
}
|
|
16742
|
-
function
|
|
16743
|
-
if (!
|
|
16744
|
-
return
|
|
16884
|
+
function shouldSortInMemory(pagination, rowCount) {
|
|
16885
|
+
if (!rowCount || rowCount < pagination.rowsPerRequest) {
|
|
16886
|
+
return true;
|
|
16745
16887
|
}
|
|
16746
|
-
return
|
|
16747
|
-
const matchingCompRow = compRows.find(
|
|
16748
|
-
(compRow) => compRow[pivot.rowField] === row[pivot.rowField]
|
|
16749
|
-
);
|
|
16750
|
-
const comparisonFields = columnFieldValues.reduce(
|
|
16751
|
-
(acc, fieldValue) => {
|
|
16752
|
-
acc[`comparison_${fieldValue}`] = matchingCompRow ? matchingCompRow[fieldValue] || null : null;
|
|
16753
|
-
return acc;
|
|
16754
|
-
},
|
|
16755
|
-
{}
|
|
16756
|
-
);
|
|
16757
|
-
return {
|
|
16758
|
-
...row,
|
|
16759
|
-
...comparisonFields
|
|
16760
|
-
};
|
|
16761
|
-
});
|
|
16888
|
+
return false;
|
|
16762
16889
|
}
|
|
16763
|
-
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
|
|
16769
|
-
|
|
16770
|
-
|
|
16771
|
-
|
|
16772
|
-
|
|
16773
|
-
|
|
16774
|
-
|
|
16775
|
-
|
|
16776
|
-
|
|
16777
|
-
|
|
16778
|
-
|
|
16779
|
-
|
|
16780
|
-
|
|
16781
|
-
|
|
16782
|
-
|
|
16783
|
-
|
|
16784
|
-
|
|
16785
|
-
|
|
16786
|
-
|
|
16787
|
-
|
|
16788
|
-
|
|
16890
|
+
|
|
16891
|
+
// src/utils/dashboard.ts
|
|
16892
|
+
var defaultDashboardItem = {
|
|
16893
|
+
id: "",
|
|
16894
|
+
name: "",
|
|
16895
|
+
dashboardName: "",
|
|
16896
|
+
rows: [],
|
|
16897
|
+
compareRows: [],
|
|
16898
|
+
columns: [],
|
|
16899
|
+
chartType: "",
|
|
16900
|
+
pivot: null,
|
|
16901
|
+
yAxisFields: [],
|
|
16902
|
+
xAxisLabel: "",
|
|
16903
|
+
xAxisField: "",
|
|
16904
|
+
xAxisFormat: "string",
|
|
16905
|
+
order: -1,
|
|
16906
|
+
filtersApplied: [],
|
|
16907
|
+
queryString: "",
|
|
16908
|
+
rowCount: 0,
|
|
16909
|
+
columnInternal: []
|
|
16910
|
+
};
|
|
16911
|
+
async function cleanDashboardItem({
|
|
16912
|
+
item,
|
|
16913
|
+
dashboardFilters,
|
|
16914
|
+
getToken,
|
|
16915
|
+
eventTracking,
|
|
16916
|
+
client,
|
|
16917
|
+
dateBucket,
|
|
16918
|
+
additionalProcessing,
|
|
16919
|
+
customFields,
|
|
16920
|
+
skipPivotFetch,
|
|
16921
|
+
tenants
|
|
16922
|
+
}) {
|
|
16923
|
+
if (!item) return defaultDashboardItem;
|
|
16924
|
+
if (!item.rows) {
|
|
16789
16925
|
return {
|
|
16790
|
-
...
|
|
16791
|
-
|
|
16926
|
+
...defaultDashboardItem,
|
|
16927
|
+
id: item._id,
|
|
16928
|
+
name: item.name
|
|
16792
16929
|
};
|
|
16793
|
-
});
|
|
16794
|
-
}
|
|
16795
|
-
function merge1DPivotRows(pivot, rows, compRows, databaseType, dateBucket, comparisonInterval) {
|
|
16796
|
-
if (isStringType(pivot.rowFieldType || "") || !pivot.rowFieldType) {
|
|
16797
|
-
return merge1DStringPivotRows(pivot, rows, compRows);
|
|
16798
16930
|
}
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16803
|
-
|
|
16804
|
-
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
|
|
16810
|
-
|
|
16931
|
+
const fields = item.fields || [];
|
|
16932
|
+
const columnsWithCustomFields = [...item.columns ?? []];
|
|
16933
|
+
if (item.includeCustomFields && item.rows?.length > 0) {
|
|
16934
|
+
const tables = item.referencedTables ?? [];
|
|
16935
|
+
tables.forEach((table) => {
|
|
16936
|
+
const _customFields = customFields?.[table] ?? [];
|
|
16937
|
+
_customFields.forEach((field) => {
|
|
16938
|
+
const isJsonCustomField = !!field.refColumn;
|
|
16939
|
+
if (item.rows[0][field.field] !== void 0 && !item.columns.some((col) => col.field === field.field)) {
|
|
16940
|
+
const result_field = fields.find((f) => f.name === field.field);
|
|
16941
|
+
const converted_field = convertPostgresColumn(result_field ?? {});
|
|
16942
|
+
columnsWithCustomFields.push({
|
|
16943
|
+
field: field.field,
|
|
16944
|
+
format: converted_field.format,
|
|
16945
|
+
label: snakeAndCamelCaseToTitleCase(field.field),
|
|
16946
|
+
fieldType: converted_field.fieldType,
|
|
16947
|
+
dataTypeID: converted_field.dataTypeID,
|
|
16948
|
+
jsType: converted_field.jsType,
|
|
16949
|
+
inferFormat: isJsonCustomField
|
|
16950
|
+
});
|
|
16951
|
+
}
|
|
16952
|
+
});
|
|
16953
|
+
});
|
|
16811
16954
|
}
|
|
16812
|
-
|
|
16813
|
-
|
|
16814
|
-
(compRow) => compRow[pivot.rowField] === row[pivot.rowField]
|
|
16815
|
-
);
|
|
16816
|
-
let aggregationSuffix = "";
|
|
16817
|
-
if (matchingCompRow && pivot.aggregationType === "percentage") {
|
|
16818
|
-
if (matchingCompRow[`${pivot.valueField}_Percentage`]) {
|
|
16819
|
-
aggregationSuffix = "_Percentage";
|
|
16820
|
-
} else if (matchingCompRow[`${pivot.valueField}_PERCENTAGE`]) {
|
|
16821
|
-
aggregationSuffix = "_PERCENTAGE";
|
|
16822
|
-
} else {
|
|
16823
|
-
aggregationSuffix = "_percentage";
|
|
16824
|
-
}
|
|
16825
|
-
}
|
|
16826
|
-
return {
|
|
16827
|
-
...row,
|
|
16828
|
-
[`comparison_${pivot.valueField}${aggregationSuffix}`]: matchingCompRow ? matchingCompRow[`${pivot.valueField}${aggregationSuffix}`] : null
|
|
16829
|
-
};
|
|
16955
|
+
const processedColumns = item.columns.map((col) => {
|
|
16956
|
+
return { ...col, label: snakeAndCamelCaseToTitleCase(col.label) };
|
|
16830
16957
|
});
|
|
16831
|
-
|
|
16832
|
-
|
|
16833
|
-
|
|
16834
|
-
return rows;
|
|
16835
|
-
}
|
|
16836
|
-
return rows.map((row) => {
|
|
16837
|
-
const rowDate = typeof row[pivot.rowField] === "string" ? new Date(row[pivot.rowField]) : row[pivot.rowField];
|
|
16838
|
-
const truncatedRowDate = dateTrunc(rowDate, dateBucket, databaseType);
|
|
16839
|
-
const matchingCompRow = compRows.find((compRow) => {
|
|
16840
|
-
const comparisonDateWithInterval = dateAdder(
|
|
16841
|
-
compRow[`${pivot.rowField}`],
|
|
16842
|
-
comparisonInterval
|
|
16843
|
-
);
|
|
16844
|
-
const truncatedCompRowDate = dateTrunc(
|
|
16845
|
-
comparisonDateWithInterval,
|
|
16846
|
-
dateBucket,
|
|
16847
|
-
databaseType
|
|
16848
|
-
);
|
|
16849
|
-
return truncatedRowDate.toISOString() === truncatedCompRowDate.toISOString();
|
|
16850
|
-
});
|
|
16851
|
-
let aggregationSuffix = "";
|
|
16852
|
-
if (matchingCompRow && pivot.aggregationType === "percentage") {
|
|
16853
|
-
if (matchingCompRow[`${pivot.valueField}_Percentage`]) {
|
|
16854
|
-
aggregationSuffix = "_Percentage";
|
|
16855
|
-
} else if (matchingCompRow[`${pivot.valueField}_PERCENTAGE`]) {
|
|
16856
|
-
aggregationSuffix = "_PERCENTAGE";
|
|
16857
|
-
} else {
|
|
16858
|
-
aggregationSuffix = "_percentage";
|
|
16859
|
-
}
|
|
16860
|
-
}
|
|
16958
|
+
const columnInternal = (item.includeCustomFields ? columnsWithCustomFields : item.columns).map((col) => {
|
|
16959
|
+
const field = item.fields?.find((f) => f.name === col.field);
|
|
16960
|
+
const converted_field = convertPostgresColumn(field ?? {});
|
|
16861
16961
|
return {
|
|
16862
|
-
|
|
16863
|
-
|
|
16962
|
+
fieldType: converted_field.fieldType,
|
|
16963
|
+
dataTypeID: converted_field.dataTypeID,
|
|
16964
|
+
jsType: converted_field.jsType,
|
|
16965
|
+
...col,
|
|
16966
|
+
label: snakeAndCamelCaseToTitleCase(col.label)
|
|
16864
16967
|
};
|
|
16865
16968
|
});
|
|
16866
|
-
|
|
16867
|
-
|
|
16868
|
-
|
|
16869
|
-
|
|
16870
|
-
|
|
16871
|
-
|
|
16872
|
-
|
|
16873
|
-
|
|
16874
|
-
|
|
16875
|
-
|
|
16876
|
-
|
|
16969
|
+
let pivotTable;
|
|
16970
|
+
let pivotError;
|
|
16971
|
+
try {
|
|
16972
|
+
const shouldPaginatePivotAsTable = item.chartType === "table";
|
|
16973
|
+
const pivotChartProcessing = {
|
|
16974
|
+
page: DEFAULT_PAGINATION
|
|
16975
|
+
};
|
|
16976
|
+
pivotTable = await getPivotTable(
|
|
16977
|
+
{
|
|
16978
|
+
...item,
|
|
16979
|
+
pivot: item.pivot && !skipPivotFetch ? {
|
|
16980
|
+
...item.pivot,
|
|
16981
|
+
aggregations: item.pivot.aggregations ?? [
|
|
16982
|
+
{
|
|
16983
|
+
valueField: item.pivot.valueField,
|
|
16984
|
+
valueFieldType: item.pivot.valueFieldType,
|
|
16985
|
+
valueField2: item.pivot.valueField2,
|
|
16986
|
+
valueField2Type: item.pivot.valueField2Type,
|
|
16987
|
+
aggregationType: item.pivot.aggregationType
|
|
16988
|
+
}
|
|
16989
|
+
]
|
|
16990
|
+
} : void 0
|
|
16991
|
+
},
|
|
16992
|
+
dashboardFilters,
|
|
16993
|
+
item.dashboardName,
|
|
16994
|
+
getToken,
|
|
16995
|
+
client,
|
|
16996
|
+
eventTracking,
|
|
16997
|
+
dateBucket,
|
|
16998
|
+
shouldPaginatePivotAsTable ? additionalProcessing : pivotChartProcessing,
|
|
16999
|
+
tenants,
|
|
17000
|
+
customFields
|
|
17001
|
+
);
|
|
17002
|
+
} catch (e) {
|
|
17003
|
+
pivotTable = void 0;
|
|
17004
|
+
eventTracking?.logError?.({
|
|
17005
|
+
type: "bug",
|
|
17006
|
+
// TODO: determine type
|
|
17007
|
+
severity: "high",
|
|
17008
|
+
message: "Error fetching pivot table",
|
|
17009
|
+
errorMessage: e.message,
|
|
17010
|
+
errorStack: e.stack,
|
|
17011
|
+
errorData: {
|
|
17012
|
+
caller: "cleanDashboardItem",
|
|
17013
|
+
function: "cleanDashboardItem"
|
|
16877
17014
|
}
|
|
17015
|
+
});
|
|
17016
|
+
console.error("Error fetching pivot table", e);
|
|
17017
|
+
pivotError = "Error fetching pivot table";
|
|
17018
|
+
}
|
|
17019
|
+
const referenceLineYValues = [];
|
|
17020
|
+
for (const key in item) {
|
|
17021
|
+
if (key.startsWith("referenceLine_")) {
|
|
17022
|
+
const field = key.slice(14);
|
|
17023
|
+
if (!item[key] || !item[key][0]) continue;
|
|
17024
|
+
const value = Object.values(item[key][0])[0];
|
|
17025
|
+
referenceLineYValues.push({ label: field, query: [value, value] });
|
|
16878
17026
|
}
|
|
16879
|
-
const compRow = {
|
|
16880
|
-
[`comparison_${pivot.valueField}${aggregationSuffix}`]: compRows[i]?.[`${pivot.valueField}${aggregationSuffix}`]
|
|
16881
|
-
};
|
|
16882
|
-
return { ...row, ...compRow };
|
|
16883
|
-
});
|
|
16884
|
-
}
|
|
16885
|
-
|
|
16886
|
-
// src/utils/queryConstructor.ts
|
|
16887
|
-
function processSingleQuotes(value, databaseType) {
|
|
16888
|
-
if (["postgresql", "snowflake", "clickhouse"].includes(
|
|
16889
|
-
databaseType.toLowerCase()
|
|
16890
|
-
)) {
|
|
16891
|
-
return value.replaceAll("'", "''");
|
|
16892
17027
|
}
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16897
|
-
|
|
16898
|
-
|
|
16899
|
-
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
|
|
16904
|
-
|
|
16905
|
-
|
|
16906
|
-
|
|
16907
|
-
return fallbackOnNull ? `"${fallbackOnNull}"` : `"_"`;
|
|
16908
|
-
}
|
|
16909
|
-
if (isColumnFieldAlias) {
|
|
16910
|
-
return `"${column.replaceAll('"', "")}"`;
|
|
16911
|
-
}
|
|
16912
|
-
const columnParts = column.split(".");
|
|
16913
|
-
if (columnParts.length > 1) {
|
|
16914
|
-
return `"` + columnParts.map((part) => part.replaceAll('"', "")).join('"."') + `"`;
|
|
17028
|
+
if (item.referenceLines) {
|
|
17029
|
+
for (const referenceLine of item.referenceLines) {
|
|
17030
|
+
if (Array.isArray(referenceLine.query)) {
|
|
17031
|
+
referenceLineYValues.push({
|
|
17032
|
+
label: referenceLine.label,
|
|
17033
|
+
query: referenceLine.query
|
|
17034
|
+
});
|
|
17035
|
+
} else if (referenceLine.query === "") {
|
|
17036
|
+
referenceLineYValues.push({
|
|
17037
|
+
label: referenceLine.label,
|
|
17038
|
+
query: (pivotTable?.rows ? pivotTable.rows : item.rows).map(
|
|
17039
|
+
(row) => Number(row[referenceLine.label]) || 0
|
|
17040
|
+
)
|
|
17041
|
+
});
|
|
16915
17042
|
}
|
|
16916
|
-
return `"${column.replaceAll('"', "")}"`;
|
|
16917
17043
|
}
|
|
16918
|
-
|
|
16919
|
-
|
|
16920
|
-
|
|
16921
|
-
|
|
16922
|
-
|
|
17044
|
+
}
|
|
17045
|
+
return {
|
|
17046
|
+
id: item._id ?? item.id,
|
|
17047
|
+
name: item.name,
|
|
17048
|
+
dashboardName: item.dashboardName,
|
|
17049
|
+
// section: item.section,
|
|
17050
|
+
rows: item.rows,
|
|
17051
|
+
pivotRows: pivotTable ? pivotTable.rows : void 0,
|
|
17052
|
+
pivotColumns: pivotTable ? pivotTable.columns : void 0,
|
|
17053
|
+
compareRows: item.compareRows,
|
|
17054
|
+
columns: processedColumns.map((column) => {
|
|
17055
|
+
return {
|
|
17056
|
+
field: column.field,
|
|
17057
|
+
format: column.format,
|
|
17058
|
+
label: column.label,
|
|
17059
|
+
inferFormat: column.inferFormat
|
|
17060
|
+
};
|
|
17061
|
+
}),
|
|
17062
|
+
includeCustomFields: item.includeCustomFields,
|
|
17063
|
+
columnInternal,
|
|
17064
|
+
columnsWithCustomFields,
|
|
17065
|
+
chartType: item.chartType,
|
|
17066
|
+
dateField: item.dateField,
|
|
17067
|
+
pivot: pivotError ? void 0 : item.pivot ? {
|
|
17068
|
+
...item.pivot,
|
|
17069
|
+
aggregations: item.pivot.aggregations ?? [
|
|
17070
|
+
{
|
|
17071
|
+
valueField: item.pivot.valueField,
|
|
17072
|
+
valueFieldType: item.pivot.valueFieldType,
|
|
17073
|
+
valueField2: item.pivot.valueField2,
|
|
17074
|
+
valueField2Type: item.pivot.valueField2Type,
|
|
17075
|
+
aggregationType: item.pivot.aggregationType
|
|
17076
|
+
}
|
|
17077
|
+
],
|
|
17078
|
+
columnValues: item.distinctStrings
|
|
17079
|
+
} : void 0,
|
|
17080
|
+
yAxisFields: pivotTable ? extractPivotedYAxis(pivotTable, item) : item.yAxisFields,
|
|
17081
|
+
xAxisLabel: item.xAxisLabel,
|
|
17082
|
+
xAxisField: item.xAxisField,
|
|
17083
|
+
xAxisFormat: item.xAxisFormat,
|
|
17084
|
+
order: item.order,
|
|
17085
|
+
filtersApplied: item.filtersApplied,
|
|
17086
|
+
filterMap: item.filterMap,
|
|
17087
|
+
flags: item.flags,
|
|
17088
|
+
rowCount: item.rowCount ? parseInt(item.rowCount) : item.rows.length,
|
|
17089
|
+
pivotRowCount: pivotTable ? pivotTable.rowCount : void 0,
|
|
17090
|
+
template: item.template,
|
|
17091
|
+
sort: item.sort,
|
|
17092
|
+
itemQuery: item.itemQuery,
|
|
17093
|
+
queryString: item.queryString,
|
|
17094
|
+
pivotQuery: pivotTable?.pivotQuery,
|
|
17095
|
+
comparisonPivotQuery: pivotTable?.comparisonPivotQuery,
|
|
17096
|
+
referencedTables: item?.referencedTables || [],
|
|
17097
|
+
referencedColumns: item?.referencedColumns || {},
|
|
17098
|
+
error: item.error ?? pivotError,
|
|
17099
|
+
referenceLineYValues,
|
|
17100
|
+
referenceLines: item.referenceLines
|
|
17101
|
+
};
|
|
17102
|
+
}
|
|
17103
|
+
async function getPivotTable(report, dashboardFilters, dashboardName, getToken, client, eventTracking, dateBucketInitial, additionalProcessing, tenants, customFields) {
|
|
17104
|
+
if (!report) return void 0;
|
|
17105
|
+
const dateFilter = Object.values(dashboardFilters ?? {}).find(
|
|
17106
|
+
(filter) => filter.filterType === "date_range" || filter.operator === "BETWEEN"
|
|
17107
|
+
);
|
|
17108
|
+
if (dateFilter?.operator === "BETWEEN") {
|
|
17109
|
+
dateFilter.startDate = dateFilter.value[0];
|
|
17110
|
+
dateFilter.endDate = dateFilter.value[1];
|
|
17111
|
+
}
|
|
17112
|
+
const pivot = report?.pivot;
|
|
17113
|
+
const data = report || {};
|
|
17114
|
+
if (pivot && client) {
|
|
17115
|
+
if (report.rowCount === 0 || report.rows.length === 0) {
|
|
17116
|
+
const columns = [];
|
|
17117
|
+
if (pivot.rowField) {
|
|
17118
|
+
columns.push({
|
|
17119
|
+
field: pivot.rowField,
|
|
17120
|
+
label: snakeCaseToTitleCase(processColumnName(pivot.rowField)),
|
|
17121
|
+
format: pivot.rowFieldType || "string",
|
|
17122
|
+
jsType: convertFieldTypeToJSType(pivot.rowFieldType || "string"),
|
|
17123
|
+
fieldType: pivot.rowFieldType || "string",
|
|
17124
|
+
dataTypeID: fieldTypeToDataTypeID(pivot.rowFieldType || "string")
|
|
17125
|
+
});
|
|
17126
|
+
}
|
|
17127
|
+
for (const agg of pivot.aggregations ?? []) {
|
|
17128
|
+
if (agg.valueField) {
|
|
17129
|
+
columns.push({
|
|
17130
|
+
field: agg.valueField,
|
|
17131
|
+
label: snakeCaseToTitleCase(processColumnName(agg.valueField)),
|
|
17132
|
+
//FIXME: valueFieldType is not always the same as the format
|
|
17133
|
+
format: agg.valueFieldType ?? "whole_number",
|
|
17134
|
+
jsType: agg.valueFieldType ?? "number",
|
|
17135
|
+
fieldType: agg.valueFieldType ?? "number",
|
|
17136
|
+
dataTypeID: fieldTypeToDataTypeID(agg.valueFieldType ?? "number")
|
|
17137
|
+
});
|
|
17138
|
+
}
|
|
17139
|
+
}
|
|
17140
|
+
return {
|
|
17141
|
+
rows: [],
|
|
17142
|
+
rowCount: 0,
|
|
17143
|
+
pivotQuery: report.queryString ?? "",
|
|
17144
|
+
columns
|
|
17145
|
+
};
|
|
17146
|
+
}
|
|
17147
|
+
try {
|
|
17148
|
+
let dateBucket = dateBucketInitial;
|
|
17149
|
+
let filterDateRange = void 0;
|
|
17150
|
+
if (dateFilter && dateFilter.startDate && dateFilter.endDate) {
|
|
17151
|
+
filterDateRange = {
|
|
17152
|
+
start: dateFilter.startDate,
|
|
17153
|
+
end: dateFilter.endDate
|
|
17154
|
+
};
|
|
17155
|
+
} else if (report.dateRange) {
|
|
17156
|
+
filterDateRange = report.dateRange;
|
|
17157
|
+
}
|
|
17158
|
+
if (!dateBucket && filterDateRange) {
|
|
17159
|
+
dateBucket = getDateBucketFromRange(filterDateRange);
|
|
17160
|
+
}
|
|
17161
|
+
const pivotTable = await generatePivotWithSQL({
|
|
17162
|
+
pivot,
|
|
17163
|
+
report,
|
|
17164
|
+
client,
|
|
17165
|
+
dateBucket,
|
|
17166
|
+
dateFilter,
|
|
17167
|
+
dashboardName,
|
|
17168
|
+
tenants,
|
|
17169
|
+
additionalProcessing,
|
|
17170
|
+
getToken
|
|
17171
|
+
});
|
|
17172
|
+
return pivotTable;
|
|
17173
|
+
} catch (e) {
|
|
17174
|
+
eventTracking?.logError?.({
|
|
17175
|
+
type: "bug",
|
|
17176
|
+
// TODO: determine type
|
|
17177
|
+
severity: "high",
|
|
17178
|
+
message: "Error fetching pivot table",
|
|
17179
|
+
errorMessage: e.message,
|
|
17180
|
+
errorStack: e.stack,
|
|
17181
|
+
errorData: {
|
|
17182
|
+
caller: "getPivotTable",
|
|
17183
|
+
function: "getPivotTable"
|
|
17184
|
+
}
|
|
17185
|
+
});
|
|
17186
|
+
console.error("Error fetching pivot table", e);
|
|
17187
|
+
throw e;
|
|
17188
|
+
}
|
|
17189
|
+
}
|
|
17190
|
+
return pivot && data.rows ? generatePivotTable({
|
|
17191
|
+
pivot,
|
|
17192
|
+
report,
|
|
17193
|
+
client,
|
|
17194
|
+
uniqueValues: report.distinctStrings,
|
|
17195
|
+
dashboardName,
|
|
17196
|
+
tenants,
|
|
17197
|
+
dateFilter,
|
|
17198
|
+
additionalProcessing,
|
|
17199
|
+
getToken,
|
|
17200
|
+
eventTracking
|
|
17201
|
+
}) : void 0;
|
|
17202
|
+
}
|
|
17203
|
+
function extractPivotedYAxis(pivotTable, itemInfo, config = void 0) {
|
|
17204
|
+
if (!pivotTable) return itemInfo?.yAxisFields ?? [];
|
|
17205
|
+
const pivot = itemInfo?.pivot || config?.pivot;
|
|
17206
|
+
if (!pivot.columnField && !pivot.rowField) return itemInfo?.yAxisFields ?? [];
|
|
17207
|
+
const yAxisFields = config ? config.yAxisFields : itemInfo?.yAxisFields;
|
|
17208
|
+
return yAxisFields && yAxisFields.length > 0 ? generatePivotTableYAxis(pivot, pivotTable.columns, yAxisFields[0]) : yAxisFields;
|
|
17209
|
+
}
|
|
17210
|
+
async function getDashboard(dashboardName, client, getToken, tenants, flags) {
|
|
17211
|
+
const { data: resp } = await quillFetch({
|
|
17212
|
+
client,
|
|
17213
|
+
task: "dashboard",
|
|
17214
|
+
metadata: {
|
|
17215
|
+
name: dashboardName,
|
|
17216
|
+
clientId: client.publicKey,
|
|
17217
|
+
databaseType: client.databaseType,
|
|
17218
|
+
useNewNodeSql: true,
|
|
17219
|
+
tenants,
|
|
17220
|
+
flags
|
|
17221
|
+
},
|
|
17222
|
+
getToken
|
|
17223
|
+
});
|
|
17224
|
+
return {
|
|
17225
|
+
...resp,
|
|
17226
|
+
createdAt: resp.createdAt && new Date(resp.createdAt),
|
|
17227
|
+
dateFilter: resp.dateFilter ? {
|
|
17228
|
+
...resp.dateFilter,
|
|
17229
|
+
presetOptions: resp.dateFilter.presetOptions?.map(
|
|
17230
|
+
(preset) => ({
|
|
17231
|
+
...preset,
|
|
17232
|
+
loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
|
|
17233
|
+
loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
|
|
17234
|
+
})
|
|
17235
|
+
),
|
|
17236
|
+
defaultPresetRanges: resp.dateFilter.defaultPresetRanges?.map(
|
|
17237
|
+
(preset) => ({
|
|
17238
|
+
...preset,
|
|
17239
|
+
loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
|
|
17240
|
+
loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
|
|
17241
|
+
})
|
|
17242
|
+
)
|
|
17243
|
+
} : void 0
|
|
17244
|
+
};
|
|
17245
|
+
}
|
|
17246
|
+
|
|
17247
|
+
// src/utils/chartBuilder.ts
|
|
17248
|
+
var numberFormatOptions = [
|
|
17249
|
+
"whole_number",
|
|
17250
|
+
"one_decimal_place",
|
|
17251
|
+
"two_decimal_places",
|
|
17252
|
+
"dollar_amount",
|
|
17253
|
+
"dollar_cents",
|
|
17254
|
+
"percentage"
|
|
17255
|
+
];
|
|
17256
|
+
var dateFormatOptions = [
|
|
17257
|
+
"MMM_yyyy",
|
|
17258
|
+
"MMM_dd",
|
|
17259
|
+
"MMM_dd_yyyy",
|
|
17260
|
+
"MMM_dd_hh:mm_ap_pm",
|
|
17261
|
+
"hh_ap_pm",
|
|
17262
|
+
"date",
|
|
17263
|
+
"timestamptz"
|
|
17264
|
+
];
|
|
17265
|
+
var NUMBER_OPTIONS = [
|
|
17266
|
+
{ value: "whole_number", label: "whole number" },
|
|
17267
|
+
{ value: "one_decimal_place", label: "one decimal place" },
|
|
17268
|
+
{ value: "two_decimal_places", label: "two decimal places" },
|
|
17269
|
+
{ value: "dollar_amount", label: "dollar amount" },
|
|
17270
|
+
{ value: "dollar_cents", label: "dollar and cent amount" },
|
|
17271
|
+
{ value: "percent", label: "percentage" }
|
|
17272
|
+
];
|
|
17273
|
+
var DATE_OPTIONS = [
|
|
17274
|
+
{ value: "MMM_yyyy", label: "month" },
|
|
17275
|
+
{ value: "MMM_dd", label: "day" },
|
|
17276
|
+
{ value: "MMM_dd_yyyy", label: "day and year" },
|
|
17277
|
+
{ value: "MMM_dd_hh:mm_ap_pm", label: "day and time" },
|
|
17278
|
+
{ value: "hh_ap_pm", label: "hour" }
|
|
17279
|
+
];
|
|
17280
|
+
var ALL_FORMAT_OPTIONS = [
|
|
17281
|
+
...NUMBER_OPTIONS,
|
|
17282
|
+
...DATE_OPTIONS,
|
|
17283
|
+
{ value: "string", label: "string" }
|
|
17284
|
+
];
|
|
17285
|
+
function createInitialFormData(columns) {
|
|
17286
|
+
const firstNumberColumn = columns?.find(
|
|
17287
|
+
(col) => numberFormatOptions.includes(col.format)
|
|
17288
|
+
);
|
|
17289
|
+
const firstStringColumn = columns?.find(
|
|
17290
|
+
(col) => !numberFormatOptions.includes(col.format) && !dateFormatOptions.includes(col.format)
|
|
17291
|
+
);
|
|
17292
|
+
const firstDateColumn = columns?.find(
|
|
17293
|
+
(col) => dateFormatOptions.includes(col.format)
|
|
17294
|
+
);
|
|
17295
|
+
const xAxisField = firstStringColumn?.field || firstDateColumn?.field || firstNumberColumn?.field || columns?.[0]?.field || "";
|
|
17296
|
+
const xAxisFormat = firstStringColumn?.format || firstDateColumn?.format || firstNumberColumn?.format || columns?.[0]?.format || "string";
|
|
17297
|
+
const formEmptyState = {
|
|
17298
|
+
name: "",
|
|
17299
|
+
columns: columns.map((col) => {
|
|
17300
|
+
return { ...col, label: snakeAndCamelCaseToTitleCase(col.label) };
|
|
17301
|
+
}),
|
|
17302
|
+
xAxisField,
|
|
17303
|
+
xAxisFormat,
|
|
17304
|
+
yAxisFields: [
|
|
17305
|
+
{
|
|
17306
|
+
field: firstNumberColumn?.field || columns?.[0]?.field || "",
|
|
17307
|
+
label: "",
|
|
17308
|
+
format: firstNumberColumn?.format || columns?.[0]?.format || "string"
|
|
17309
|
+
}
|
|
17310
|
+
],
|
|
17311
|
+
xAxisLabel: "",
|
|
17312
|
+
chartType: firstNumberColumn ? "line" : "table",
|
|
17313
|
+
pivot: null,
|
|
17314
|
+
template: true,
|
|
17315
|
+
referenceLines: []
|
|
17316
|
+
};
|
|
17317
|
+
return formEmptyState;
|
|
17318
|
+
}
|
|
17319
|
+
|
|
17320
|
+
// src/utils/error.ts
|
|
17321
|
+
var DataLoadError = class extends Error {
|
|
17322
|
+
data;
|
|
17323
|
+
constructor(message, data) {
|
|
17324
|
+
super(message);
|
|
17325
|
+
this.name = "DataLoadError";
|
|
17326
|
+
this.data = data;
|
|
17327
|
+
}
|
|
17328
|
+
};
|
|
17329
|
+
|
|
17330
|
+
// src/utils/errorProcessing.ts
|
|
17331
|
+
function processFilterErrorList(resp) {
|
|
17332
|
+
if (!resp || !resp.filterErrorList || !Array.isArray(resp.filterErrorList)) {
|
|
17333
|
+
return;
|
|
17334
|
+
}
|
|
17335
|
+
}
|
|
17336
|
+
|
|
17337
|
+
// src/utils/queryConstructor.ts
|
|
17338
|
+
function replaceBigQuerySpecialCharacters(column) {
|
|
17339
|
+
return column.replaceAll("/", "quill_forward_slash");
|
|
17340
|
+
}
|
|
17341
|
+
function processColumnReference(column, databaseType, fallbackOnNull, isColumnFieldAlias, isValueFieldAlias) {
|
|
17342
|
+
switch (databaseType.toLowerCase()) {
|
|
17343
|
+
case "postgresql":
|
|
17344
|
+
case "clickhouse": {
|
|
17345
|
+
if (column === "") {
|
|
17346
|
+
return fallbackOnNull ? `"${fallbackOnNull}"` : `"_"`;
|
|
17347
|
+
}
|
|
17348
|
+
if (isColumnFieldAlias) {
|
|
17349
|
+
return `"${column.replaceAll('"', "")}"`;
|
|
17350
|
+
}
|
|
17351
|
+
const columnParts = column.split(".");
|
|
17352
|
+
if (columnParts.length > 1) {
|
|
17353
|
+
return `"` + columnParts.map((part) => part.replaceAll('"', "")).join('"."') + `"`;
|
|
17354
|
+
}
|
|
17355
|
+
return `"${column.replaceAll('"', "")}"`;
|
|
17356
|
+
}
|
|
17357
|
+
case "mysql": {
|
|
17358
|
+
if (column === "") {
|
|
17359
|
+
return fallbackOnNull ? `${fallbackOnNull}` : "_";
|
|
17360
|
+
}
|
|
17361
|
+
if (isColumnFieldAlias) {
|
|
16923
17362
|
return `\`${column.replaceAll(`\``, "").replaceAll(`"`, "")}\``;
|
|
16924
17363
|
}
|
|
16925
17364
|
const columnParts = column.split(".");
|
|
@@ -16987,51 +17426,6 @@ function processColumnReference(column, databaseType, fallbackOnNull, isColumnFi
|
|
|
16987
17426
|
function replaceSpacesWithUnderscores(column) {
|
|
16988
17427
|
return column.replaceAll(" ", "_");
|
|
16989
17428
|
}
|
|
16990
|
-
function processInterval(interval2, rowField, databaseType) {
|
|
16991
|
-
if (["postgresql", "snowflake", "clickhouse"].includes(
|
|
16992
|
-
databaseType.toLowerCase()
|
|
16993
|
-
)) {
|
|
16994
|
-
return `(${processColumnReference(rowField, databaseType)} + INTERVAL '${interval2}')`;
|
|
16995
|
-
} else if (databaseType.toLowerCase() === "mysql") {
|
|
16996
|
-
return `(${processColumnReference(rowField, databaseType)} + INTERVAL ${interval2})`;
|
|
16997
|
-
}
|
|
16998
|
-
return `TIMESTAMP_ADD(${processColumnReference(rowField, databaseType)}, INTERVAL ${interval2} )`;
|
|
16999
|
-
}
|
|
17000
|
-
function processDateTrunc(dateBucket, rowField, databaseType, comparisonInterval) {
|
|
17001
|
-
const dateField = comparisonInterval ? processInterval(comparisonInterval, rowField, databaseType) : processColumnReference(rowField, databaseType);
|
|
17002
|
-
if (["postgresql", "snowflake"].includes(databaseType.toLowerCase())) {
|
|
17003
|
-
return `date_trunc('${dateBucket}', ${dateField})`;
|
|
17004
|
-
}
|
|
17005
|
-
if (["clickhouse"].includes(databaseType.toLowerCase())) {
|
|
17006
|
-
return `dateTrunc('${dateBucket}', ${dateField})`;
|
|
17007
|
-
}
|
|
17008
|
-
if (["databricks"].includes(databaseType.toLowerCase())) {
|
|
17009
|
-
return `DATE_TRUNC('${dateBucket}', ${dateField})`;
|
|
17010
|
-
}
|
|
17011
|
-
if (["mysql"].includes(databaseType.toLowerCase())) {
|
|
17012
|
-
switch (dateBucket.toLowerCase()) {
|
|
17013
|
-
case "year":
|
|
17014
|
-
return `DATE_FORMAT(${dateField}, '%Y-01-01 00:00:00')`;
|
|
17015
|
-
case "month":
|
|
17016
|
-
return `DATE_FORMAT(${dateField}, '%Y-%m-01 00:00:00')`;
|
|
17017
|
-
case "week":
|
|
17018
|
-
return `DATE_FORMAT(${dateField}, '%Y-%U-1 00:00:00')`;
|
|
17019
|
-
case "day":
|
|
17020
|
-
default:
|
|
17021
|
-
return `DATE(${dateField})`;
|
|
17022
|
-
}
|
|
17023
|
-
}
|
|
17024
|
-
if (["mssql"].includes(databaseType.toLowerCase())) {
|
|
17025
|
-
return `DATETRUNC(${dateBucket}, ${dateField})`;
|
|
17026
|
-
}
|
|
17027
|
-
return `TIMESTAMP_TRUNC(${dateField}, ${dateBucket})`;
|
|
17028
|
-
}
|
|
17029
|
-
function processValueField(aggType, databaseType, valueField) {
|
|
17030
|
-
if (aggType === "min" || aggType === "max" || aggType?.toLowerCase() === "average")
|
|
17031
|
-
return `${processColumnReference(valueField, databaseType)} ELSE null`;
|
|
17032
|
-
if (aggType === "count") return `1 ELSE 0`;
|
|
17033
|
-
return valueField ? `${processColumnReference(valueField, databaseType)} ELSE 0` : `1 ELSE 0`;
|
|
17034
|
-
}
|
|
17035
17429
|
function generateCountQuery(fields, query, databaseType) {
|
|
17036
17430
|
let countQuery = [];
|
|
17037
17431
|
let cteQuery = `WITH querytable AS (${query.replace(";", "")}) `;
|
|
@@ -17150,1123 +17544,12 @@ function generateMinMaxDateRangeQueries(columnFields, query, databaseType) {
|
|
|
17150
17544
|
const distinctQueries = columnFields.map((field) => {
|
|
17151
17545
|
const wrappedField = ["postgresql", "clickhouse"].includes(
|
|
17152
17546
|
databaseType.toLowerCase()
|
|
17153
|
-
) ?
|
|
17154
|
-
return `SELECT '${field}' AS field, ${min2}(${wrappedField})${cast} AS min_range, ${max2}(${wrappedField})${cast} AS max_range FROM querytable`;
|
|
17547
|
+
) ? processColumnReference(field, databaseType) : field;
|
|
17548
|
+
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`;
|
|
17155
17549
|
});
|
|
17156
17550
|
const distinctQuery = distinctQueries.join(" UNION ALL ");
|
|
17157
17551
|
return `WITH querytable AS (${query.replace(";", "")}) ` + distinctQuery;
|
|
17158
17552
|
}
|
|
17159
|
-
function generatePivotQuery(pivot, itemQuery, databaseType, distinctStrings, dateBucket) {
|
|
17160
|
-
if (!isValidPivot(pivot).valid) {
|
|
17161
|
-
return void 0;
|
|
17162
|
-
}
|
|
17163
|
-
if (pivot.columnField && distinctStrings && distinctStrings.length > 0) {
|
|
17164
|
-
return create2DPivotQuery(
|
|
17165
|
-
pivot,
|
|
17166
|
-
itemQuery,
|
|
17167
|
-
databaseType,
|
|
17168
|
-
distinctStrings,
|
|
17169
|
-
dateBucket
|
|
17170
|
-
);
|
|
17171
|
-
}
|
|
17172
|
-
if (pivot.rowField) {
|
|
17173
|
-
return create1DPivotQuery(pivot, itemQuery, dateBucket, databaseType);
|
|
17174
|
-
}
|
|
17175
|
-
return createAggregationValuePivot(pivot, itemQuery, databaseType);
|
|
17176
|
-
}
|
|
17177
|
-
function create2DPivotQuery(pivot, itemQuery, databaseType, columnFieldValues, dateBucket) {
|
|
17178
|
-
if (!pivot || !pivot.columnField) {
|
|
17179
|
-
return void 0;
|
|
17180
|
-
}
|
|
17181
|
-
if (isStringType(pivot.rowFieldType ?? "") || !pivot.rowFieldType) {
|
|
17182
|
-
return create2DStringPivotQuery(
|
|
17183
|
-
pivot,
|
|
17184
|
-
itemQuery,
|
|
17185
|
-
columnFieldValues,
|
|
17186
|
-
databaseType
|
|
17187
|
-
);
|
|
17188
|
-
}
|
|
17189
|
-
return create2DDatePivotQuery(
|
|
17190
|
-
pivot,
|
|
17191
|
-
itemQuery,
|
|
17192
|
-
columnFieldValues,
|
|
17193
|
-
databaseType,
|
|
17194
|
-
dateBucket
|
|
17195
|
-
);
|
|
17196
|
-
}
|
|
17197
|
-
function create2DStringPivotQuery(pivot, itemQuery, columnFieldValues, databaseType) {
|
|
17198
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17199
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17200
|
-
);
|
|
17201
|
-
if (!isValidBaseQuery || !pivot.columnField || !pivot.rowField)
|
|
17202
|
-
return void 0;
|
|
17203
|
-
const rowField = pivot.rowField;
|
|
17204
|
-
if (!pivot.aggregations?.[0]?.valueField && pivot.aggregations?.[0]?.aggregationType !== "count" && !pivot.valueField && pivot.aggregationType !== "count")
|
|
17205
|
-
throw new Error("No value field provided for pivot");
|
|
17206
|
-
if (!pivot.aggregations?.[0]?.aggregationType && !pivot.aggregationType)
|
|
17207
|
-
throw new Error("No aggregation type provided for pivot");
|
|
17208
|
-
const columnField = pivot.columnField;
|
|
17209
|
-
const rowFieldAlias = processColumnReference(
|
|
17210
|
-
rowField,
|
|
17211
|
-
databaseType,
|
|
17212
|
-
void 0,
|
|
17213
|
-
false,
|
|
17214
|
-
true
|
|
17215
|
-
);
|
|
17216
|
-
const columnFieldAlias = processColumnReference(
|
|
17217
|
-
columnField,
|
|
17218
|
-
databaseType,
|
|
17219
|
-
void 0,
|
|
17220
|
-
false,
|
|
17221
|
-
true
|
|
17222
|
-
);
|
|
17223
|
-
let caseWhens = [];
|
|
17224
|
-
let valueAliases = [];
|
|
17225
|
-
const seenAggs = {};
|
|
17226
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17227
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17228
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17229
|
-
} else {
|
|
17230
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17231
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17232
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17233
|
-
};
|
|
17234
|
-
}
|
|
17235
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString();
|
|
17236
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17237
|
-
const valueFieldAlias = processColumnReference(
|
|
17238
|
-
currentAgg.valueField || rowField || "count",
|
|
17239
|
-
databaseType,
|
|
17240
|
-
void 0,
|
|
17241
|
-
false,
|
|
17242
|
-
true
|
|
17243
|
-
);
|
|
17244
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17245
|
-
let value2AliasSubstring = "";
|
|
17246
|
-
const disambiguationField = Object.values(seenAggs[currentAgg.aggregationType ?? ""] ?? {}).reduce(
|
|
17247
|
-
(acc, v) => acc + v
|
|
17248
|
-
) > 1 ? `_${currentAgg.valueField}${disambiguationIndex}` : "";
|
|
17249
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationField}_${disambiguationField ? matchCasing(currentAgg.aggregationType, currentAgg.valueField) : currentAgg.aggregationType}` : "";
|
|
17250
|
-
const valueExpr = currentAgg.valueFieldType === "bool" ? `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END` : processValueField(
|
|
17251
|
-
currentAgg.aggregationType,
|
|
17252
|
-
databaseType,
|
|
17253
|
-
valueFieldAlias
|
|
17254
|
-
);
|
|
17255
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17256
|
-
if (!currentAgg.valueField)
|
|
17257
|
-
throw new Error("No value field provided for pivot");
|
|
17258
|
-
const valueField2Alias = processColumnReference(
|
|
17259
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17260
|
-
databaseType,
|
|
17261
|
-
void 0,
|
|
17262
|
-
false,
|
|
17263
|
-
true
|
|
17264
|
-
);
|
|
17265
|
-
const value2Expr = (currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool" ? `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END` : valueField2Alias;
|
|
17266
|
-
if (currentAgg.valueField === currentAgg.valueField2 || !currentAgg.valueField2) {
|
|
17267
|
-
caseWhens = [
|
|
17268
|
-
...caseWhens,
|
|
17269
|
-
...columnFieldValues.map((column) => {
|
|
17270
|
-
return `CAST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17271
|
-
column,
|
|
17272
|
-
databaseType
|
|
17273
|
-
)}' THEN ${valueExpr} END) AS FLOAT) / GREATEST(sum(${value2Expr}), 1) AS ${processColumnReference(
|
|
17274
|
-
column + disambiguation,
|
|
17275
|
-
databaseType,
|
|
17276
|
-
"_",
|
|
17277
|
-
true
|
|
17278
|
-
)}`;
|
|
17279
|
-
})
|
|
17280
|
-
];
|
|
17281
|
-
} else {
|
|
17282
|
-
value2AliasSubstring = `${processColumnReference(
|
|
17283
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17284
|
-
databaseType,
|
|
17285
|
-
void 0,
|
|
17286
|
-
true
|
|
17287
|
-
)} AS ${valueField2Alias}`;
|
|
17288
|
-
caseWhens = [
|
|
17289
|
-
...caseWhens,
|
|
17290
|
-
...columnFieldValues.map((column) => {
|
|
17291
|
-
return `CAST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17292
|
-
column,
|
|
17293
|
-
databaseType
|
|
17294
|
-
)}' THEN ${valueExpr} END) AS FLOAT) / GREATEST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17295
|
-
column,
|
|
17296
|
-
databaseType
|
|
17297
|
-
)}' THEN ${value2Expr} END), 1) AS ${processColumnReference(
|
|
17298
|
-
column + disambiguation,
|
|
17299
|
-
databaseType,
|
|
17300
|
-
"_",
|
|
17301
|
-
true
|
|
17302
|
-
)}`;
|
|
17303
|
-
})
|
|
17304
|
-
];
|
|
17305
|
-
}
|
|
17306
|
-
} else {
|
|
17307
|
-
caseWhens = [
|
|
17308
|
-
...caseWhens,
|
|
17309
|
-
...columnFieldValues.map((column) => {
|
|
17310
|
-
return `${processAggType(currentAgg.aggregationType, true)}(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17311
|
-
column,
|
|
17312
|
-
databaseType
|
|
17313
|
-
)}' THEN ${valueExpr} END) AS ${processColumnReference(column + disambiguation, databaseType, "_", true)}`;
|
|
17314
|
-
})
|
|
17315
|
-
];
|
|
17316
|
-
}
|
|
17317
|
-
if (valueAliasSubstring) valueAliases.push(valueAliasSubstring);
|
|
17318
|
-
if (value2AliasSubstring) valueAliases.push(value2AliasSubstring);
|
|
17319
|
-
});
|
|
17320
|
-
valueAliases = [
|
|
17321
|
-
`${processColumnReference(rowField, databaseType, void 0, true)} AS ${rowFieldAlias}`,
|
|
17322
|
-
...valueAliases,
|
|
17323
|
-
`${processColumnReference(columnField, databaseType, void 0, true)} AS ${columnFieldAlias}`
|
|
17324
|
-
];
|
|
17325
|
-
valueAliases = Array.from(new Set(valueAliases));
|
|
17326
|
-
const sortQuery = pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : "";
|
|
17327
|
-
const pivotQuery = `
|
|
17328
|
-
,quill_alias AS (
|
|
17329
|
-
SELECT ${valueAliases.length > 0 ? `${valueAliases.join(", ")}` : ""}
|
|
17330
|
-
FROM quill_base_table
|
|
17331
|
-
),
|
|
17332
|
-
quill_qt_cw AS (
|
|
17333
|
-
SELECT ${rowFieldAlias}
|
|
17334
|
-
${caseWhens.length > 0 ? `, ${caseWhens.join(", ")}` : ""}
|
|
17335
|
-
FROM quill_alias
|
|
17336
|
-
GROUP BY ${rowFieldAlias}
|
|
17337
|
-
),
|
|
17338
|
-
quill_base_pivot AS (
|
|
17339
|
-
SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} *
|
|
17340
|
-
FROM quill_qt_cw qt
|
|
17341
|
-
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""}
|
|
17342
|
-
)
|
|
17343
|
-
SELECT * FROM quill_base_pivot
|
|
17344
|
-
`.replace(/\s+/g, " ").trim();
|
|
17345
|
-
return itemQuery.replace(
|
|
17346
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17347
|
-
pivotQuery
|
|
17348
|
-
);
|
|
17349
|
-
}
|
|
17350
|
-
function create2DDatePivotQuery(pivot, itemQuery, columnFieldValues, databaseType, dateBucket = "month") {
|
|
17351
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17352
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17353
|
-
);
|
|
17354
|
-
if (!isValidBaseQuery || !pivot.columnField || !pivot.rowField) {
|
|
17355
|
-
return void 0;
|
|
17356
|
-
}
|
|
17357
|
-
if (!pivot.aggregations?.[0]?.valueField && pivot.aggregations?.[0]?.aggregationType !== "count" && !pivot.valueField && pivot.aggregationType !== "count")
|
|
17358
|
-
throw new Error("No value field provided for pivot");
|
|
17359
|
-
if (!pivot.aggregations?.[0]?.aggregationType && !pivot.aggregationType)
|
|
17360
|
-
throw new Error("No aggregation type provided for pivot");
|
|
17361
|
-
const rowField = pivot.rowField;
|
|
17362
|
-
const columnField = pivot.columnField;
|
|
17363
|
-
const rowFieldAlias = processColumnReference(
|
|
17364
|
-
rowField,
|
|
17365
|
-
databaseType,
|
|
17366
|
-
void 0,
|
|
17367
|
-
false,
|
|
17368
|
-
true
|
|
17369
|
-
);
|
|
17370
|
-
const columnFieldAlias = processColumnReference(
|
|
17371
|
-
columnField,
|
|
17372
|
-
databaseType,
|
|
17373
|
-
void 0,
|
|
17374
|
-
false,
|
|
17375
|
-
true
|
|
17376
|
-
);
|
|
17377
|
-
let caseWhens = [];
|
|
17378
|
-
let valueFieldAliases = [];
|
|
17379
|
-
const seenAggs = {};
|
|
17380
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17381
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17382
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17383
|
-
} else {
|
|
17384
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17385
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17386
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17387
|
-
};
|
|
17388
|
-
}
|
|
17389
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString();
|
|
17390
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17391
|
-
const valueFieldAlias = processColumnReference(
|
|
17392
|
-
currentAgg.valueField ?? rowField,
|
|
17393
|
-
databaseType,
|
|
17394
|
-
void 0,
|
|
17395
|
-
false,
|
|
17396
|
-
true
|
|
17397
|
-
);
|
|
17398
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17399
|
-
let value2AliasSubstring = "";
|
|
17400
|
-
const disambiguationField = Object.values(seenAggs[currentAgg.aggregationType ?? ""] ?? {}).reduce(
|
|
17401
|
-
(acc, v) => acc + v
|
|
17402
|
-
) > 1 ? `_${currentAgg.valueField}${disambiguationIndex}` : "";
|
|
17403
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationField}_${disambiguationField ? matchCasing(currentAgg.aggregationType, currentAgg.valueField) : currentAgg.aggregationType}` : "";
|
|
17404
|
-
const valueExpr = currentAgg.valueFieldType === "bool" ? `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END` : processValueField(
|
|
17405
|
-
currentAgg.aggregationType,
|
|
17406
|
-
databaseType,
|
|
17407
|
-
valueFieldAlias
|
|
17408
|
-
);
|
|
17409
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17410
|
-
if (!currentAgg.valueField)
|
|
17411
|
-
throw new Error("No value field provided for pivot");
|
|
17412
|
-
const valueField2Alias = processColumnReference(
|
|
17413
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17414
|
-
databaseType,
|
|
17415
|
-
void 0,
|
|
17416
|
-
false,
|
|
17417
|
-
true
|
|
17418
|
-
);
|
|
17419
|
-
const value2Expr = (currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool" ? `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END` : valueField2Alias;
|
|
17420
|
-
if (currentAgg.valueField === currentAgg.valueField2 || !currentAgg.valueField2) {
|
|
17421
|
-
caseWhens = [
|
|
17422
|
-
...caseWhens,
|
|
17423
|
-
...columnFieldValues.map((column) => {
|
|
17424
|
-
return `CAST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17425
|
-
column,
|
|
17426
|
-
databaseType
|
|
17427
|
-
)}' THEN ${valueExpr} END) AS FLOAT) / GREATEST(sum(${value2Expr}), 1) AS ${processColumnReference(
|
|
17428
|
-
column + disambiguation,
|
|
17429
|
-
databaseType,
|
|
17430
|
-
"_",
|
|
17431
|
-
true
|
|
17432
|
-
)}`;
|
|
17433
|
-
})
|
|
17434
|
-
];
|
|
17435
|
-
} else {
|
|
17436
|
-
value2AliasSubstring = `${processColumnReference(
|
|
17437
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17438
|
-
databaseType,
|
|
17439
|
-
void 0,
|
|
17440
|
-
true
|
|
17441
|
-
)} AS ${valueField2Alias}`;
|
|
17442
|
-
caseWhens = [
|
|
17443
|
-
...caseWhens,
|
|
17444
|
-
...columnFieldValues.map((column) => {
|
|
17445
|
-
return `CAST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17446
|
-
column,
|
|
17447
|
-
databaseType
|
|
17448
|
-
)}' THEN ${valueExpr} END) AS FLOAT) / GREATEST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17449
|
-
column,
|
|
17450
|
-
databaseType
|
|
17451
|
-
)}' THEN ${value2Expr} END), 1) AS ${processColumnReference(
|
|
17452
|
-
column + disambiguation,
|
|
17453
|
-
databaseType,
|
|
17454
|
-
"_",
|
|
17455
|
-
true
|
|
17456
|
-
)}`;
|
|
17457
|
-
})
|
|
17458
|
-
];
|
|
17459
|
-
}
|
|
17460
|
-
} else {
|
|
17461
|
-
caseWhens = [
|
|
17462
|
-
...caseWhens,
|
|
17463
|
-
...columnFieldValues.map((column) => {
|
|
17464
|
-
return `${processAggType(currentAgg.aggregationType, true)}(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(
|
|
17465
|
-
column,
|
|
17466
|
-
databaseType
|
|
17467
|
-
)}' THEN ${valueExpr} END) AS ${processColumnReference(column + disambiguation, databaseType, "_", true)}`;
|
|
17468
|
-
})
|
|
17469
|
-
];
|
|
17470
|
-
}
|
|
17471
|
-
if (valueAliasSubstring) valueFieldAliases.push(valueAliasSubstring);
|
|
17472
|
-
if (value2AliasSubstring) valueFieldAliases.push(value2AliasSubstring);
|
|
17473
|
-
});
|
|
17474
|
-
valueFieldAliases = [
|
|
17475
|
-
`${processColumnReference(rowField, databaseType, void 0, true)} AS ${rowFieldAlias}`,
|
|
17476
|
-
...valueFieldAliases,
|
|
17477
|
-
`${processColumnReference(columnField, databaseType, void 0, true)} AS ${columnFieldAlias}`
|
|
17478
|
-
];
|
|
17479
|
-
valueFieldAliases = Array.from(new Set(valueFieldAliases));
|
|
17480
|
-
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : ""}`;
|
|
17481
|
-
const pivotQuery = `
|
|
17482
|
-
, quill_alias AS (SELECT ${valueFieldAliases.length > 0 ? `${valueFieldAliases.join(", ")}` : ""} FROM quill_base_table),
|
|
17483
|
-
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)}),
|
|
17484
|
-
quill_base_pivot AS (SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} * FROM quill_qt_agg qt
|
|
17485
|
-
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""})
|
|
17486
|
-
SELECT * FROM quill_base_pivot
|
|
17487
|
-
`.replace(/\s+/g, " ").trim();
|
|
17488
|
-
return itemQuery.replace(
|
|
17489
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17490
|
-
pivotQuery
|
|
17491
|
-
);
|
|
17492
|
-
}
|
|
17493
|
-
function create1DPivotQuery(pivot, itemQuery, dateBucket = "month", databaseType) {
|
|
17494
|
-
if (isStringType(pivot.rowFieldType || "") || !pivot.rowFieldType) {
|
|
17495
|
-
return create1DStringPivotQuery(pivot, itemQuery, databaseType);
|
|
17496
|
-
}
|
|
17497
|
-
return create1DDatePivotQuery(pivot, itemQuery, dateBucket, databaseType);
|
|
17498
|
-
}
|
|
17499
|
-
function create1DStringPivotQuery(pivot, itemQuery, databaseType) {
|
|
17500
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17501
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17502
|
-
);
|
|
17503
|
-
if (!isValidBaseQuery) return void 0;
|
|
17504
|
-
const rowField = pivot.rowField;
|
|
17505
|
-
const rowAlias = processColumnReference(
|
|
17506
|
-
rowField,
|
|
17507
|
-
databaseType,
|
|
17508
|
-
void 0,
|
|
17509
|
-
true
|
|
17510
|
-
);
|
|
17511
|
-
let quillAggSelects = [rowAlias];
|
|
17512
|
-
let valueFieldAliases = [];
|
|
17513
|
-
const seenAggs = {};
|
|
17514
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17515
|
-
if (!currentAgg.valueField) currentAgg.valueField = void 0;
|
|
17516
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17517
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17518
|
-
} else {
|
|
17519
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17520
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17521
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17522
|
-
};
|
|
17523
|
-
}
|
|
17524
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString() ?? "";
|
|
17525
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17526
|
-
const valueFieldAlias = processColumnReference(
|
|
17527
|
-
currentAgg.valueField || rowField || "count",
|
|
17528
|
-
databaseType,
|
|
17529
|
-
void 0,
|
|
17530
|
-
false,
|
|
17531
|
-
true
|
|
17532
|
-
);
|
|
17533
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17534
|
-
let value2AliasSubstring = "";
|
|
17535
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationIndex}` + (currentAgg.aggregationType !== "count" ? `_${currentAgg.aggregationType}` : "") : "";
|
|
17536
|
-
let valueExpr = !currentAgg.valueField ? "*" : valueFieldAlias;
|
|
17537
|
-
if (currentAgg.valueFieldType === "bool") {
|
|
17538
|
-
valueExpr = `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END`;
|
|
17539
|
-
}
|
|
17540
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17541
|
-
let countPercentage = false;
|
|
17542
|
-
if (!currentAgg.valueField) {
|
|
17543
|
-
countPercentage = true;
|
|
17544
|
-
}
|
|
17545
|
-
const valueField2Alias = processColumnReference(
|
|
17546
|
-
currentAgg.valueField2 ?? currentAgg.valueField ?? "count",
|
|
17547
|
-
databaseType,
|
|
17548
|
-
void 0,
|
|
17549
|
-
false,
|
|
17550
|
-
true
|
|
17551
|
-
);
|
|
17552
|
-
let value2Expr = valueField2Alias;
|
|
17553
|
-
if ((currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool") {
|
|
17554
|
-
value2Expr = `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END`;
|
|
17555
|
-
}
|
|
17556
|
-
value2AliasSubstring = currentAgg.valueField2 && currentAgg.valueField !== currentAgg.valueField2 ? `${processColumnReference(currentAgg.valueField2, databaseType, void 0, true)} AS ${valueField2Alias}` : "";
|
|
17557
|
-
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)`;
|
|
17558
|
-
quillAggSelects = [
|
|
17559
|
-
...quillAggSelects,
|
|
17560
|
-
`${percentageExpr} as ${processColumnReference(
|
|
17561
|
-
`${currentAgg.valueField ?? (disambiguation ? "count" : "percentage")}${disambiguation}`,
|
|
17562
|
-
databaseType,
|
|
17563
|
-
void 0,
|
|
17564
|
-
false,
|
|
17565
|
-
true
|
|
17566
|
-
)}`
|
|
17567
|
-
];
|
|
17568
|
-
} else {
|
|
17569
|
-
quillAggSelects = [
|
|
17570
|
-
...quillAggSelects,
|
|
17571
|
-
`${processAggType(currentAgg.aggregationType)}(${valueExpr}) AS ${processColumnReference(
|
|
17572
|
-
(currentAgg.valueField || "count") + disambiguation,
|
|
17573
|
-
databaseType
|
|
17574
|
-
)}`
|
|
17575
|
-
];
|
|
17576
|
-
}
|
|
17577
|
-
if (valueAliasSubstring) valueFieldAliases.push(valueAliasSubstring);
|
|
17578
|
-
if (value2AliasSubstring) valueFieldAliases.push(value2AliasSubstring);
|
|
17579
|
-
});
|
|
17580
|
-
valueFieldAliases = Array.from(new Set(valueFieldAliases));
|
|
17581
|
-
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : ""}`;
|
|
17582
|
-
const pivotQuery = `, quill_alias AS (
|
|
17583
|
-
SELECT ${processColumnReference(`${rowField}`, databaseType, void 0, true)} AS ${rowAlias}${valueFieldAliases.length > 0 ? `, ${valueFieldAliases.join(", ")}` : ""}
|
|
17584
|
-
FROM quill_base_table
|
|
17585
|
-
),
|
|
17586
|
-
quill_qt_cw AS (
|
|
17587
|
-
SELECT ${quillAggSelects.join(", ")} FROM quill_alias GROUP BY ${rowAlias}
|
|
17588
|
-
),
|
|
17589
|
-
quill_base_pivot AS (
|
|
17590
|
-
SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} *
|
|
17591
|
-
FROM quill_qt_cw qt ${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""}
|
|
17592
|
-
)
|
|
17593
|
-
SELECT * FROM quill_base_pivot`.replace(/\s+/g, " ").trim();
|
|
17594
|
-
return itemQuery.replace(
|
|
17595
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17596
|
-
pivotQuery
|
|
17597
|
-
);
|
|
17598
|
-
}
|
|
17599
|
-
function create1DDatePivotQuery(pivot, itemQuery, dateBucket = "month", databaseType) {
|
|
17600
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17601
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17602
|
-
);
|
|
17603
|
-
if (!isValidBaseQuery) {
|
|
17604
|
-
return void 0;
|
|
17605
|
-
}
|
|
17606
|
-
const rowField = pivot.rowField || "";
|
|
17607
|
-
const rowFieldAlias = processColumnReference(
|
|
17608
|
-
rowField,
|
|
17609
|
-
databaseType,
|
|
17610
|
-
void 0
|
|
17611
|
-
);
|
|
17612
|
-
let quillAggSelects = [
|
|
17613
|
-
`${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${processColumnReference(rowField, databaseType)}`
|
|
17614
|
-
];
|
|
17615
|
-
let valueFieldAliases = [];
|
|
17616
|
-
const seenAggs = {};
|
|
17617
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17618
|
-
if (!currentAgg.valueField) currentAgg.valueField = void 0;
|
|
17619
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17620
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17621
|
-
} else {
|
|
17622
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17623
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17624
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17625
|
-
};
|
|
17626
|
-
}
|
|
17627
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString() ?? "";
|
|
17628
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17629
|
-
const valueFieldAlias = processColumnReference(
|
|
17630
|
-
currentAgg.valueField || rowField || "count",
|
|
17631
|
-
databaseType,
|
|
17632
|
-
void 0,
|
|
17633
|
-
false,
|
|
17634
|
-
true
|
|
17635
|
-
);
|
|
17636
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17637
|
-
let value2AliasSubstring = "";
|
|
17638
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationIndex}` + (currentAgg.aggregationType !== "count" ? `_${currentAgg.aggregationType}` : "") : "";
|
|
17639
|
-
let valueExpr = !currentAgg.valueField ? "*" : valueFieldAlias;
|
|
17640
|
-
if (currentAgg.valueFieldType === "bool") {
|
|
17641
|
-
valueExpr = `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END`;
|
|
17642
|
-
}
|
|
17643
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17644
|
-
let countPercentage = false;
|
|
17645
|
-
if (!currentAgg.valueField) {
|
|
17646
|
-
countPercentage = true;
|
|
17647
|
-
}
|
|
17648
|
-
const valueField2Alias = processColumnReference(
|
|
17649
|
-
currentAgg.valueField2 ?? currentAgg.valueField ?? "count",
|
|
17650
|
-
databaseType,
|
|
17651
|
-
void 0,
|
|
17652
|
-
false,
|
|
17653
|
-
true
|
|
17654
|
-
);
|
|
17655
|
-
value2AliasSubstring = currentAgg.valueField2 && currentAgg.valueField !== currentAgg.valueField2 ? `${processColumnReference(currentAgg.valueField2, databaseType, void 0, true)} AS ${valueField2Alias}` : "";
|
|
17656
|
-
let value2Expr = valueField2Alias;
|
|
17657
|
-
if ((currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool") {
|
|
17658
|
-
value2Expr = `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END`;
|
|
17659
|
-
}
|
|
17660
|
-
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)`;
|
|
17661
|
-
quillAggSelects = [
|
|
17662
|
-
...quillAggSelects,
|
|
17663
|
-
`${percentageExpr} as ${processColumnReference(
|
|
17664
|
-
`${currentAgg.valueField ?? (disambiguation ? "count" : "percentage")}${disambiguation}`,
|
|
17665
|
-
databaseType,
|
|
17666
|
-
void 0,
|
|
17667
|
-
false,
|
|
17668
|
-
true
|
|
17669
|
-
)}`
|
|
17670
|
-
];
|
|
17671
|
-
} else {
|
|
17672
|
-
quillAggSelects = [
|
|
17673
|
-
...quillAggSelects,
|
|
17674
|
-
`${processAggType(currentAgg.aggregationType)}(${valueExpr}) AS ${processColumnReference((currentAgg.valueField || "count") + disambiguation, databaseType)}`
|
|
17675
|
-
];
|
|
17676
|
-
}
|
|
17677
|
-
if (valueAliasSubstring) valueFieldAliases.push(valueAliasSubstring);
|
|
17678
|
-
if (value2AliasSubstring) valueFieldAliases.push(value2AliasSubstring);
|
|
17679
|
-
});
|
|
17680
|
-
valueFieldAliases = Array.from(new Set(valueFieldAliases));
|
|
17681
|
-
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : ""}`;
|
|
17682
|
-
const pivotQuery = `, quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, void 0, true)} AS ${rowFieldAlias}${valueFieldAliases.length > 0 ? `, ${valueFieldAliases.join(", ")}` : ""}
|
|
17683
|
-
FROM quill_base_table),
|
|
17684
|
-
quill_qt_agg AS (SELECT ${quillAggSelects.join(", ")}
|
|
17685
|
-
FROM quill_alias GROUP BY ${databaseType.toLowerCase() === "clickhouse" ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)}),
|
|
17686
|
-
quill_base_pivot AS (SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} * FROM quill_qt_agg qt
|
|
17687
|
-
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""})
|
|
17688
|
-
SELECT * FROM quill_base_pivot
|
|
17689
|
-
`.replace(/\s+/g, " ").trim();
|
|
17690
|
-
return itemQuery.replace(
|
|
17691
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17692
|
-
pivotQuery
|
|
17693
|
-
);
|
|
17694
|
-
}
|
|
17695
|
-
function createAggregationValuePivot(pivot, itemQuery, databaseType) {
|
|
17696
|
-
const isValidBaseQuery = itemQuery.match(
|
|
17697
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/
|
|
17698
|
-
);
|
|
17699
|
-
if (!isValidBaseQuery) return void 0;
|
|
17700
|
-
let quillAggSelects = [];
|
|
17701
|
-
let valueFieldAliases = [];
|
|
17702
|
-
const seenAggs = {};
|
|
17703
|
-
pivot.aggregations?.forEach((currentAgg) => {
|
|
17704
|
-
if (!currentAgg.valueField) currentAgg.valueField = void 0;
|
|
17705
|
-
if (seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]) {
|
|
17706
|
-
seenAggs[currentAgg.aggregationType ?? ""][currentAgg.valueField ?? ""] += 1;
|
|
17707
|
-
} else {
|
|
17708
|
-
seenAggs[currentAgg.aggregationType ?? ""] = {
|
|
17709
|
-
...seenAggs[currentAgg.aggregationType ?? ""],
|
|
17710
|
-
[currentAgg.valueField ?? ""]: 1
|
|
17711
|
-
};
|
|
17712
|
-
}
|
|
17713
|
-
let disambiguationIndex = seenAggs[currentAgg.aggregationType ?? ""]?.[currentAgg.valueField ?? ""]?.toString() ?? "";
|
|
17714
|
-
if (disambiguationIndex === "1") disambiguationIndex = "";
|
|
17715
|
-
const valueFieldAlias = processColumnReference(
|
|
17716
|
-
currentAgg.valueField || "count",
|
|
17717
|
-
databaseType,
|
|
17718
|
-
void 0,
|
|
17719
|
-
false,
|
|
17720
|
-
true
|
|
17721
|
-
);
|
|
17722
|
-
const valueAliasSubstring = currentAgg.valueField ? `${processColumnReference(currentAgg.valueField, databaseType, void 0, true)} AS ${valueFieldAlias}` : "";
|
|
17723
|
-
let value2AliasSubstring = "";
|
|
17724
|
-
const disambiguation = pivot.aggregations?.length > 1 ? `${disambiguationIndex}_${currentAgg.aggregationType}` : "";
|
|
17725
|
-
let valueExpr = !currentAgg.valueField ? "*" : valueFieldAlias;
|
|
17726
|
-
valueExpr = currentAgg.valueFieldType === "bool" ? `CASE WHEN ${valueFieldAlias} THEN 1 ELSE 0 END` : valueExpr;
|
|
17727
|
-
if (currentAgg.aggregationType === "percentage") {
|
|
17728
|
-
if (!currentAgg.valueField) {
|
|
17729
|
-
throw new Error("No value field provided for percentage aggregation");
|
|
17730
|
-
}
|
|
17731
|
-
const valueField2Alias = processColumnReference(
|
|
17732
|
-
currentAgg.valueField2 ?? currentAgg.valueField,
|
|
17733
|
-
databaseType,
|
|
17734
|
-
void 0,
|
|
17735
|
-
false,
|
|
17736
|
-
true
|
|
17737
|
-
);
|
|
17738
|
-
const value2Expr = (currentAgg.valueField2Type ?? currentAgg.valueFieldType) === "bool" ? `CASE WHEN ${valueField2Alias} THEN 1 ELSE 0 END` : valueField2Alias;
|
|
17739
|
-
value2AliasSubstring = currentAgg.valueField2 && currentAgg.valueField !== currentAgg.valueField2 ? `${processColumnReference(currentAgg.valueField2, databaseType, void 0, true)} AS ${valueField2Alias}` : "";
|
|
17740
|
-
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)`;
|
|
17741
|
-
quillAggSelects = [
|
|
17742
|
-
...quillAggSelects,
|
|
17743
|
-
`${percentageExpr} as ${processColumnReference(
|
|
17744
|
-
`${currentAgg.valueField ?? ""}${disambiguation}`,
|
|
17745
|
-
databaseType,
|
|
17746
|
-
void 0,
|
|
17747
|
-
false,
|
|
17748
|
-
true
|
|
17749
|
-
)}`
|
|
17750
|
-
];
|
|
17751
|
-
} else {
|
|
17752
|
-
quillAggSelects = [
|
|
17753
|
-
...quillAggSelects,
|
|
17754
|
-
`${processAggType(currentAgg.aggregationType)}(${valueExpr}) AS ${processColumnReference(
|
|
17755
|
-
(currentAgg.valueField || "count") + disambiguation,
|
|
17756
|
-
databaseType
|
|
17757
|
-
)}`
|
|
17758
|
-
];
|
|
17759
|
-
}
|
|
17760
|
-
if (valueAliasSubstring) valueFieldAliases.push(valueAliasSubstring);
|
|
17761
|
-
if (value2AliasSubstring) valueFieldAliases.push(value2AliasSubstring);
|
|
17762
|
-
});
|
|
17763
|
-
valueFieldAliases = Array.from(new Set(valueFieldAliases));
|
|
17764
|
-
if (valueFieldAliases.length === 0) {
|
|
17765
|
-
valueFieldAliases = ["*"];
|
|
17766
|
-
}
|
|
17767
|
-
const sortQuery = pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, void 0, true)} ${pivot.sortDirection || ""} ` : "";
|
|
17768
|
-
const pivotQuery = `, quill_alias AS (
|
|
17769
|
-
SELECT ${valueFieldAliases.join(", ")} FROM quill_base_table
|
|
17770
|
-
),
|
|
17771
|
-
quill_qt_agg AS (
|
|
17772
|
-
SELECT ${quillAggSelects.join(", ")} FROM quill_alias
|
|
17773
|
-
),
|
|
17774
|
-
quill_base_pivot AS (
|
|
17775
|
-
SELECT ${pivot.rowLimit && databaseType.toLowerCase() === "mssql" ? `TOP ${pivot.rowLimit}` : ""} * FROM quill_qt_agg qt
|
|
17776
|
-
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== "mssql" ? ` LIMIT ${pivot.rowLimit}` : ""}
|
|
17777
|
-
)
|
|
17778
|
-
SELECT * FROM quill_base_pivot`.replace(/\s+/g, " ").trim();
|
|
17779
|
-
return itemQuery.replace(
|
|
17780
|
-
/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/,
|
|
17781
|
-
pivotQuery
|
|
17782
|
-
);
|
|
17783
|
-
}
|
|
17784
|
-
function additionalProcessingOnPivotQuery(pivot, query, additionalProcessing, databaseType = "postgresql") {
|
|
17785
|
-
if (!additionalProcessing || !query) return query;
|
|
17786
|
-
const isValidBaseQuery = query.match(
|
|
17787
|
-
/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/
|
|
17788
|
-
);
|
|
17789
|
-
if (!isValidBaseQuery) {
|
|
17790
|
-
return void 0;
|
|
17791
|
-
}
|
|
17792
|
-
if (!pivot.aggregations || pivot.aggregations.length === 0) {
|
|
17793
|
-
if (pivot.aggregationType) {
|
|
17794
|
-
pivot.aggregations = [
|
|
17795
|
-
{
|
|
17796
|
-
aggregationType: pivot.aggregationType,
|
|
17797
|
-
valueField: pivot.valueField,
|
|
17798
|
-
valueField2: pivot.valueField2
|
|
17799
|
-
}
|
|
17800
|
-
];
|
|
17801
|
-
} else {
|
|
17802
|
-
throw new Error("No aggregations provided for pivot");
|
|
17803
|
-
}
|
|
17804
|
-
}
|
|
17805
|
-
let rowsPerPage = 0;
|
|
17806
|
-
let currentInterval = 0;
|
|
17807
|
-
let offset = 0;
|
|
17808
|
-
let limit = 1e3;
|
|
17809
|
-
let sortQuery = "";
|
|
17810
|
-
if (additionalProcessing.page) {
|
|
17811
|
-
const page = additionalProcessing.page.page || 0;
|
|
17812
|
-
if (additionalProcessing.page.rowsPerRequest) {
|
|
17813
|
-
limit = additionalProcessing.page.rowsPerRequest;
|
|
17814
|
-
}
|
|
17815
|
-
rowsPerPage = additionalProcessing.page.rowsPerPage || 0;
|
|
17816
|
-
currentInterval = page ? Math.floor(page / (limit / rowsPerPage)) : 0;
|
|
17817
|
-
offset = currentInterval * limit;
|
|
17818
|
-
}
|
|
17819
|
-
const disambiguation = pivot.aggregations.length > 1 ? `_${matchCasing(pivot.aggregations?.[0]?.aggregationType, pivot.aggregations?.[0]?.valueField)}` : "";
|
|
17820
|
-
if (additionalProcessing.sort) {
|
|
17821
|
-
sortQuery = `ORDER BY ${processColumnReference(additionalProcessing.sort.field, databaseType, void 0, true)} ${additionalProcessing.sort.direction || ""}`;
|
|
17822
|
-
} else {
|
|
17823
|
-
const valueFieldAlias = processColumnReference(
|
|
17824
|
-
(pivot.aggregations?.[0]?.valueField ?? "") + disambiguation,
|
|
17825
|
-
databaseType,
|
|
17826
|
-
void 0,
|
|
17827
|
-
false,
|
|
17828
|
-
true
|
|
17829
|
-
);
|
|
17830
|
-
const defaultSortField = pivot.sortField || pivot.rowField || valueFieldAlias;
|
|
17831
|
-
const defaultSortDirection = pivot.sortDirection || "";
|
|
17832
|
-
if (defaultSortField !== `"_"`) {
|
|
17833
|
-
sortQuery = `ORDER BY ${processColumnReference(defaultSortField, databaseType, void 0, true)} ${defaultSortDirection}`;
|
|
17834
|
-
} else {
|
|
17835
|
-
sortQuery = "";
|
|
17836
|
-
}
|
|
17837
|
-
}
|
|
17838
|
-
const additionalProcessingQuery = `
|
|
17839
|
-
SELECT *
|
|
17840
|
-
FROM quill_base_pivot ${sortQuery}${databaseType.toLowerCase() === "mssql" ? ` OFFSET ${offset} ROWS FETCH NEXT ${limit} ROWS ONLY` : ` LIMIT ${limit} OFFSET ${offset}`}
|
|
17841
|
-
`.replace(/\s+/g, " ").trim();
|
|
17842
|
-
return query.replace(
|
|
17843
|
-
/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/,
|
|
17844
|
-
additionalProcessingQuery
|
|
17845
|
-
);
|
|
17846
|
-
}
|
|
17847
|
-
function generateRowCountQuery(query, databaseType) {
|
|
17848
|
-
if (!query) return query;
|
|
17849
|
-
const isValidBaseQuery = query.match(
|
|
17850
|
-
/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/
|
|
17851
|
-
);
|
|
17852
|
-
if (!isValidBaseQuery) {
|
|
17853
|
-
return void 0;
|
|
17854
|
-
}
|
|
17855
|
-
const rowCountQuery = `, subview_row_count_cte AS (SELECT * FROM quill_base_pivot)
|
|
17856
|
-
SELECT count(*) as ${processColumnReference("row_count", databaseType || "postgresql", void 0, true)} FROM subview_row_count_cte
|
|
17857
|
-
`.replace(/\s+/g, " ").trim();
|
|
17858
|
-
return query.replace(
|
|
17859
|
-
/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/,
|
|
17860
|
-
rowCountQuery
|
|
17861
|
-
);
|
|
17862
|
-
}
|
|
17863
|
-
|
|
17864
|
-
// src/utils/pivotConstructor.ts
|
|
17865
|
-
async function generatePivotWithSQL({
|
|
17866
|
-
pivot,
|
|
17867
|
-
report,
|
|
17868
|
-
client,
|
|
17869
|
-
dateBucket,
|
|
17870
|
-
dateFilter,
|
|
17871
|
-
distinctStrings,
|
|
17872
|
-
dashboardName,
|
|
17873
|
-
tenants,
|
|
17874
|
-
additionalProcessing,
|
|
17875
|
-
pivotQuery,
|
|
17876
|
-
comparisonPivotQuery,
|
|
17877
|
-
getPivotRowCount = true,
|
|
17878
|
-
caller,
|
|
17879
|
-
getToken
|
|
17880
|
-
}) {
|
|
17881
|
-
let sqlQuery = pivotQuery;
|
|
17882
|
-
let comparisonPivotSql = comparisonPivotQuery;
|
|
17883
|
-
const databaseType = client.databaseType || "postgresql";
|
|
17884
|
-
if (!pivotQuery && pivot.columnField && !pivot.columnValues && !distinctStrings) {
|
|
17885
|
-
if (!report?.rows) {
|
|
17886
|
-
throw new Error("No distinct strings provided for column field");
|
|
17887
|
-
} else {
|
|
17888
|
-
distinctStrings = Array.from(
|
|
17889
|
-
new Set(
|
|
17890
|
-
report.rows.map((row) => row[pivot.columnField]).filter((value) => value !== null && value !== void 0)
|
|
17891
|
-
)
|
|
17892
|
-
);
|
|
17893
|
-
}
|
|
17894
|
-
}
|
|
17895
|
-
if (!pivot.aggregations?.length && pivot.aggregationType) {
|
|
17896
|
-
pivot.aggregations = [
|
|
17897
|
-
{
|
|
17898
|
-
aggregationType: pivot.aggregationType,
|
|
17899
|
-
valueField: pivot.valueField,
|
|
17900
|
-
valueFieldType: pivot.valueFieldType,
|
|
17901
|
-
valueField2: pivot.valueField2,
|
|
17902
|
-
valueField2Type: pivot.valueField2Type
|
|
17903
|
-
}
|
|
17904
|
-
];
|
|
17905
|
-
}
|
|
17906
|
-
let comparisonInterval = void 0;
|
|
17907
|
-
if (dateFilter && dateFilter.comparisonRange) {
|
|
17908
|
-
comparisonInterval = getComparisonInterval(
|
|
17909
|
-
{
|
|
17910
|
-
startDate: dateFilter.comparisonRange.startDate,
|
|
17911
|
-
endDate: dateFilter.comparisonRange.endDate
|
|
17912
|
-
},
|
|
17913
|
-
dateBucket
|
|
17914
|
-
);
|
|
17915
|
-
}
|
|
17916
|
-
if (pivot.rowField && !pivot.rowFieldType) {
|
|
17917
|
-
const rowColumn = report?.columns.find(
|
|
17918
|
-
(column) => column.field === pivot.rowField
|
|
17919
|
-
);
|
|
17920
|
-
pivot.rowFieldType = rowColumn?.format || "string";
|
|
17921
|
-
}
|
|
17922
|
-
const filteredDistinctStrings = distinctStrings?.filter(
|
|
17923
|
-
(value) => value !== null && value !== void 0 && value !== ""
|
|
17924
|
-
);
|
|
17925
|
-
const pivotColumnFields = filteredDistinctStrings?.slice(
|
|
17926
|
-
0,
|
|
17927
|
-
MAX_PIVOT_UNIQUE_VALUES
|
|
17928
|
-
);
|
|
17929
|
-
if (!pivotQuery && report) {
|
|
17930
|
-
if (!report.itemQuery) {
|
|
17931
|
-
throw Error("No item query found in report");
|
|
17932
|
-
}
|
|
17933
|
-
const itemQuery = report.itemQuery[0];
|
|
17934
|
-
const comparisonQuery = report.itemQuery[1];
|
|
17935
|
-
if (!itemQuery) {
|
|
17936
|
-
throw Error("No item query found in report");
|
|
17937
|
-
}
|
|
17938
|
-
sqlQuery = generatePivotQuery(
|
|
17939
|
-
pivot,
|
|
17940
|
-
itemQuery,
|
|
17941
|
-
databaseType,
|
|
17942
|
-
pivotColumnFields,
|
|
17943
|
-
dateBucket
|
|
17944
|
-
);
|
|
17945
|
-
comparisonPivotSql = comparisonQuery ? generatePivotQuery(
|
|
17946
|
-
pivot,
|
|
17947
|
-
comparisonQuery,
|
|
17948
|
-
databaseType,
|
|
17949
|
-
pivotColumnFields,
|
|
17950
|
-
dateBucket
|
|
17951
|
-
) : "";
|
|
17952
|
-
}
|
|
17953
|
-
if (!sqlQuery) {
|
|
17954
|
-
throw "Error generating pivot query";
|
|
17955
|
-
}
|
|
17956
|
-
const paginatedSqlQuery = additionalProcessingOnPivotQuery(
|
|
17957
|
-
pivot,
|
|
17958
|
-
sqlQuery,
|
|
17959
|
-
additionalProcessing,
|
|
17960
|
-
client.databaseType
|
|
17961
|
-
);
|
|
17962
|
-
const paginatedComparisonQuery = comparisonPivotSql ? additionalProcessingOnPivotQuery(
|
|
17963
|
-
pivot,
|
|
17964
|
-
comparisonPivotSql,
|
|
17965
|
-
additionalProcessing,
|
|
17966
|
-
client.databaseType
|
|
17967
|
-
) : "";
|
|
17968
|
-
const preQueries = [paginatedSqlQuery];
|
|
17969
|
-
getPivotRowCount = getPivotRowCount && (report?.chartType === "table" || caller === "ReportBuilder");
|
|
17970
|
-
if (getPivotRowCount) {
|
|
17971
|
-
const pivotRowCountQuery = generateRowCountQuery(
|
|
17972
|
-
sqlQuery,
|
|
17973
|
-
client.databaseType
|
|
17974
|
-
);
|
|
17975
|
-
preQueries.push(pivotRowCountQuery);
|
|
17976
|
-
}
|
|
17977
|
-
if (paginatedComparisonQuery) {
|
|
17978
|
-
preQueries.push(paginatedComparisonQuery);
|
|
17979
|
-
}
|
|
17980
|
-
const { data: resp } = await quillFetch({
|
|
17981
|
-
client,
|
|
17982
|
-
task: "query",
|
|
17983
|
-
metadata: {
|
|
17984
|
-
preQueries,
|
|
17985
|
-
clientId: client.publicKey,
|
|
17986
|
-
databaseType,
|
|
17987
|
-
runQueryConfig: {
|
|
17988
|
-
overridePost: true,
|
|
17989
|
-
convertDatatypes: true
|
|
17990
|
-
},
|
|
17991
|
-
useNewNodeSql: true,
|
|
17992
|
-
dashboardName,
|
|
17993
|
-
tenants
|
|
17994
|
-
},
|
|
17995
|
-
urlParameters: `caller=generatePivot&task=query`,
|
|
17996
|
-
credentials: "same-origin",
|
|
17997
|
-
getToken
|
|
17998
|
-
});
|
|
17999
|
-
if (resp.success === false) {
|
|
18000
|
-
throw resp.errorMessage;
|
|
18001
|
-
}
|
|
18002
|
-
const queryResponseRows = resp?.queryResults?.[0]?.rows || [];
|
|
18003
|
-
const queryResponseFields = resp?.queryResults?.[0]?.fields || [];
|
|
18004
|
-
const queryComparisonResponseRows = (getPivotRowCount ? resp?.queryResults?.[2]?.rows : resp?.queryResults?.[1]?.rows) || [];
|
|
18005
|
-
const queryComparisonResponseFields = (getPivotRowCount ? resp?.queryResults?.[2]?.fields : resp?.queryResults?.[1]?.fields) || [];
|
|
18006
|
-
parseValueFromBigQueryDates(queryResponseRows, queryResponseFields);
|
|
18007
|
-
parseValueFromBigQueryDates(
|
|
18008
|
-
queryComparisonResponseRows,
|
|
18009
|
-
queryComparisonResponseFields
|
|
18010
|
-
);
|
|
18011
|
-
const responseRows = mergeComparisonPivotRows({
|
|
18012
|
-
pivot,
|
|
18013
|
-
rows: queryResponseRows,
|
|
18014
|
-
compRows: queryComparisonResponseRows,
|
|
18015
|
-
databaseType,
|
|
18016
|
-
dateBucket,
|
|
18017
|
-
comparisonInterval,
|
|
18018
|
-
columnFieldValues: pivotColumnFields
|
|
18019
|
-
});
|
|
18020
|
-
const responseFields = mergeComparisonPivotColumns({
|
|
18021
|
-
pivot,
|
|
18022
|
-
rows: queryResponseFields,
|
|
18023
|
-
compRows: queryComparisonResponseFields
|
|
18024
|
-
});
|
|
18025
|
-
const rows = pivot.rowField ? responseRows.map(
|
|
18026
|
-
(row) => !row[pivot.rowField] ? { ...row, [pivot.rowField]: "-" } : row
|
|
18027
|
-
) : responseRows;
|
|
18028
|
-
if (pivot.columnField && client.databaseType?.toLowerCase() === "bigquery") {
|
|
18029
|
-
rows.forEach((row) => {
|
|
18030
|
-
Object.keys(row).forEach((key) => {
|
|
18031
|
-
const processedKey = processColumnName(key);
|
|
18032
|
-
if (processedKey !== key) {
|
|
18033
|
-
row[processedKey] = row[key];
|
|
18034
|
-
delete row[key];
|
|
18035
|
-
}
|
|
18036
|
-
});
|
|
18037
|
-
});
|
|
18038
|
-
}
|
|
18039
|
-
const columns = responseFields?.map((field) => ({
|
|
18040
|
-
field: processColumnName(field.name),
|
|
18041
|
-
label: snakeCaseToTitleCase(
|
|
18042
|
-
processColumnName(field.name.replace("comparison_", "comparison "))
|
|
18043
|
-
),
|
|
18044
|
-
format: field.name === pivot.rowField ? "string" : (
|
|
18045
|
-
// This scary equation is calculating which aggregation a column is associated with.
|
|
18046
|
-
// 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.
|
|
18047
|
-
// pivot.aggregations?.[
|
|
18048
|
-
// Math.floor(
|
|
18049
|
-
// (index - 1) /
|
|
18050
|
-
// Math.floor(
|
|
18051
|
-
// (responseFields.length - 1) /
|
|
18052
|
-
// (pivot.aggregations?.length ?? 1),
|
|
18053
|
-
// ),
|
|
18054
|
-
// )
|
|
18055
|
-
// ]?.aggregationType === 'percentage'
|
|
18056
|
-
pivot.aggregations?.find(
|
|
18057
|
-
(agg) => agg.valueField === field.name || `${agg.valueField}_percentage` === field.name || !agg.valueField && agg.aggregationType === "percentage" && field.name.endsWith("percentage")
|
|
18058
|
-
)?.aggregationType === "percentage" ? "percent" : "whole_number"
|
|
18059
|
-
),
|
|
18060
|
-
fieldType: field.fieldType,
|
|
18061
|
-
jsType: field.jsType,
|
|
18062
|
-
dataTypeID: field.dataTypeID
|
|
18063
|
-
})).filter(
|
|
18064
|
-
(field, index) => field.field !== "comparison_" + pivot.rowField || index === 0
|
|
18065
|
-
).sort((a, b) => {
|
|
18066
|
-
if (a.field === pivot.rowField) {
|
|
18067
|
-
return -1;
|
|
18068
|
-
}
|
|
18069
|
-
if (b.field === pivot.rowField) {
|
|
18070
|
-
return 1;
|
|
18071
|
-
}
|
|
18072
|
-
return 0;
|
|
18073
|
-
});
|
|
18074
|
-
if (pivot.rowField && !isStringType(pivot.rowFieldType || "")) {
|
|
18075
|
-
rows.forEach((row) => {
|
|
18076
|
-
row.__quillRawDate = typeof row[pivot.rowField || ""] === "object" ? row[pivot.rowField || ""].value : row[pivot.rowField || ""];
|
|
18077
|
-
let value = typeof row[pivot.rowField || ""] === "object" ? row[pivot.rowField || ""].value : row[pivot.rowField || ""];
|
|
18078
|
-
if (dateBucket === "week" && dateFilter?.startDate && dateFilter?.endDate) {
|
|
18079
|
-
const rowDate = new Date(value);
|
|
18080
|
-
if (rowDate < dateFilter.startDate) {
|
|
18081
|
-
value = dateFilter.startDate.toISOString();
|
|
18082
|
-
} else if (rowDate > dateFilter.endDate) {
|
|
18083
|
-
value = dateFilter.endDate.toISOString();
|
|
18084
|
-
}
|
|
18085
|
-
}
|
|
18086
|
-
const dateString = getDateString(
|
|
18087
|
-
value,
|
|
18088
|
-
dateFilter?.startDate && dateFilter?.endDate ? { start: dateFilter.startDate, end: dateFilter.endDate } : void 0,
|
|
18089
|
-
dateBucket,
|
|
18090
|
-
databaseType
|
|
18091
|
-
);
|
|
18092
|
-
row[pivot.rowField || ""] = dateString;
|
|
18093
|
-
});
|
|
18094
|
-
if (pivot.rowField && pivot.rowFieldType && !isStringType(pivot.rowFieldType) && dateFilter?.startDate && dateFilter?.endDate) {
|
|
18095
|
-
const dateSet = new Set(
|
|
18096
|
-
rows.map((row) => row[pivot.rowField || ""])
|
|
18097
|
-
);
|
|
18098
|
-
for (let date = dateFilter.startDate; date <= dateFilter.endDate; date = new Date(date.getTime() + 24 * 60 * 60 * 1e3)) {
|
|
18099
|
-
const formattedDate = getDateString(
|
|
18100
|
-
date.toISOString(),
|
|
18101
|
-
{ start: dateFilter.startDate, end: dateFilter.endDate },
|
|
18102
|
-
dateBucket,
|
|
18103
|
-
databaseType
|
|
18104
|
-
);
|
|
18105
|
-
if (!dateSet.has(formattedDate)) {
|
|
18106
|
-
const newRow = {};
|
|
18107
|
-
newRow[pivot.rowField] = formattedDate;
|
|
18108
|
-
newRow.__quillRawDate = date.toISOString();
|
|
18109
|
-
rows.push(newRow);
|
|
18110
|
-
dateSet.add(formattedDate);
|
|
18111
|
-
}
|
|
18112
|
-
}
|
|
18113
|
-
}
|
|
18114
|
-
if (!pivot.sort) {
|
|
18115
|
-
rows.sort((a, b) => {
|
|
18116
|
-
if (a.__quillRawDate < b.__quillRawDate) {
|
|
18117
|
-
return -1;
|
|
18118
|
-
}
|
|
18119
|
-
if (a.__quillRawDate > b.__quillRawDate) {
|
|
18120
|
-
return 1;
|
|
18121
|
-
}
|
|
18122
|
-
return 0;
|
|
18123
|
-
});
|
|
18124
|
-
}
|
|
18125
|
-
}
|
|
18126
|
-
columns?.forEach((column, index) => {
|
|
18127
|
-
if (column.label && ["null", "undefined"].includes(column.label.toLowerCase()) && !pivot.columnField && !pivot.aggregations?.[index]?.valueField && pivot.aggregations?.[index]?.aggregationType === "count") {
|
|
18128
|
-
column.label = "Count";
|
|
18129
|
-
}
|
|
18130
|
-
});
|
|
18131
|
-
const numericColumns = columns?.filter(
|
|
18132
|
-
(column) => column.format === "whole_number" || column.format === "percentage"
|
|
18133
|
-
);
|
|
18134
|
-
rows.forEach((row) => {
|
|
18135
|
-
numericColumns?.forEach((column) => {
|
|
18136
|
-
row[column.field] = row[column.field] ?? 0;
|
|
18137
|
-
});
|
|
18138
|
-
});
|
|
18139
|
-
return {
|
|
18140
|
-
rows,
|
|
18141
|
-
columns: columns ?? [],
|
|
18142
|
-
rowCount: getPivotRowCount ? Number(resp?.queryResults?.[1]?.rows?.[0]?.["row_count"]) ?? rows.length : 0,
|
|
18143
|
-
pivotQuery: sqlQuery,
|
|
18144
|
-
comparisonPivotQuery: comparisonPivotSql
|
|
18145
|
-
};
|
|
18146
|
-
}
|
|
18147
|
-
function generatePivotTableYAxis(pivot, cols, yAxisField) {
|
|
18148
|
-
if (pivot?.aggregationType === "count") {
|
|
18149
|
-
return [
|
|
18150
|
-
{
|
|
18151
|
-
field: pivot.valueField ?? "count",
|
|
18152
|
-
label: yAxisField.label,
|
|
18153
|
-
format: yAxisField.format
|
|
18154
|
-
}
|
|
18155
|
-
];
|
|
18156
|
-
}
|
|
18157
|
-
return [
|
|
18158
|
-
{
|
|
18159
|
-
field: pivot.valueField ?? "count",
|
|
18160
|
-
label: yAxisField.label,
|
|
18161
|
-
format: yAxisField.format
|
|
18162
|
-
}
|
|
18163
|
-
];
|
|
18164
|
-
}
|
|
18165
|
-
function generatePivotTitle(pivot) {
|
|
18166
|
-
if (pivot.rowField && !pivot.valueField && pivot.aggregations?.[0]) {
|
|
18167
|
-
return snakeAndCamelCaseToTitleCase(
|
|
18168
|
-
`${pivot.aggregations[0].aggregationType} of ${pivot.rowField}${pivot.columnField ? ` by ${pivot.columnField}` : ""}
|
|
18169
|
-
`
|
|
18170
|
-
);
|
|
18171
|
-
} else if (!pivot.rowField && pivot.aggregations?.[0]?.valueField) {
|
|
18172
|
-
return snakeAndCamelCaseToTitleCase(
|
|
18173
|
-
`${pivot.aggregations[0].aggregationType} of ${pivot.aggregations[0].valueField}
|
|
18174
|
-
`
|
|
18175
|
-
);
|
|
18176
|
-
}
|
|
18177
|
-
return snakeAndCamelCaseToTitleCase(
|
|
18178
|
-
`${pivot.aggregations?.[0]?.aggregationType ?? "Aggregation"} of ${pivot.aggregations?.[0]?.valueField ?? "value"}${pivot.rowField ? ` by ${pivot.rowField}` : ""}${pivot.columnField ? ` and ${pivot.columnField}` : ""}`
|
|
18179
|
-
);
|
|
18180
|
-
}
|
|
18181
|
-
async function generatePivotTable({
|
|
18182
|
-
pivot,
|
|
18183
|
-
dateBucket,
|
|
18184
|
-
dateFilter,
|
|
18185
|
-
report,
|
|
18186
|
-
client,
|
|
18187
|
-
getToken,
|
|
18188
|
-
eventTracking,
|
|
18189
|
-
uniqueValues,
|
|
18190
|
-
dashboardName,
|
|
18191
|
-
tenants,
|
|
18192
|
-
additionalProcessing,
|
|
18193
|
-
caller,
|
|
18194
|
-
pivotQuery
|
|
18195
|
-
}) {
|
|
18196
|
-
try {
|
|
18197
|
-
if (report && client) {
|
|
18198
|
-
const pivotTable = await generatePivotWithSQL({
|
|
18199
|
-
pivotQuery,
|
|
18200
|
-
pivot,
|
|
18201
|
-
report,
|
|
18202
|
-
client,
|
|
18203
|
-
dateBucket,
|
|
18204
|
-
dateFilter,
|
|
18205
|
-
distinctStrings: pivot.columnField && uniqueValues?.[pivot.columnField] ? uniqueValues[pivot.columnField] : [],
|
|
18206
|
-
dashboardName,
|
|
18207
|
-
tenants,
|
|
18208
|
-
additionalProcessing,
|
|
18209
|
-
caller,
|
|
18210
|
-
getToken
|
|
18211
|
-
});
|
|
18212
|
-
return pivotTable;
|
|
18213
|
-
}
|
|
18214
|
-
} catch (e) {
|
|
18215
|
-
eventTracking?.logError?.({
|
|
18216
|
-
type: "bug",
|
|
18217
|
-
// TODO: determine type
|
|
18218
|
-
severity: "high",
|
|
18219
|
-
message: "Error generating pivot table",
|
|
18220
|
-
errorMessage: e.message,
|
|
18221
|
-
errorStack: e.stack,
|
|
18222
|
-
errorData: {
|
|
18223
|
-
caller: "PivotModal",
|
|
18224
|
-
function: "generatePivotTable"
|
|
18225
|
-
}
|
|
18226
|
-
});
|
|
18227
|
-
throw Error(`Failed to generate pivot table with SQL: ${e}`);
|
|
18228
|
-
}
|
|
18229
|
-
throw Error("Failed to generate pivot table: invalid report");
|
|
18230
|
-
}
|
|
18231
|
-
|
|
18232
|
-
// src/utils/errorProcessing.ts
|
|
18233
|
-
function processFilterErrorList(resp) {
|
|
18234
|
-
if (!resp || !resp.filterErrorList || !Array.isArray(resp.filterErrorList)) {
|
|
18235
|
-
return;
|
|
18236
|
-
}
|
|
18237
|
-
}
|
|
18238
|
-
|
|
18239
|
-
// src/utils/paginationProcessing.ts
|
|
18240
|
-
var DEFAULT_PAGINATION = {
|
|
18241
|
-
page: 0,
|
|
18242
|
-
rowsPerPage: 10,
|
|
18243
|
-
rowsPerRequest: 600
|
|
18244
|
-
};
|
|
18245
|
-
var DEFAULT_TABLE_PAGINATION = {
|
|
18246
|
-
page: 0,
|
|
18247
|
-
rowsPerPage: 10,
|
|
18248
|
-
rowsPerRequest: 50
|
|
18249
|
-
};
|
|
18250
|
-
function shouldFetchMore(pagination, page, maxPage, currentRowCount) {
|
|
18251
|
-
if (!pagination || currentRowCount && currentRowCount >= pagination.rowsPerPage * (page + 1)) {
|
|
18252
|
-
return false;
|
|
18253
|
-
}
|
|
18254
|
-
const indexAdjustedPage = page;
|
|
18255
|
-
const pageInterval = Math.floor(
|
|
18256
|
-
indexAdjustedPage * pagination.rowsPerPage / pagination.rowsPerRequest
|
|
18257
|
-
);
|
|
18258
|
-
const indexAdjustedPreviousPage = maxPage;
|
|
18259
|
-
const previousPageInterval = Math.floor(
|
|
18260
|
-
indexAdjustedPreviousPage * pagination.rowsPerPage / pagination.rowsPerRequest
|
|
18261
|
-
);
|
|
18262
|
-
return pageInterval > previousPageInterval;
|
|
18263
|
-
}
|
|
18264
|
-
function shouldSortInMemory(pagination, rowCount) {
|
|
18265
|
-
if (!rowCount || rowCount < pagination.rowsPerRequest) {
|
|
18266
|
-
return true;
|
|
18267
|
-
}
|
|
18268
|
-
return false;
|
|
18269
|
-
}
|
|
18270
17553
|
|
|
18271
17554
|
// src/utils/tableProcessing.ts
|
|
18272
17555
|
var getUniqueValuesByQuery = async ({
|
|
@@ -19008,491 +18291,6 @@ var fetchTableByAST = async (ast, client, getToken, tenants, eventTracking, dash
|
|
|
19008
18291
|
return { rows, columns, rowCount, error, itemQuery, referencedTables };
|
|
19009
18292
|
};
|
|
19010
18293
|
|
|
19011
|
-
// src/utils/dashboard.ts
|
|
19012
|
-
var defaultDashboardItem = {
|
|
19013
|
-
id: "",
|
|
19014
|
-
name: "",
|
|
19015
|
-
dashboardName: "",
|
|
19016
|
-
rows: [],
|
|
19017
|
-
compareRows: [],
|
|
19018
|
-
columns: [],
|
|
19019
|
-
chartType: "",
|
|
19020
|
-
pivot: null,
|
|
19021
|
-
yAxisFields: [],
|
|
19022
|
-
xAxisLabel: "",
|
|
19023
|
-
xAxisField: "",
|
|
19024
|
-
xAxisFormat: "string",
|
|
19025
|
-
order: -1,
|
|
19026
|
-
filtersApplied: [],
|
|
19027
|
-
queryString: "",
|
|
19028
|
-
rowCount: 0,
|
|
19029
|
-
columnInternal: []
|
|
19030
|
-
};
|
|
19031
|
-
async function cleanDashboardItem({
|
|
19032
|
-
item,
|
|
19033
|
-
dashboardFilters,
|
|
19034
|
-
getToken,
|
|
19035
|
-
eventTracking,
|
|
19036
|
-
client,
|
|
19037
|
-
dateBucket,
|
|
19038
|
-
additionalProcessing,
|
|
19039
|
-
customFields,
|
|
19040
|
-
skipPivotFetch,
|
|
19041
|
-
tenants
|
|
19042
|
-
}) {
|
|
19043
|
-
if (!item) return defaultDashboardItem;
|
|
19044
|
-
if (!item.rows) {
|
|
19045
|
-
return {
|
|
19046
|
-
...defaultDashboardItem,
|
|
19047
|
-
id: item._id,
|
|
19048
|
-
name: item.name
|
|
19049
|
-
};
|
|
19050
|
-
}
|
|
19051
|
-
const fields = item.fields || [];
|
|
19052
|
-
const columnsWithCustomFields = [...item.columns ?? []];
|
|
19053
|
-
if (item.includeCustomFields && item.rows?.length > 0) {
|
|
19054
|
-
const tables = item.referencedTables ?? [];
|
|
19055
|
-
tables.forEach((table) => {
|
|
19056
|
-
const _customFields = customFields?.[table] ?? [];
|
|
19057
|
-
_customFields.forEach((field) => {
|
|
19058
|
-
const isJsonCustomField = !!field.refColumn;
|
|
19059
|
-
if (item.rows[0][field.field] !== void 0 && !item.columns.some((col) => col.field === field.field)) {
|
|
19060
|
-
const result_field = fields.find((f) => f.name === field.field);
|
|
19061
|
-
const converted_field = convertPostgresColumn(result_field ?? {});
|
|
19062
|
-
columnsWithCustomFields.push({
|
|
19063
|
-
field: field.field,
|
|
19064
|
-
format: converted_field.format,
|
|
19065
|
-
label: snakeAndCamelCaseToTitleCase(field.field),
|
|
19066
|
-
fieldType: converted_field.fieldType,
|
|
19067
|
-
dataTypeID: converted_field.dataTypeID,
|
|
19068
|
-
jsType: converted_field.jsType,
|
|
19069
|
-
inferFormat: isJsonCustomField
|
|
19070
|
-
});
|
|
19071
|
-
}
|
|
19072
|
-
});
|
|
19073
|
-
});
|
|
19074
|
-
}
|
|
19075
|
-
const processedColumns = item.columns.map((col) => {
|
|
19076
|
-
return { ...col, label: snakeAndCamelCaseToTitleCase(col.label) };
|
|
19077
|
-
});
|
|
19078
|
-
const columnInternal = (item.includeCustomFields ? columnsWithCustomFields : item.columns).map((col) => {
|
|
19079
|
-
const field = item.fields?.find((f) => f.name === col.field);
|
|
19080
|
-
const converted_field = convertPostgresColumn(field ?? {});
|
|
19081
|
-
return {
|
|
19082
|
-
fieldType: converted_field.fieldType,
|
|
19083
|
-
dataTypeID: converted_field.dataTypeID,
|
|
19084
|
-
jsType: converted_field.jsType,
|
|
19085
|
-
...col,
|
|
19086
|
-
label: snakeAndCamelCaseToTitleCase(col.label)
|
|
19087
|
-
};
|
|
19088
|
-
});
|
|
19089
|
-
let pivotTable;
|
|
19090
|
-
let pivotError;
|
|
19091
|
-
try {
|
|
19092
|
-
const shouldPaginatePivotAsTable = item.chartType === "table";
|
|
19093
|
-
const pivotChartProcessing = {
|
|
19094
|
-
page: DEFAULT_PAGINATION
|
|
19095
|
-
};
|
|
19096
|
-
pivotTable = await getPivotTable(
|
|
19097
|
-
{
|
|
19098
|
-
...item,
|
|
19099
|
-
pivot: item.pivot && !skipPivotFetch ? {
|
|
19100
|
-
...item.pivot,
|
|
19101
|
-
aggregations: item.pivot.aggregations ?? [
|
|
19102
|
-
{
|
|
19103
|
-
valueField: item.pivot.valueField,
|
|
19104
|
-
valueFieldType: item.pivot.valueFieldType,
|
|
19105
|
-
valueField2: item.pivot.valueField2,
|
|
19106
|
-
valueField2Type: item.pivot.valueField2Type,
|
|
19107
|
-
aggregationType: item.pivot.aggregationType
|
|
19108
|
-
}
|
|
19109
|
-
]
|
|
19110
|
-
} : void 0
|
|
19111
|
-
},
|
|
19112
|
-
dashboardFilters,
|
|
19113
|
-
item.dashboardName,
|
|
19114
|
-
getToken,
|
|
19115
|
-
client,
|
|
19116
|
-
eventTracking,
|
|
19117
|
-
dateBucket,
|
|
19118
|
-
shouldPaginatePivotAsTable ? additionalProcessing : pivotChartProcessing,
|
|
19119
|
-
tenants,
|
|
19120
|
-
customFields
|
|
19121
|
-
);
|
|
19122
|
-
} catch (e) {
|
|
19123
|
-
pivotTable = void 0;
|
|
19124
|
-
eventTracking?.logError?.({
|
|
19125
|
-
type: "bug",
|
|
19126
|
-
// TODO: determine type
|
|
19127
|
-
severity: "high",
|
|
19128
|
-
message: "Error fetching pivot table",
|
|
19129
|
-
errorMessage: e.message,
|
|
19130
|
-
errorStack: e.stack,
|
|
19131
|
-
errorData: {
|
|
19132
|
-
caller: "cleanDashboardItem",
|
|
19133
|
-
function: "cleanDashboardItem"
|
|
19134
|
-
}
|
|
19135
|
-
});
|
|
19136
|
-
console.error("Error fetching pivot table", e);
|
|
19137
|
-
pivotError = "Error fetching pivot table";
|
|
19138
|
-
}
|
|
19139
|
-
const referenceLineYValues = [];
|
|
19140
|
-
for (const key in item) {
|
|
19141
|
-
if (key.startsWith("referenceLine_")) {
|
|
19142
|
-
const field = key.slice(14);
|
|
19143
|
-
if (!item[key] || !item[key][0]) continue;
|
|
19144
|
-
const value = Object.values(item[key][0])[0];
|
|
19145
|
-
referenceLineYValues.push({ label: field, query: [value, value] });
|
|
19146
|
-
}
|
|
19147
|
-
}
|
|
19148
|
-
if (item.referenceLines) {
|
|
19149
|
-
for (const referenceLine of item.referenceLines) {
|
|
19150
|
-
if (Array.isArray(referenceLine.query)) {
|
|
19151
|
-
referenceLineYValues.push({
|
|
19152
|
-
label: referenceLine.label,
|
|
19153
|
-
query: referenceLine.query
|
|
19154
|
-
});
|
|
19155
|
-
} else if (referenceLine.query === "") {
|
|
19156
|
-
referenceLineYValues.push({
|
|
19157
|
-
label: referenceLine.label,
|
|
19158
|
-
query: (pivotTable?.rows ? pivotTable.rows : item.rows).map(
|
|
19159
|
-
(row) => Number(row[referenceLine.label]) || 0
|
|
19160
|
-
)
|
|
19161
|
-
});
|
|
19162
|
-
}
|
|
19163
|
-
}
|
|
19164
|
-
}
|
|
19165
|
-
return {
|
|
19166
|
-
id: item._id ?? item.id,
|
|
19167
|
-
name: item.name,
|
|
19168
|
-
dashboardName: item.dashboardName,
|
|
19169
|
-
// section: item.section,
|
|
19170
|
-
rows: item.rows,
|
|
19171
|
-
pivotRows: pivotTable ? pivotTable.rows : void 0,
|
|
19172
|
-
pivotColumns: pivotTable ? pivotTable.columns : void 0,
|
|
19173
|
-
compareRows: item.compareRows,
|
|
19174
|
-
columns: processedColumns.map((column) => {
|
|
19175
|
-
return {
|
|
19176
|
-
field: column.field,
|
|
19177
|
-
format: column.format,
|
|
19178
|
-
label: column.label,
|
|
19179
|
-
inferFormat: column.inferFormat
|
|
19180
|
-
};
|
|
19181
|
-
}),
|
|
19182
|
-
includeCustomFields: item.includeCustomFields,
|
|
19183
|
-
columnInternal,
|
|
19184
|
-
columnsWithCustomFields,
|
|
19185
|
-
chartType: item.chartType,
|
|
19186
|
-
dateField: item.dateField,
|
|
19187
|
-
pivot: pivotError ? void 0 : item.pivot ? {
|
|
19188
|
-
...item.pivot,
|
|
19189
|
-
aggregations: item.pivot.aggregations ?? [
|
|
19190
|
-
{
|
|
19191
|
-
valueField: item.pivot.valueField,
|
|
19192
|
-
valueFieldType: item.pivot.valueFieldType,
|
|
19193
|
-
valueField2: item.pivot.valueField2,
|
|
19194
|
-
valueField2Type: item.pivot.valueField2Type,
|
|
19195
|
-
aggregationType: item.pivot.aggregationType
|
|
19196
|
-
}
|
|
19197
|
-
],
|
|
19198
|
-
columnValues: item.distinctStrings
|
|
19199
|
-
} : void 0,
|
|
19200
|
-
yAxisFields: pivotTable ? extractPivotedYAxis(pivotTable, item) : item.yAxisFields,
|
|
19201
|
-
xAxisLabel: item.xAxisLabel,
|
|
19202
|
-
xAxisField: item.xAxisField,
|
|
19203
|
-
xAxisFormat: item.xAxisFormat,
|
|
19204
|
-
order: item.order,
|
|
19205
|
-
filtersApplied: item.filtersApplied,
|
|
19206
|
-
filterMap: item.filterMap,
|
|
19207
|
-
flags: item.flags,
|
|
19208
|
-
rowCount: item.rowCount ? parseInt(item.rowCount) : item.rows.length,
|
|
19209
|
-
pivotRowCount: pivotTable ? pivotTable.rowCount : void 0,
|
|
19210
|
-
template: item.template,
|
|
19211
|
-
sort: item.sort,
|
|
19212
|
-
itemQuery: item.itemQuery,
|
|
19213
|
-
queryString: item.queryString,
|
|
19214
|
-
pivotQuery: pivotTable?.pivotQuery,
|
|
19215
|
-
comparisonPivotQuery: pivotTable?.comparisonPivotQuery,
|
|
19216
|
-
referencedTables: item?.referencedTables || [],
|
|
19217
|
-
referencedColumns: item?.referencedColumns || {},
|
|
19218
|
-
error: item.error ?? pivotError,
|
|
19219
|
-
referenceLineYValues,
|
|
19220
|
-
referenceLines: item.referenceLines
|
|
19221
|
-
};
|
|
19222
|
-
}
|
|
19223
|
-
async function getPivotTable(report, dashboardFilters, dashboardName, getToken, client, eventTracking, dateBucketInitial, additionalProcessing, tenants, customFields) {
|
|
19224
|
-
if (!report) return void 0;
|
|
19225
|
-
const dateFilter = Object.values(dashboardFilters ?? {}).find(
|
|
19226
|
-
(filter) => filter.filterType === "date_range" || filter.operator === "BETWEEN"
|
|
19227
|
-
);
|
|
19228
|
-
if (dateFilter?.operator === "BETWEEN") {
|
|
19229
|
-
dateFilter.startDate = dateFilter.value[0];
|
|
19230
|
-
dateFilter.endDate = dateFilter.value[1];
|
|
19231
|
-
}
|
|
19232
|
-
const pivot = report?.pivot;
|
|
19233
|
-
const data = report || {};
|
|
19234
|
-
if (pivot && client) {
|
|
19235
|
-
if (report.rowCount === 0 || report.rows.length === 0) {
|
|
19236
|
-
const columns = [];
|
|
19237
|
-
if (pivot.rowField) {
|
|
19238
|
-
columns.push({
|
|
19239
|
-
field: pivot.rowField,
|
|
19240
|
-
label: snakeCaseToTitleCase(processColumnName(pivot.rowField)),
|
|
19241
|
-
format: pivot.rowFieldType || "string",
|
|
19242
|
-
jsType: convertFieldTypeToJSType(pivot.rowFieldType || "string"),
|
|
19243
|
-
fieldType: pivot.rowFieldType || "string",
|
|
19244
|
-
dataTypeID: fieldTypeToDataTypeID(pivot.rowFieldType || "string")
|
|
19245
|
-
});
|
|
19246
|
-
}
|
|
19247
|
-
for (const agg of pivot.aggregations ?? []) {
|
|
19248
|
-
if (agg.valueField) {
|
|
19249
|
-
columns.push({
|
|
19250
|
-
field: agg.valueField,
|
|
19251
|
-
label: snakeCaseToTitleCase(processColumnName(agg.valueField)),
|
|
19252
|
-
//FIXME: valueFieldType is not always the same as the format
|
|
19253
|
-
format: agg.valueFieldType ?? "whole_number",
|
|
19254
|
-
jsType: agg.valueFieldType ?? "number",
|
|
19255
|
-
fieldType: agg.valueFieldType ?? "number",
|
|
19256
|
-
dataTypeID: fieldTypeToDataTypeID(agg.valueFieldType ?? "number")
|
|
19257
|
-
});
|
|
19258
|
-
}
|
|
19259
|
-
}
|
|
19260
|
-
const pivotQuery = generatePivotQuery(
|
|
19261
|
-
pivot,
|
|
19262
|
-
report.itemQuery?.[0],
|
|
19263
|
-
client.databaseType
|
|
19264
|
-
);
|
|
19265
|
-
return {
|
|
19266
|
-
rows: [],
|
|
19267
|
-
rowCount: 0,
|
|
19268
|
-
pivotQuery: pivotQuery ?? "",
|
|
19269
|
-
columns
|
|
19270
|
-
};
|
|
19271
|
-
}
|
|
19272
|
-
try {
|
|
19273
|
-
let dateBucket = dateBucketInitial;
|
|
19274
|
-
let filterDateRange = void 0;
|
|
19275
|
-
if (dateFilter && dateFilter.startDate && dateFilter.endDate) {
|
|
19276
|
-
filterDateRange = {
|
|
19277
|
-
start: dateFilter.startDate,
|
|
19278
|
-
end: dateFilter.endDate
|
|
19279
|
-
};
|
|
19280
|
-
} else if (report.dateRange) {
|
|
19281
|
-
filterDateRange = report.dateRange;
|
|
19282
|
-
}
|
|
19283
|
-
if (!dateBucket && filterDateRange) {
|
|
19284
|
-
dateBucket = getDateBucketFromRange(filterDateRange);
|
|
19285
|
-
}
|
|
19286
|
-
if (pivot.columnField && !report.distinctStrings) {
|
|
19287
|
-
const columnFieldColumn = (report.columnsWithCustomFields ?? report.columns).find((col) => col.field === pivot.columnField);
|
|
19288
|
-
if (!columnFieldColumn) {
|
|
19289
|
-
console.error(
|
|
19290
|
-
"could not find pivot column field on report",
|
|
19291
|
-
pivot.columnField
|
|
19292
|
-
);
|
|
19293
|
-
}
|
|
19294
|
-
const unique = await getUniqueValuesByQuery({
|
|
19295
|
-
columns: [columnFieldColumn],
|
|
19296
|
-
query: report.queryString,
|
|
19297
|
-
client,
|
|
19298
|
-
getToken,
|
|
19299
|
-
dashboardName,
|
|
19300
|
-
tenants,
|
|
19301
|
-
customFields: customFields ?? {},
|
|
19302
|
-
eventTracking
|
|
19303
|
-
});
|
|
19304
|
-
report.distinctStrings = unique?.[pivot.columnField] ?? [];
|
|
19305
|
-
}
|
|
19306
|
-
if (pivot.columnField && !report.distinctStrings) {
|
|
19307
|
-
const columnFieldColumn = (report.columnsWithCustomFields ?? report.columns).find((col) => col.field === pivot.columnField);
|
|
19308
|
-
if (!columnFieldColumn) {
|
|
19309
|
-
console.error(
|
|
19310
|
-
"could not find pivot column field on report",
|
|
19311
|
-
pivot.columnField
|
|
19312
|
-
);
|
|
19313
|
-
}
|
|
19314
|
-
const unique = await getUniqueValuesByQuery({
|
|
19315
|
-
columns: [columnFieldColumn],
|
|
19316
|
-
query: report.queryString,
|
|
19317
|
-
client,
|
|
19318
|
-
getToken,
|
|
19319
|
-
dashboardName,
|
|
19320
|
-
tenants,
|
|
19321
|
-
customFields: customFields ?? {},
|
|
19322
|
-
eventTracking
|
|
19323
|
-
});
|
|
19324
|
-
report.distinctStrings = unique?.[pivot.columnField] ?? [];
|
|
19325
|
-
}
|
|
19326
|
-
const pivotTable = await generatePivotWithSQL({
|
|
19327
|
-
pivot,
|
|
19328
|
-
report,
|
|
19329
|
-
client,
|
|
19330
|
-
dateBucket,
|
|
19331
|
-
dateFilter,
|
|
19332
|
-
distinctStrings: report.distinctStrings,
|
|
19333
|
-
dashboardName,
|
|
19334
|
-
tenants,
|
|
19335
|
-
additionalProcessing,
|
|
19336
|
-
getToken
|
|
19337
|
-
});
|
|
19338
|
-
return pivotTable;
|
|
19339
|
-
} catch (e) {
|
|
19340
|
-
eventTracking?.logError?.({
|
|
19341
|
-
type: "bug",
|
|
19342
|
-
// TODO: determine type
|
|
19343
|
-
severity: "high",
|
|
19344
|
-
message: "Error fetching pivot table",
|
|
19345
|
-
errorMessage: e.message,
|
|
19346
|
-
errorStack: e.stack,
|
|
19347
|
-
errorData: {
|
|
19348
|
-
caller: "getPivotTable",
|
|
19349
|
-
function: "getPivotTable"
|
|
19350
|
-
}
|
|
19351
|
-
});
|
|
19352
|
-
console.error("Error fetching pivot table", e);
|
|
19353
|
-
throw e;
|
|
19354
|
-
}
|
|
19355
|
-
}
|
|
19356
|
-
return pivot && data.rows ? generatePivotTable({
|
|
19357
|
-
pivot,
|
|
19358
|
-
report,
|
|
19359
|
-
client,
|
|
19360
|
-
uniqueValues: report.distinctStrings,
|
|
19361
|
-
dashboardName,
|
|
19362
|
-
tenants,
|
|
19363
|
-
dateFilter,
|
|
19364
|
-
additionalProcessing,
|
|
19365
|
-
getToken,
|
|
19366
|
-
eventTracking
|
|
19367
|
-
}) : void 0;
|
|
19368
|
-
}
|
|
19369
|
-
function extractPivotedYAxis(pivotTable, itemInfo, config = void 0) {
|
|
19370
|
-
if (!pivotTable) return itemInfo?.yAxisFields ?? [];
|
|
19371
|
-
const pivot = itemInfo?.pivot || config?.pivot;
|
|
19372
|
-
if (!pivot.columnField && !pivot.rowField) return itemInfo?.yAxisFields ?? [];
|
|
19373
|
-
const yAxisFields = config ? config.yAxisFields : itemInfo?.yAxisFields;
|
|
19374
|
-
return yAxisFields && yAxisFields.length > 0 ? generatePivotTableYAxis(pivot, pivotTable.columns, yAxisFields[0]) : yAxisFields;
|
|
19375
|
-
}
|
|
19376
|
-
async function getDashboard(dashboardName, client, getToken, tenants, flags) {
|
|
19377
|
-
const { data: resp } = await quillFetch({
|
|
19378
|
-
client,
|
|
19379
|
-
task: "dashboard",
|
|
19380
|
-
metadata: {
|
|
19381
|
-
name: dashboardName,
|
|
19382
|
-
clientId: client.publicKey,
|
|
19383
|
-
databaseType: client.databaseType,
|
|
19384
|
-
useNewNodeSql: true,
|
|
19385
|
-
tenants,
|
|
19386
|
-
flags
|
|
19387
|
-
},
|
|
19388
|
-
getToken
|
|
19389
|
-
});
|
|
19390
|
-
return {
|
|
19391
|
-
...resp,
|
|
19392
|
-
createdAt: resp.createdAt && new Date(resp.createdAt),
|
|
19393
|
-
dateFilter: resp.dateFilter ? {
|
|
19394
|
-
...resp.dateFilter,
|
|
19395
|
-
presetOptions: resp.dateFilter.presetOptions?.map(
|
|
19396
|
-
(preset) => ({
|
|
19397
|
-
...preset,
|
|
19398
|
-
loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
|
|
19399
|
-
loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
|
|
19400
|
-
})
|
|
19401
|
-
),
|
|
19402
|
-
defaultPresetRanges: resp.dateFilter.defaultPresetRanges?.map(
|
|
19403
|
-
(preset) => ({
|
|
19404
|
-
...preset,
|
|
19405
|
-
loopStart: preset.loopStart ? new Date(preset.loopStart) : void 0,
|
|
19406
|
-
loopEnd: preset.loopEnd ? new Date(preset.loopEnd) : void 0
|
|
19407
|
-
})
|
|
19408
|
-
)
|
|
19409
|
-
} : void 0
|
|
19410
|
-
};
|
|
19411
|
-
}
|
|
19412
|
-
|
|
19413
|
-
// src/utils/chartBuilder.ts
|
|
19414
|
-
var numberFormatOptions = [
|
|
19415
|
-
"whole_number",
|
|
19416
|
-
"one_decimal_place",
|
|
19417
|
-
"two_decimal_places",
|
|
19418
|
-
"dollar_amount",
|
|
19419
|
-
"dollar_cents",
|
|
19420
|
-
"percentage"
|
|
19421
|
-
];
|
|
19422
|
-
var dateFormatOptions = [
|
|
19423
|
-
"MMM_yyyy",
|
|
19424
|
-
"MMM_dd",
|
|
19425
|
-
"MMM_dd_yyyy",
|
|
19426
|
-
"MMM_dd_hh:mm_ap_pm",
|
|
19427
|
-
"hh_ap_pm",
|
|
19428
|
-
"date",
|
|
19429
|
-
"timestamptz"
|
|
19430
|
-
];
|
|
19431
|
-
var NUMBER_OPTIONS = [
|
|
19432
|
-
{ value: "whole_number", label: "whole number" },
|
|
19433
|
-
{ value: "one_decimal_place", label: "one decimal place" },
|
|
19434
|
-
{ value: "two_decimal_places", label: "two decimal places" },
|
|
19435
|
-
{ value: "dollar_amount", label: "dollar amount" },
|
|
19436
|
-
{ value: "dollar_cents", label: "dollar and cent amount" },
|
|
19437
|
-
{ value: "percent", label: "percentage" }
|
|
19438
|
-
];
|
|
19439
|
-
var DATE_OPTIONS = [
|
|
19440
|
-
{ value: "MMM_yyyy", label: "month" },
|
|
19441
|
-
{ value: "MMM_dd", label: "day" },
|
|
19442
|
-
{ value: "MMM_dd_yyyy", label: "day and year" },
|
|
19443
|
-
{ value: "MMM_dd_hh:mm_ap_pm", label: "day and time" },
|
|
19444
|
-
{ value: "hh_ap_pm", label: "hour" }
|
|
19445
|
-
];
|
|
19446
|
-
var ALL_FORMAT_OPTIONS = [
|
|
19447
|
-
...NUMBER_OPTIONS,
|
|
19448
|
-
...DATE_OPTIONS,
|
|
19449
|
-
{ value: "string", label: "string" }
|
|
19450
|
-
];
|
|
19451
|
-
function createInitialFormData(columns) {
|
|
19452
|
-
const firstNumberColumn = columns?.find(
|
|
19453
|
-
(col) => numberFormatOptions.includes(col.format)
|
|
19454
|
-
);
|
|
19455
|
-
const firstStringColumn = columns?.find(
|
|
19456
|
-
(col) => !numberFormatOptions.includes(col.format) && !dateFormatOptions.includes(col.format)
|
|
19457
|
-
);
|
|
19458
|
-
const firstDateColumn = columns?.find(
|
|
19459
|
-
(col) => dateFormatOptions.includes(col.format)
|
|
19460
|
-
);
|
|
19461
|
-
const xAxisField = firstStringColumn?.field || firstDateColumn?.field || firstNumberColumn?.field || columns?.[0]?.field || "";
|
|
19462
|
-
const xAxisFormat = firstStringColumn?.format || firstDateColumn?.format || firstNumberColumn?.format || columns?.[0]?.format || "string";
|
|
19463
|
-
const formEmptyState = {
|
|
19464
|
-
name: "",
|
|
19465
|
-
columns: columns.map((col) => {
|
|
19466
|
-
return { ...col, label: snakeAndCamelCaseToTitleCase(col.label) };
|
|
19467
|
-
}),
|
|
19468
|
-
xAxisField,
|
|
19469
|
-
xAxisFormat,
|
|
19470
|
-
yAxisFields: [
|
|
19471
|
-
{
|
|
19472
|
-
field: firstNumberColumn?.field || columns?.[0]?.field || "",
|
|
19473
|
-
label: "",
|
|
19474
|
-
format: firstNumberColumn?.format || columns?.[0]?.format || "string"
|
|
19475
|
-
}
|
|
19476
|
-
],
|
|
19477
|
-
xAxisLabel: "",
|
|
19478
|
-
chartType: firstNumberColumn ? "line" : "table",
|
|
19479
|
-
pivot: null,
|
|
19480
|
-
template: true,
|
|
19481
|
-
referenceLines: []
|
|
19482
|
-
};
|
|
19483
|
-
return formEmptyState;
|
|
19484
|
-
}
|
|
19485
|
-
|
|
19486
|
-
// src/utils/error.ts
|
|
19487
|
-
var DataLoadError = class extends Error {
|
|
19488
|
-
data;
|
|
19489
|
-
constructor(message, data) {
|
|
19490
|
-
super(message);
|
|
19491
|
-
this.name = "DataLoadError";
|
|
19492
|
-
this.data = data;
|
|
19493
|
-
}
|
|
19494
|
-
};
|
|
19495
|
-
|
|
19496
18294
|
// src/components/ReportBuilder/convert.ts
|
|
19497
18295
|
import { isValid as isValid3, parseISO as parseISO2 } from "date-fns";
|
|
19498
18296
|
function recursiveSearchAndReplace(node, search, replace) {
|
|
@@ -23144,6 +21942,35 @@ import jsPDF from "jspdf";
|
|
|
23144
21942
|
|
|
23145
21943
|
// src/hooks/useDashboard.ts
|
|
23146
21944
|
import { useContext, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
21945
|
+
|
|
21946
|
+
// src/utils/merge.ts
|
|
21947
|
+
import {
|
|
21948
|
+
add,
|
|
21949
|
+
startOfDay as startOfDay3,
|
|
21950
|
+
startOfMonth,
|
|
21951
|
+
startOfWeek as startOfWeek3,
|
|
21952
|
+
startOfYear
|
|
21953
|
+
} from "date-fns";
|
|
21954
|
+
import { utcToZonedTime as utcToZonedTime2 } from "date-fns-tz";
|
|
21955
|
+
function mergeComparisonRange(resp) {
|
|
21956
|
+
if (resp.chartType === "table") return resp;
|
|
21957
|
+
const compRows = resp.compareRows;
|
|
21958
|
+
if (!compRows) return resp;
|
|
21959
|
+
const newRows = resp.rows.map((row, i) => {
|
|
21960
|
+
if (i < compRows.length) {
|
|
21961
|
+
const compRow = compRows[i];
|
|
21962
|
+
const newRow = { ...row };
|
|
21963
|
+
for (const [key, value] of Object.entries(compRow)) {
|
|
21964
|
+
newRow[`comparison_${key}`] = value;
|
|
21965
|
+
}
|
|
21966
|
+
return newRow;
|
|
21967
|
+
}
|
|
21968
|
+
return row;
|
|
21969
|
+
});
|
|
21970
|
+
return { ...resp, rows: newRows };
|
|
21971
|
+
}
|
|
21972
|
+
|
|
21973
|
+
// src/hooks/useDashboard.ts
|
|
23147
21974
|
var useDashboardInternal = (dashboardName, customFilters) => {
|
|
23148
21975
|
const [dashboard] = useContext(DashboardContext);
|
|
23149
21976
|
const {
|
|
@@ -39043,6 +37870,22 @@ import {
|
|
|
39043
37870
|
useContext as useContext26,
|
|
39044
37871
|
useMemo as useMemo21
|
|
39045
37872
|
} from "react";
|
|
37873
|
+
import {
|
|
37874
|
+
closestCenter,
|
|
37875
|
+
DndContext,
|
|
37876
|
+
KeyboardSensor,
|
|
37877
|
+
PointerSensor,
|
|
37878
|
+
useSensor,
|
|
37879
|
+
useSensors
|
|
37880
|
+
} from "@dnd-kit/core";
|
|
37881
|
+
import {
|
|
37882
|
+
arrayMove,
|
|
37883
|
+
SortableContext,
|
|
37884
|
+
sortableKeyboardCoordinates,
|
|
37885
|
+
verticalListSortingStrategy,
|
|
37886
|
+
useSortable
|
|
37887
|
+
} from "@dnd-kit/sortable";
|
|
37888
|
+
import { CSS as DND_CSS } from "@dnd-kit/utilities";
|
|
39046
37889
|
|
|
39047
37890
|
// src/internals/ReportBuilder/PivotModal.tsx
|
|
39048
37891
|
import {
|
|
@@ -42312,6 +41155,173 @@ var CHART_TO_LABELS = {
|
|
|
42312
41155
|
"World map": { xAxisLabel: "Country", yAxisLabel: "Value" },
|
|
42313
41156
|
gauge: { xAxisLabel: "Value" }
|
|
42314
41157
|
};
|
|
41158
|
+
function SortableColumnItem({
|
|
41159
|
+
column,
|
|
41160
|
+
index,
|
|
41161
|
+
rows,
|
|
41162
|
+
columns,
|
|
41163
|
+
handleChange,
|
|
41164
|
+
deleteRef,
|
|
41165
|
+
deleteButtonMargin,
|
|
41166
|
+
handleRemoveField,
|
|
41167
|
+
SelectComponent,
|
|
41168
|
+
TextInputComponent,
|
|
41169
|
+
DeleteButtonComponent
|
|
41170
|
+
}) {
|
|
41171
|
+
const { attributes, listeners, setNodeRef, transform, transition: transition2 } = useSortable({ id: column.field });
|
|
41172
|
+
const style2 = {
|
|
41173
|
+
transform: DND_CSS.Transform.toString(transform),
|
|
41174
|
+
transition: transition2
|
|
41175
|
+
};
|
|
41176
|
+
return /* @__PURE__ */ jsx65("div", { style: style2, ref: setNodeRef, children: /* @__PURE__ */ jsxs47(
|
|
41177
|
+
"div",
|
|
41178
|
+
{
|
|
41179
|
+
style: {
|
|
41180
|
+
display: "flex",
|
|
41181
|
+
alignItems: "center",
|
|
41182
|
+
gap: 4
|
|
41183
|
+
},
|
|
41184
|
+
children: [
|
|
41185
|
+
/* @__PURE__ */ jsxs47(
|
|
41186
|
+
"div",
|
|
41187
|
+
{
|
|
41188
|
+
style: {
|
|
41189
|
+
cursor: "grab",
|
|
41190
|
+
display: "flex",
|
|
41191
|
+
gap: 2,
|
|
41192
|
+
flexDirection: "row",
|
|
41193
|
+
paddingTop: 8,
|
|
41194
|
+
paddingBottom: 8,
|
|
41195
|
+
paddingLeft: 8,
|
|
41196
|
+
paddingRight: 8,
|
|
41197
|
+
borderRadius: 4
|
|
41198
|
+
},
|
|
41199
|
+
className: "handle",
|
|
41200
|
+
...attributes,
|
|
41201
|
+
...listeners,
|
|
41202
|
+
children: [
|
|
41203
|
+
/* @__PURE__ */ jsx65("style", { children: `.handle{background:white;} .handle:hover{background:rgba(0,0,0,0.03);}` }),
|
|
41204
|
+
/* @__PURE__ */ jsxs47("div", { style: { display: "flex", gap: 2, flexDirection: "column" }, children: [
|
|
41205
|
+
/* @__PURE__ */ jsx65(
|
|
41206
|
+
"div",
|
|
41207
|
+
{
|
|
41208
|
+
style: {
|
|
41209
|
+
width: 3,
|
|
41210
|
+
height: 3,
|
|
41211
|
+
borderRadius: 3,
|
|
41212
|
+
background: "#9CA0A7"
|
|
41213
|
+
}
|
|
41214
|
+
}
|
|
41215
|
+
),
|
|
41216
|
+
/* @__PURE__ */ jsx65(
|
|
41217
|
+
"div",
|
|
41218
|
+
{
|
|
41219
|
+
style: {
|
|
41220
|
+
width: 3,
|
|
41221
|
+
height: 3,
|
|
41222
|
+
borderRadius: 3,
|
|
41223
|
+
background: "#9CA0A7"
|
|
41224
|
+
}
|
|
41225
|
+
}
|
|
41226
|
+
),
|
|
41227
|
+
/* @__PURE__ */ jsx65(
|
|
41228
|
+
"div",
|
|
41229
|
+
{
|
|
41230
|
+
style: {
|
|
41231
|
+
width: 3,
|
|
41232
|
+
height: 3,
|
|
41233
|
+
borderRadius: 3,
|
|
41234
|
+
background: "#9CA0A7"
|
|
41235
|
+
}
|
|
41236
|
+
}
|
|
41237
|
+
)
|
|
41238
|
+
] }),
|
|
41239
|
+
/* @__PURE__ */ jsxs47("div", { style: { display: "flex", gap: 2, flexDirection: "column" }, children: [
|
|
41240
|
+
/* @__PURE__ */ jsx65(
|
|
41241
|
+
"div",
|
|
41242
|
+
{
|
|
41243
|
+
style: {
|
|
41244
|
+
width: 3,
|
|
41245
|
+
height: 3,
|
|
41246
|
+
borderRadius: 3,
|
|
41247
|
+
background: "#9CA0A7"
|
|
41248
|
+
}
|
|
41249
|
+
}
|
|
41250
|
+
),
|
|
41251
|
+
/* @__PURE__ */ jsx65(
|
|
41252
|
+
"div",
|
|
41253
|
+
{
|
|
41254
|
+
style: {
|
|
41255
|
+
width: 3,
|
|
41256
|
+
height: 3,
|
|
41257
|
+
borderRadius: 3,
|
|
41258
|
+
background: "#9CA0A7"
|
|
41259
|
+
}
|
|
41260
|
+
}
|
|
41261
|
+
),
|
|
41262
|
+
/* @__PURE__ */ jsx65(
|
|
41263
|
+
"div",
|
|
41264
|
+
{
|
|
41265
|
+
style: {
|
|
41266
|
+
width: 3,
|
|
41267
|
+
height: 3,
|
|
41268
|
+
borderRadius: 3,
|
|
41269
|
+
background: "#9CA0A7"
|
|
41270
|
+
}
|
|
41271
|
+
}
|
|
41272
|
+
)
|
|
41273
|
+
] })
|
|
41274
|
+
]
|
|
41275
|
+
}
|
|
41276
|
+
),
|
|
41277
|
+
/* @__PURE__ */ jsxs47("div", { style: { flex: 1, display: "flex", gap: 12 }, children: [
|
|
41278
|
+
/* @__PURE__ */ jsx65(
|
|
41279
|
+
SelectComponent,
|
|
41280
|
+
{
|
|
41281
|
+
value: column.field,
|
|
41282
|
+
onChange: (e) => handleChange(e.target.value, "columns.field", index),
|
|
41283
|
+
options: rows[0] ? Object.keys(rows[0]).map((elem) => ({
|
|
41284
|
+
label: elem,
|
|
41285
|
+
value: elem
|
|
41286
|
+
})) : columns.map((elem) => ({
|
|
41287
|
+
label: elem.field,
|
|
41288
|
+
value: elem.field
|
|
41289
|
+
})),
|
|
41290
|
+
width: 200,
|
|
41291
|
+
hideEmptyOption: true
|
|
41292
|
+
}
|
|
41293
|
+
),
|
|
41294
|
+
/* @__PURE__ */ jsx65(
|
|
41295
|
+
TextInputComponent,
|
|
41296
|
+
{
|
|
41297
|
+
id: `chart-builder-column-label-${index}`,
|
|
41298
|
+
width: 200,
|
|
41299
|
+
value: column.label,
|
|
41300
|
+
placeholder: "Column Label",
|
|
41301
|
+
onChange: (e) => handleChange(e.target.value, "columns.label", index)
|
|
41302
|
+
}
|
|
41303
|
+
),
|
|
41304
|
+
/* @__PURE__ */ jsx65(
|
|
41305
|
+
SelectComponent,
|
|
41306
|
+
{
|
|
41307
|
+
value: column.format,
|
|
41308
|
+
onChange: (e) => handleChange(e.target.value, "columns.format", index),
|
|
41309
|
+
options: ALL_FORMAT_OPTIONS,
|
|
41310
|
+
width: 200,
|
|
41311
|
+
hideEmptyOption: true
|
|
41312
|
+
}
|
|
41313
|
+
),
|
|
41314
|
+
/* @__PURE__ */ jsx65("div", { ref: deleteRef, style: { marginLeft: deleteButtonMargin }, children: /* @__PURE__ */ jsx65(
|
|
41315
|
+
DeleteButtonComponent,
|
|
41316
|
+
{
|
|
41317
|
+
onClick: () => handleRemoveField("columns", index)
|
|
41318
|
+
}
|
|
41319
|
+
) })
|
|
41320
|
+
] })
|
|
41321
|
+
]
|
|
41322
|
+
}
|
|
41323
|
+
) });
|
|
41324
|
+
}
|
|
42315
41325
|
function getPivotMetricOptions(pivot, selectedPivotTable, chartType) {
|
|
42316
41326
|
if (["metric", "gauge"].includes(chartType) && selectedPivotTable) {
|
|
42317
41327
|
return selectedPivotTable.columns.map((elem) => ({
|
|
@@ -42520,7 +41530,6 @@ function ChartBuilder({
|
|
|
42520
41530
|
}, [reportId]);
|
|
42521
41531
|
const [windowWidth, setWindowWidth] = useState28(1200);
|
|
42522
41532
|
const [rows, setRows] = useState28(report?.rows ?? []);
|
|
42523
|
-
const [itemQuery, setItemQuery] = useState28(report?.itemQuery);
|
|
42524
41533
|
const [rowCount, setRowCount] = useState28(report?.rowCount ?? 0);
|
|
42525
41534
|
const [maxPage, setMaxPage] = useState28(0);
|
|
42526
41535
|
const [isLoading, setIsLoading] = useState28(false);
|
|
@@ -43250,7 +42259,7 @@ function ChartBuilder({
|
|
|
43250
42259
|
pivot,
|
|
43251
42260
|
dateBucket,
|
|
43252
42261
|
dateFilter,
|
|
43253
|
-
report: report ? { ...report, ...tableInfo
|
|
42262
|
+
report: report ? { ...report, ...tableInfo } : void 0,
|
|
43254
42263
|
client,
|
|
43255
42264
|
uniqueValues,
|
|
43256
42265
|
dashboardName: destinationDashboardName,
|
|
@@ -43411,7 +42420,6 @@ function ChartBuilder({
|
|
|
43411
42420
|
setCurrentProcessing(processing);
|
|
43412
42421
|
setRows(tableInfo.rows);
|
|
43413
42422
|
setProcessedColumns(processColumns(tableInfo.columns));
|
|
43414
|
-
setItemQuery(tableInfo.itemQuery);
|
|
43415
42423
|
fetchRowCount(processing, overrideFilters);
|
|
43416
42424
|
if (formData.pivot) {
|
|
43417
42425
|
try {
|
|
@@ -43777,6 +42785,26 @@ function ChartBuilder({
|
|
|
43777
42785
|
);
|
|
43778
42786
|
setFormData({ ...formData, [fieldName]: updatedArray });
|
|
43779
42787
|
};
|
|
42788
|
+
const columnDragSensors = useSensors(
|
|
42789
|
+
useSensor(PointerSensor),
|
|
42790
|
+
useSensor(KeyboardSensor, {
|
|
42791
|
+
coordinateGetter: sortableKeyboardCoordinates
|
|
42792
|
+
})
|
|
42793
|
+
);
|
|
42794
|
+
const handleColumnDragEnd = (event) => {
|
|
42795
|
+
const { active, over } = event;
|
|
42796
|
+
if (!active || !over) return;
|
|
42797
|
+
if (active.id !== over.id) {
|
|
42798
|
+
const oldIndex = formData.columns.findIndex(
|
|
42799
|
+
(col) => col.field === active.id
|
|
42800
|
+
);
|
|
42801
|
+
const newIndex = formData.columns.findIndex(
|
|
42802
|
+
(col) => col.field === over.id
|
|
42803
|
+
);
|
|
42804
|
+
const newColumns = arrayMove(formData.columns, oldIndex, newIndex);
|
|
42805
|
+
setFormData({ ...formData, columns: newColumns });
|
|
42806
|
+
}
|
|
42807
|
+
};
|
|
43780
42808
|
const handleSubmit = (event) => {
|
|
43781
42809
|
event.preventDefault();
|
|
43782
42810
|
};
|
|
@@ -44297,7 +43325,7 @@ function ChartBuilder({
|
|
|
44297
43325
|
uniqueValuesIsLoading: initialUniqueValuesIsLoading,
|
|
44298
43326
|
initialSelectedPivotTable: selectedPivotTable,
|
|
44299
43327
|
pivotRecommendationsEnabled,
|
|
44300
|
-
report
|
|
43328
|
+
report,
|
|
44301
43329
|
dashboardName: destinationDashboardName || "",
|
|
44302
43330
|
dateFilter: filtersEnabled ? currentDashboardFilters?.find(
|
|
44303
43331
|
(f) => f.filterType === "date_range"
|
|
@@ -44685,141 +43713,98 @@ function ChartBuilder({
|
|
|
44685
43713
|
formData.pivot && selectedPivotTable && selectedPivotTable.columns && formData.chartType === "table" ? (
|
|
44686
43714
|
// THIS CASE IF FOR PIVOT TABLES ONLY
|
|
44687
43715
|
selectedPivotTable.columns.map(
|
|
44688
|
-
(column, index) => /* @__PURE__ */ jsxs47(
|
|
44689
|
-
|
|
44690
|
-
|
|
44691
|
-
|
|
44692
|
-
|
|
44693
|
-
|
|
44694
|
-
|
|
44695
|
-
|
|
44696
|
-
|
|
44697
|
-
e.target.value,
|
|
44698
|
-
"pivot.field",
|
|
44699
|
-
index
|
|
44700
|
-
),
|
|
44701
|
-
options: selectedPivotTable.columns.map(
|
|
44702
|
-
(elem) => ({
|
|
44703
|
-
label: elem.field,
|
|
44704
|
-
value: elem.field
|
|
44705
|
-
})
|
|
44706
|
-
),
|
|
44707
|
-
disabled: index === 0,
|
|
44708
|
-
width: 200,
|
|
44709
|
-
hideEmptyOption: true
|
|
44710
|
-
}
|
|
43716
|
+
(column, index) => /* @__PURE__ */ jsxs47(ChartBuilderInputRowContainer, { children: [
|
|
43717
|
+
/* @__PURE__ */ jsx65(
|
|
43718
|
+
SelectComponent,
|
|
43719
|
+
{
|
|
43720
|
+
value: column.field,
|
|
43721
|
+
onChange: (e) => handleChange(
|
|
43722
|
+
e.target.value,
|
|
43723
|
+
"pivot.field",
|
|
43724
|
+
index
|
|
44711
43725
|
),
|
|
44712
|
-
|
|
44713
|
-
|
|
44714
|
-
|
|
44715
|
-
|
|
44716
|
-
|
|
44717
|
-
value: column.label,
|
|
44718
|
-
placeholder: "Column Label",
|
|
44719
|
-
onChange: (e) => handleChange(
|
|
44720
|
-
e.target.value,
|
|
44721
|
-
"pivot.label",
|
|
44722
|
-
index
|
|
44723
|
-
)
|
|
44724
|
-
}
|
|
43726
|
+
options: selectedPivotTable.columns.map(
|
|
43727
|
+
(elem) => ({
|
|
43728
|
+
label: elem.field,
|
|
43729
|
+
value: elem.field
|
|
43730
|
+
})
|
|
44725
43731
|
),
|
|
44726
|
-
|
|
44727
|
-
|
|
44728
|
-
|
|
44729
|
-
|
|
44730
|
-
|
|
44731
|
-
|
|
44732
|
-
|
|
44733
|
-
|
|
44734
|
-
|
|
44735
|
-
|
|
44736
|
-
|
|
44737
|
-
|
|
44738
|
-
|
|
44739
|
-
|
|
44740
|
-
|
|
44741
|
-
|
|
44742
|
-
{ label: "string", value: "string" }
|
|
44743
|
-
],
|
|
44744
|
-
width: 200,
|
|
44745
|
-
hideEmptyOption: true
|
|
44746
|
-
}
|
|
43732
|
+
disabled: index === 0,
|
|
43733
|
+
width: 200,
|
|
43734
|
+
hideEmptyOption: true
|
|
43735
|
+
}
|
|
43736
|
+
),
|
|
43737
|
+
/* @__PURE__ */ jsx65(
|
|
43738
|
+
TextInputComponent,
|
|
43739
|
+
{
|
|
43740
|
+
id: `chart-builder-column-label-${index}`,
|
|
43741
|
+
width: 200,
|
|
43742
|
+
value: column.label,
|
|
43743
|
+
placeholder: "Column Label",
|
|
43744
|
+
onChange: (e) => handleChange(
|
|
43745
|
+
e.target.value,
|
|
43746
|
+
"pivot.label",
|
|
43747
|
+
index
|
|
44747
43748
|
)
|
|
44748
|
-
|
|
44749
|
-
|
|
44750
|
-
|
|
44751
|
-
|
|
43749
|
+
}
|
|
43750
|
+
),
|
|
43751
|
+
/* @__PURE__ */ jsx65(
|
|
43752
|
+
SelectComponent,
|
|
43753
|
+
{
|
|
43754
|
+
value: (
|
|
43755
|
+
// The first index use rowField for the rest of them use value fields
|
|
43756
|
+
column.format
|
|
43757
|
+
),
|
|
43758
|
+
onChange: (e) => handleChange(
|
|
43759
|
+
e.target.value,
|
|
43760
|
+
"pivot.format",
|
|
43761
|
+
index
|
|
43762
|
+
),
|
|
43763
|
+
options: formData.pivot && index === 0 && selectedPivotTable?.columns.length > 1 ? isDateField(
|
|
43764
|
+
formData.pivot.rowFieldType || ""
|
|
43765
|
+
) ? [{ label: "date", value: "string" }] : [{ label: "string", value: "string" }] : [
|
|
43766
|
+
...NUMBER_OPTIONS,
|
|
43767
|
+
{ label: "string", value: "string" }
|
|
43768
|
+
],
|
|
43769
|
+
width: 200,
|
|
43770
|
+
hideEmptyOption: true
|
|
43771
|
+
}
|
|
43772
|
+
)
|
|
43773
|
+
] }, "column" + index)
|
|
44752
43774
|
)
|
|
44753
|
-
) :
|
|
44754
|
-
|
|
44755
|
-
|
|
44756
|
-
|
|
44757
|
-
|
|
44758
|
-
|
|
44759
|
-
|
|
44760
|
-
|
|
44761
|
-
|
|
44762
|
-
|
|
44763
|
-
|
|
44764
|
-
|
|
44765
|
-
|
|
44766
|
-
|
|
44767
|
-
|
|
44768
|
-
|
|
44769
|
-
|
|
44770
|
-
|
|
44771
|
-
|
|
44772
|
-
|
|
44773
|
-
|
|
44774
|
-
|
|
44775
|
-
|
|
44776
|
-
|
|
44777
|
-
|
|
44778
|
-
|
|
44779
|
-
|
|
44780
|
-
|
|
44781
|
-
|
|
44782
|
-
width: 200,
|
|
44783
|
-
value: column.label,
|
|
44784
|
-
placeholder: "Column Label",
|
|
44785
|
-
onChange: (e) => handleChange(
|
|
44786
|
-
e.target.value,
|
|
44787
|
-
"columns.label",
|
|
44788
|
-
index
|
|
44789
|
-
)
|
|
44790
|
-
}
|
|
44791
|
-
),
|
|
44792
|
-
/* @__PURE__ */ jsx65(
|
|
44793
|
-
SelectComponent,
|
|
44794
|
-
{
|
|
44795
|
-
value: column.format,
|
|
44796
|
-
onChange: (e) => handleChange(
|
|
44797
|
-
e.target.value,
|
|
44798
|
-
"columns.format",
|
|
44799
|
-
index
|
|
44800
|
-
),
|
|
44801
|
-
options: ALL_FORMAT_OPTIONS,
|
|
44802
|
-
width: 200,
|
|
44803
|
-
hideEmptyOption: true
|
|
44804
|
-
}
|
|
44805
|
-
),
|
|
44806
|
-
/* @__PURE__ */ jsx65(
|
|
44807
|
-
"div",
|
|
44808
|
-
{
|
|
44809
|
-
ref: deleteRef,
|
|
44810
|
-
style: { marginLeft: deleteButtonMargin },
|
|
44811
|
-
children: /* @__PURE__ */ jsx65(
|
|
44812
|
-
DeleteButtonComponent,
|
|
44813
|
-
{
|
|
44814
|
-
onClick: () => handleRemoveField("columns", index)
|
|
44815
|
-
}
|
|
44816
|
-
)
|
|
44817
|
-
}
|
|
43775
|
+
) : /* @__PURE__ */ jsx65(
|
|
43776
|
+
DndContext,
|
|
43777
|
+
{
|
|
43778
|
+
sensors: columnDragSensors,
|
|
43779
|
+
collisionDetection: closestCenter,
|
|
43780
|
+
onDragEnd: handleColumnDragEnd,
|
|
43781
|
+
children: /* @__PURE__ */ jsx65(
|
|
43782
|
+
SortableContext,
|
|
43783
|
+
{
|
|
43784
|
+
items: formData.columns.map((col) => col.field),
|
|
43785
|
+
strategy: verticalListSortingStrategy,
|
|
43786
|
+
children: formData.columns.map(
|
|
43787
|
+
(column, index) => /* @__PURE__ */ jsx65(
|
|
43788
|
+
SortableColumnItem,
|
|
43789
|
+
{
|
|
43790
|
+
column,
|
|
43791
|
+
index,
|
|
43792
|
+
rows,
|
|
43793
|
+
columns,
|
|
43794
|
+
handleChange,
|
|
43795
|
+
deleteRef,
|
|
43796
|
+
deleteButtonMargin,
|
|
43797
|
+
handleRemoveField,
|
|
43798
|
+
SelectComponent,
|
|
43799
|
+
TextInputComponent,
|
|
43800
|
+
DeleteButtonComponent
|
|
43801
|
+
},
|
|
43802
|
+
column.field
|
|
43803
|
+
)
|
|
44818
43804
|
)
|
|
44819
|
-
|
|
44820
|
-
|
|
44821
|
-
|
|
44822
|
-
)
|
|
43805
|
+
}
|
|
43806
|
+
)
|
|
43807
|
+
}
|
|
44823
43808
|
),
|
|
44824
43809
|
/* @__PURE__ */ jsx65("div", { children: !// hide when pivoted and chartType === 'table'
|
|
44825
43810
|
(formData.pivot && selectedPivotTable && selectedPivotTable.columns && formData.chartType === "table") && /* @__PURE__ */ jsxs47(
|
|
@@ -48994,21 +47979,21 @@ var useReportBuilder = ({
|
|
|
48994
47979
|
// src/components/ReportBuilder/AddColumnModal.tsx
|
|
48995
47980
|
import { useState as useState32, useRef as useRef19, useMemo as useMemo24, useEffect as useEffect26, useContext as useContext30 } from "react";
|
|
48996
47981
|
import {
|
|
48997
|
-
DndContext,
|
|
48998
|
-
closestCenter,
|
|
48999
|
-
KeyboardSensor,
|
|
49000
|
-
PointerSensor,
|
|
49001
|
-
useSensor,
|
|
49002
|
-
useSensors
|
|
47982
|
+
DndContext as DndContext2,
|
|
47983
|
+
closestCenter as closestCenter2,
|
|
47984
|
+
KeyboardSensor as KeyboardSensor2,
|
|
47985
|
+
PointerSensor as PointerSensor2,
|
|
47986
|
+
useSensor as useSensor2,
|
|
47987
|
+
useSensors as useSensors2
|
|
49003
47988
|
} from "@dnd-kit/core";
|
|
49004
47989
|
import {
|
|
49005
|
-
arrayMove,
|
|
49006
|
-
SortableContext,
|
|
49007
|
-
sortableKeyboardCoordinates,
|
|
49008
|
-
verticalListSortingStrategy,
|
|
49009
|
-
useSortable
|
|
47990
|
+
arrayMove as arrayMove2,
|
|
47991
|
+
SortableContext as SortableContext2,
|
|
47992
|
+
sortableKeyboardCoordinates as sortableKeyboardCoordinates2,
|
|
47993
|
+
verticalListSortingStrategy as verticalListSortingStrategy2,
|
|
47994
|
+
useSortable as useSortable2
|
|
49010
47995
|
} from "@dnd-kit/sortable";
|
|
49011
|
-
import { CSS as
|
|
47996
|
+
import { CSS as DND_CSS2 } from "@dnd-kit/utilities";
|
|
49012
47997
|
import { jsx as jsx67, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
49013
47998
|
function AddColumnModal({
|
|
49014
47999
|
onSave,
|
|
@@ -49077,10 +48062,10 @@ function AddColumnModal({
|
|
|
49077
48062
|
setTimeout(() => setInitialLoad(false), 200);
|
|
49078
48063
|
}
|
|
49079
48064
|
}, [schemaLoading]);
|
|
49080
|
-
const sensors =
|
|
49081
|
-
|
|
49082
|
-
|
|
49083
|
-
coordinateGetter:
|
|
48065
|
+
const sensors = useSensors2(
|
|
48066
|
+
useSensor2(PointerSensor2),
|
|
48067
|
+
useSensor2(KeyboardSensor2, {
|
|
48068
|
+
coordinateGetter: sortableKeyboardCoordinates2
|
|
49084
48069
|
})
|
|
49085
48070
|
);
|
|
49086
48071
|
function handleDragEnd(event) {
|
|
@@ -49090,7 +48075,7 @@ function AddColumnModal({
|
|
|
49090
48075
|
setOrderedColumnNames((orderedColumnNames2) => {
|
|
49091
48076
|
const oldIndex = orderedColumnNames2.indexOf(active.id);
|
|
49092
48077
|
const newIndex = orderedColumnNames2.indexOf(over.id);
|
|
49093
|
-
return
|
|
48078
|
+
return arrayMove2(orderedColumnNames2, oldIndex, newIndex);
|
|
49094
48079
|
});
|
|
49095
48080
|
}
|
|
49096
48081
|
}
|
|
@@ -49134,16 +48119,16 @@ function AddColumnModal({
|
|
|
49134
48119
|
}
|
|
49135
48120
|
),
|
|
49136
48121
|
schemaLoading || initialLoad ? /* @__PURE__ */ jsx67(LoadingComponent, {}) : schema.length > 0 ? /* @__PURE__ */ jsx67(
|
|
49137
|
-
|
|
48122
|
+
DndContext2,
|
|
49138
48123
|
{
|
|
49139
48124
|
sensors,
|
|
49140
|
-
collisionDetection:
|
|
48125
|
+
collisionDetection: closestCenter2,
|
|
49141
48126
|
onDragEnd: handleDragEnd,
|
|
49142
48127
|
children: /* @__PURE__ */ jsx67(
|
|
49143
|
-
|
|
48128
|
+
SortableContext2,
|
|
49144
48129
|
{
|
|
49145
48130
|
items: orderedColumnNames,
|
|
49146
|
-
strategy:
|
|
48131
|
+
strategy: verticalListSortingStrategy2,
|
|
49147
48132
|
children: /* @__PURE__ */ jsxs49(
|
|
49148
48133
|
"div",
|
|
49149
48134
|
{
|
|
@@ -49351,9 +48336,9 @@ var SortableItem = ({
|
|
|
49351
48336
|
selectedColumns,
|
|
49352
48337
|
SelectColumn
|
|
49353
48338
|
}) => {
|
|
49354
|
-
const { attributes, listeners, setNodeRef, transform, transition: transition2 } =
|
|
48339
|
+
const { attributes, listeners, setNodeRef, transform, transition: transition2 } = useSortable2({ id: id2 });
|
|
49355
48340
|
const style2 = {
|
|
49356
|
-
transform:
|
|
48341
|
+
transform: DND_CSS2.Transform.toString(transform),
|
|
49357
48342
|
transition: transition2
|
|
49358
48343
|
};
|
|
49359
48344
|
const handleSelect = () => {
|
|
@@ -49383,17 +48368,17 @@ var SortableItem = ({
|
|
|
49383
48368
|
|
|
49384
48369
|
// src/components/ReportBuilder/DraggableColumns.tsx
|
|
49385
48370
|
import {
|
|
49386
|
-
closestCenter as
|
|
49387
|
-
DndContext as
|
|
49388
|
-
KeyboardSensor as
|
|
49389
|
-
PointerSensor as
|
|
49390
|
-
useSensor as
|
|
49391
|
-
useSensors as
|
|
48371
|
+
closestCenter as closestCenter3,
|
|
48372
|
+
DndContext as DndContext3,
|
|
48373
|
+
KeyboardSensor as KeyboardSensor3,
|
|
48374
|
+
PointerSensor as PointerSensor3,
|
|
48375
|
+
useSensor as useSensor3,
|
|
48376
|
+
useSensors as useSensors3
|
|
49392
48377
|
} from "@dnd-kit/core";
|
|
49393
48378
|
|
|
49394
48379
|
// src/components/ReportBuilder/DraggableItem.tsx
|
|
49395
|
-
import { useSortable as
|
|
49396
|
-
import { CSS as
|
|
48380
|
+
import { useSortable as useSortable3 } from "@dnd-kit/sortable";
|
|
48381
|
+
import { CSS as DND_CSS3 } from "@dnd-kit/utilities";
|
|
49397
48382
|
import { jsx as jsx68 } from "react/jsx-runtime";
|
|
49398
48383
|
function DraggableItem({
|
|
49399
48384
|
id: id2,
|
|
@@ -49402,9 +48387,9 @@ function DraggableItem({
|
|
|
49402
48387
|
DraggableColumnComponent,
|
|
49403
48388
|
loading
|
|
49404
48389
|
}) {
|
|
49405
|
-
const { attributes, listeners, setNodeRef, transform, transition: transition2 } =
|
|
48390
|
+
const { attributes, listeners, setNodeRef, transform, transition: transition2 } = useSortable3({ id: id2 });
|
|
49406
48391
|
const style2 = {
|
|
49407
|
-
transform:
|
|
48392
|
+
transform: DND_CSS3.Transform.toString(transform),
|
|
49408
48393
|
transition: transition2
|
|
49409
48394
|
};
|
|
49410
48395
|
return /* @__PURE__ */ jsx68("div", { style: { ...style2 }, ref: setNodeRef, children: /* @__PURE__ */ jsx68(
|
|
@@ -49430,10 +48415,10 @@ function DraggableItem({
|
|
|
49430
48415
|
|
|
49431
48416
|
// src/components/ReportBuilder/DraggableColumns.tsx
|
|
49432
48417
|
import {
|
|
49433
|
-
arrayMove as
|
|
49434
|
-
SortableContext as
|
|
49435
|
-
sortableKeyboardCoordinates as
|
|
49436
|
-
verticalListSortingStrategy as
|
|
48418
|
+
arrayMove as arrayMove3,
|
|
48419
|
+
SortableContext as SortableContext3,
|
|
48420
|
+
sortableKeyboardCoordinates as sortableKeyboardCoordinates3,
|
|
48421
|
+
verticalListSortingStrategy as verticalListSortingStrategy3
|
|
49437
48422
|
} from "@dnd-kit/sortable";
|
|
49438
48423
|
import { useMemo as useMemo25 } from "react";
|
|
49439
48424
|
import { jsx as jsx69, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
@@ -49443,10 +48428,10 @@ function DraggableColumns({
|
|
|
49443
48428
|
DraggableColumnComponent,
|
|
49444
48429
|
loading
|
|
49445
48430
|
}) {
|
|
49446
|
-
const sensors =
|
|
49447
|
-
|
|
49448
|
-
|
|
49449
|
-
coordinateGetter:
|
|
48431
|
+
const sensors = useSensors3(
|
|
48432
|
+
useSensor3(PointerSensor3),
|
|
48433
|
+
useSensor3(KeyboardSensor3, {
|
|
48434
|
+
coordinateGetter: sortableKeyboardCoordinates3
|
|
49450
48435
|
})
|
|
49451
48436
|
);
|
|
49452
48437
|
const columnNames = useMemo25(() => {
|
|
@@ -49463,7 +48448,7 @@ function DraggableColumns({
|
|
|
49463
48448
|
if (active.id !== over.id) {
|
|
49464
48449
|
const oldIndex = columnNames.findIndex((c) => c.endsWith(active.id));
|
|
49465
48450
|
const newIndex = columnNames.findIndex((c) => c.endsWith(over.id));
|
|
49466
|
-
const newOrder =
|
|
48451
|
+
const newOrder = arrayMove3(columnNames, oldIndex, newIndex);
|
|
49467
48452
|
const orderToColumns = newOrder.map((name2) => {
|
|
49468
48453
|
const [table, field] = name2.split(".");
|
|
49469
48454
|
return columns.find(
|
|
@@ -49480,16 +48465,16 @@ function DraggableColumns({
|
|
|
49480
48465
|
onColumnOrderChange(newColumns);
|
|
49481
48466
|
}
|
|
49482
48467
|
return /* @__PURE__ */ jsx69(
|
|
49483
|
-
|
|
48468
|
+
DndContext3,
|
|
49484
48469
|
{
|
|
49485
48470
|
sensors,
|
|
49486
|
-
collisionDetection:
|
|
48471
|
+
collisionDetection: closestCenter3,
|
|
49487
48472
|
onDragEnd: handleDragEnd,
|
|
49488
48473
|
children: /* @__PURE__ */ jsx69(
|
|
49489
|
-
|
|
48474
|
+
SortableContext3,
|
|
49490
48475
|
{
|
|
49491
48476
|
items: columnNames,
|
|
49492
|
-
strategy:
|
|
48477
|
+
strategy: verticalListSortingStrategy3,
|
|
49493
48478
|
children: /* @__PURE__ */ jsxs50(
|
|
49494
48479
|
"div",
|
|
49495
48480
|
{
|