Compare commits

...

13 Commits

Author SHA1 Message Date
28ae2283f6 Add null-pointer check in getFieldAndTable (but be careful downstream...) 2024-02-23 14:58:35 -06:00
077845bc42 put commas in +n on filter human-strings 2024-02-23 14:58:15 -06:00
0262f8e365 Change to post multipart/form-data for exports - fixes giant filter making request-too-big error from javalin 2024-02-23 14:57:51 -06:00
8cffbbcac4 Update to cimg/openjdk:17.0.9 2024-02-22 20:30:51 -06:00
37eb280d79 Revert to previous check for disabling export-menu items - that is - totalRecords === 0, instead of !totalRecords. makes tables w/o count allowed to do exports again. 2024-02-22 12:16:27 -06:00
948aee70fd Disable 'c' hotkey for columns (broke with buiding custom columsn button instead of using data grid's) 2024-02-21 19:43:20 -06:00
f0c1af18d0 Fix last commit (shouldn't add layout to ChartSubheaderWithData) 2024-02-21 19:42:00 -06:00
fa65d6c0ad Add cursor:pointer to PieChart and StackedBarChart 2024-02-21 19:18:34 -06:00
d6c9bf79b1 Update circleci/browser-tools@1.4.7 and try to re-activate verify 2024-02-19 14:49:55 -06:00
677b93a09f Turn off broken selenium/int tests 2024-02-19 14:49:02 -06:00
314bf0fd67 Fix to clear out limit when using a select-all filter for launching processes 2024-02-19 13:47:04 -06:00
76642f13e9 HOTFIX - Change defaultRowsPerPage from 10 to 50 2024-02-16 11:23:31 -06:00
0eaf171523 Merge pull request #43 from Kingsrook/feature/CE-798-quick-filters-fixes
Feature/ce 798 quick filters fixes
2024-02-16 10:56:15 -06:00
9 changed files with 117 additions and 67 deletions

View File

@ -2,12 +2,12 @@ version: 2.1
orbs:
node: circleci/node@5.1.0
browser-tools: circleci/browser-tools@1.4.6
browser-tools: circleci/browser-tools@1.4.7
executors:
java17:
docker:
- image: 'cimg/openjdk:17.0'
- image: 'cimg/openjdk:17.0.9'
commands:
install_java17:

View File

@ -354,8 +354,7 @@ const CommandMenu = ({metaData}: Props) =>
<Grid container columnSpacing={5} rowSpacing={1}>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>n</span>Create a New Record</Grid>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>r</span>Refresh the Query</Grid>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>c</span>Open the Columns Panel</Grid>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>f</span>Open the Filter Panel</Grid>
<Grid item xs={6} className={classes.item}><span className={classes.keyboardKey}>f</span>Open the Filter Builder (Advanced mode only)</Grid>
</Grid>
<Typography variant="h6" pt={3}>Record View</Typography>

View File

@ -45,7 +45,7 @@ export default function ExportMenuItem(props: QExportMenuItemProps)
return (
<MenuItem
disabled={!totalRecords}
disabled={totalRecords === 0}
onClick={() =>
{
///////////////////////////////////////////////////////////////////////////////
@ -98,7 +98,7 @@ export default function ExportMenuItem(props: QExportMenuItemProps)
</head>
<body>
Generating file <u>${filename}</u>${totalRecords ? " with " + totalRecords.toLocaleString() + " record" + (totalRecords == 1 ? "" : "s") : ""}...
<form id="exportForm" method="post" action="${url}" >
<form id="exportForm" method="post" action="${url}" enctype="multipart/form-data">
<input type="hidden" name="fields" value="${visibleFields.join(",")}">
<input type="hidden" name="filter" id="filter">
</form>

View File

@ -39,65 +39,79 @@ ChartJS.register(
Legend
);
export const options = {
maintainAspectRatio: false,
responsive: true,
animation: {
duration: 0
},
elements: {
bar: {
borderRadius: 4
}
},
plugins: {
tooltip: {
// todo - some configs around this
callbacks: {
title: function(context: any)
{
return ("");
},
label: function(context: any)
{
if(context.dataset.label.startsWith(context.label))
{
return `${context.label}: ${context.formattedValue}`;
}
else
export const makeOptions = (data: DefaultChartData) =>
{
return({
maintainAspectRatio: false,
responsive: true,
animation: {
duration: 0
},
elements: {
bar: {
borderRadius: 4
}
},
onHover: function (event: any, elements: any[], chart: any)
{
if(event.type == "mousemove" && elements.length > 0 && data.urls && data.urls.length > elements[0].index && data.urls[elements[0].index])
{
chart.canvas.style.cursor = "pointer";
}
else
{
chart.canvas.style.cursor = "default";
}
},
plugins: {
tooltip: {
// todo - some configs around this
callbacks: {
title: function(context: any)
{
return ("");
},
label: function(context: any)
{
if(context.dataset.label.startsWith(context.label))
{
return `${context.label}: ${context.formattedValue}`;
}
else
{
return ("");
}
}
}
},
legend: {
position: "bottom",
labels: {
usePointStyle: true,
pointStyle: "circle",
boxHeight: 6,
boxWidth: 6,
padding: 12,
font: {
size: 14
}
}
}
},
legend: {
position: "bottom",
labels: {
usePointStyle: true,
pointStyle: "circle",
boxHeight: 6,
boxWidth: 6,
padding: 12,
font: {
size: 14
}
}
}
},
scales: {
x: {
stacked: true,
grid: {display: false},
ticks: {autoSkip: false, maxRotation: 90}
scales: {
x: {
stacked: true,
grid: {display: false},
ticks: {autoSkip: false, maxRotation: 90}
},
y: {
stacked: true,
position: "right",
ticks: {precision: 0}
},
},
y: {
stacked: true,
position: "right",
ticks: {precision: 0}
},
},
};
});
}
interface Props
{
@ -151,7 +165,7 @@ function StackedBarChart({data, chartSubheaderData}: Props): JSX.Element
<Box>
{chartSubheaderData && (<ChartSubheaderWithData chartSubheaderData={chartSubheaderData} />)}
<Box width="100%" height="300px">
<Bar data={data} options={options} getElementsAtEvent={handleClick} />
<Bar data={data} options={makeOptions(data)} getElementsAtEvent={handleClick} />
</Box>
</Box>
) : <Skeleton sx={{marginLeft: "20px", marginRight: "20px", height: "200px"}} />;

View File

@ -70,7 +70,7 @@ function PieChart({description, chartData, chartSubheaderData}: Props): JSX.Elem
chartData.dataset.backgroundColors = chartColors;
}
}
const {data, options} = configs(chartData?.labels || [], chartData?.dataset || {});
const {data, options} = configs(chartData?.labels || [], chartData?.dataset || {}, chartData?.dataset?.urls);
useEffect(() =>
{

View File

@ -23,7 +23,7 @@ import colors from "qqq/assets/theme/base/colors";
const {gradients, dark} = colors;
function configs(labels: any, datasets: any)
function configs(labels: any, datasets: any, urls: string[] | undefined)
{
const backgroundColors = [];
@ -66,6 +66,17 @@ function configs(labels: any, datasets: any)
options: {
maintainAspectRatio: false,
responsive: true,
onHover: function (event: any, elements: any[], chart: any)
{
if(event.type == "mousemove" && elements.length > 0 && urls && urls.length > elements[0].index && urls[elements[0].index])
{
chart.canvas.style.cursor = "pointer";
}
else
{
chart.canvas.style.cursor = "default";
}
},
plugins: {
tooltip: {
callbacks: {

View File

@ -168,7 +168,7 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
// define some default values (e.g., to be used if nothing in local storage or no active view) //
/////////////////////////////////////////////////////////////////////////////////////////////////
let defaultSort = [] as GridSortItem[];
let defaultRowsPerPage = 10;
let defaultRowsPerPage = 50;
let defaultDensity = "standard" as GridDensity;
let defaultTableVariant: QTableVariant = null;
let defaultMode = "basic";
@ -610,11 +610,14 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
e.preventDefault()
updateTable("'r' keyboard event");
}
/*
// disable until we add a ... ref down to let us programmatically open Columns button
else if (! e.metaKey && e.key === "c")
{
e.preventDefault()
gridApiRef.current.showPreferences(GridPreferencePanelsValue.columns)
}
*/
else if (! e.metaKey && e.key === "f")
{
e.preventDefault()
@ -1380,7 +1383,10 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
{
if (selectFullFilterState === "filter")
{
return `?recordsParam=filterJSON&filterJSON=${encodeURIComponent(JSON.stringify(prepQueryFilterForBackend(queryFilter)))}`;
const filterForBackend = prepQueryFilterForBackend(queryFilter);
filterForBackend.skip = 0;
filterForBackend.limit = null;
return `?recordsParam=filterJSON&filterJSON=${encodeURIComponent(JSON.stringify(filterForBackend))}`;
}
if (selectFullFilterState === "filterSubset")
@ -1408,7 +1414,10 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
{
if (selectFullFilterState === "filter")
{
setRecordIdsForProcess(prepQueryFilterForBackend(queryFilter));
const filterForBackend = prepQueryFilterForBackend(queryFilter);
filterForBackend.skip = 0;
filterForBackend.limit = null;
setRecordIdsForProcess(filterForBackend);
}
else if (selectFullFilterState === "filterSubset")
{
@ -2103,20 +2112,32 @@ function RecordQuery({table, launchProcess}: Props): JSX.Element
{
if(selectedIndex == 0)
{
///////////////
// this page //
///////////////
programmaticallySelectSomeOrAllRows();
setSelectFullFilterState("checked")
}
else if(selectedIndex == 1)
{
///////////////////////
// full query result //
///////////////////////
programmaticallySelectSomeOrAllRows();
setSelectFullFilterState("filter")
}
else if(selectedIndex == 2)
{
////////////////////////////
// subset of query result //
////////////////////////////
setSelectionSubsetSizePromptOpen(true);
}
else if(selectedIndex == 3)
{
/////////////////////
// clear selection //
/////////////////////
setSelectFullFilterState("n/a")
setRowSelectionModel([]);
setSelectedIds([]);

View File

@ -395,10 +395,10 @@ class FilterUtils
switch (andMoreFormat)
{
case "andNOther":
labels.push(` and ${n} other value${n == 1 ? "" : "s"}.`);
labels.push(` and ${n.toLocaleString()} other value${n == 1 ? "" : "s"}.`);
break;
case "+N":
labels[labels.length-1] += ` +${n}`;
labels[labels.length-1] += ` +${n.toLocaleString()}`;
break;
}
}

View File

@ -93,6 +93,11 @@ class TableUtils
*******************************************************************************/
public static getFieldAndTable(tableMetaData: QTableMetaData, fieldName: string): [QFieldMetaData, QTableMetaData]
{
if(fieldName == null || tableMetaData == null)
{
return ([null, null]);
}
if (fieldName.indexOf(".") > -1)
{
const nameParts = fieldName.split(".", 2);
@ -110,7 +115,7 @@ class TableUtils
return ([tableMetaData.fields.get(fieldName), tableMetaData]);
}
return (null);
return ([null, null]);
}