mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-17 21:00:45 +00:00
Merge branch 'feature/search-possible-values-by-label' into integration
This commit is contained in:
@ -91,7 +91,7 @@ function ChipTextField({...props})
|
|||||||
for (let k = 0; k < page.length; k++)
|
for (let k = 0; k < page.length; k++)
|
||||||
{
|
{
|
||||||
const result = page[k];
|
const result = page[k];
|
||||||
if (result.label === batch[j])
|
if (result.label.toLowerCase() === batch[j].toLowerCase())
|
||||||
{
|
{
|
||||||
chipPVSIds.push(result.id);
|
chipPVSIds.push(result.id);
|
||||||
newChipColors.push("info");
|
newChipColors.push("info");
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
|
import {QFieldMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldMetaData";
|
||||||
|
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
|
||||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||||
import {QPossibleValue} from "@kingsrook/qqq-frontend-core/lib/model/QPossibleValue";
|
import {QPossibleValue} from "@kingsrook/qqq-frontend-core/lib/model/QPossibleValue";
|
||||||
import {FormControl, InputLabel, Select, SelectChangeEvent} from "@mui/material";
|
import {FormControl, InputLabel, Select, SelectChangeEvent} from "@mui/material";
|
||||||
@ -34,7 +35,9 @@ import Typography from "@mui/material/Typography";
|
|||||||
import {QCancelButton, QSaveButton} from "qqq/components/buttons/DefaultButtons";
|
import {QCancelButton, QSaveButton} from "qqq/components/buttons/DefaultButtons";
|
||||||
|
|
||||||
import ChipTextField from "qqq/components/forms/ChipTextField";
|
import ChipTextField from "qqq/components/forms/ChipTextField";
|
||||||
|
import HelpContent from "qqq/components/misc/HelpContent";
|
||||||
import {LoadingState} from "qqq/models/LoadingState";
|
import {LoadingState} from "qqq/models/LoadingState";
|
||||||
|
import Client from "qqq/utils/qqq/Client";
|
||||||
import React, {useEffect, useReducer, useState} from "react";
|
import React, {useEffect, useReducer, useState} from "react";
|
||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
@ -46,6 +49,7 @@ interface Props
|
|||||||
}
|
}
|
||||||
|
|
||||||
FilterCriteriaPaster.defaultProps = {};
|
FilterCriteriaPaster.defaultProps = {};
|
||||||
|
const qController = Client.getInstance();
|
||||||
|
|
||||||
function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
||||||
{
|
{
|
||||||
@ -92,6 +96,7 @@ function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
|||||||
const [detectedText, setDetectedText] = useState("");
|
const [detectedText, setDetectedText] = useState("");
|
||||||
const [errorText, setErrorText] = useState("");
|
const [errorText, setErrorText] = useState("");
|
||||||
const [saveDisabled, setSaveDisabled] = useState(true);
|
const [saveDisabled, setSaveDisabled] = useState(true);
|
||||||
|
const [metaData, setMetaData] = useState(null as QInstance);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
// handler for when paste icon is clicked in 'any' operator //
|
// handler for when paste icon is clicked in 'any' operator //
|
||||||
@ -255,6 +260,12 @@ function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
|||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
|
(async () =>
|
||||||
|
{
|
||||||
|
const metaData = await qController.loadMetaData();
|
||||||
|
setMetaData(metaData);
|
||||||
|
})();
|
||||||
|
|
||||||
let currentDelimiter = delimiter;
|
let currentDelimiter = delimiter;
|
||||||
let currentDelimiterCharacter = delimiterCharacter;
|
let currentDelimiterCharacter = delimiterCharacter;
|
||||||
|
|
||||||
@ -291,6 +302,7 @@ function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
|||||||
// if delimiter is empty string, dont split anything //
|
// if delimiter is empty string, dont split anything //
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
setErrorText("");
|
setErrorText("");
|
||||||
|
let invalidCount = 0;
|
||||||
if (currentDelimiterCharacter !== "")
|
if (currentDelimiterCharacter !== "")
|
||||||
{
|
{
|
||||||
for (let i = 0; i < parts.length; i++)
|
for (let i = 0; i < parts.length; i++)
|
||||||
@ -303,25 +315,39 @@ function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// if numeric or pvs, check validity first before pushing as a chip //
|
// if numeric or pvs, check validity first before pushing as a chip //
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
if (chipValidity[i] !== true)
|
if (chipValidity[i] != null && chipValidity[i] !== true)
|
||||||
{
|
{
|
||||||
if (type === "number" && Number.isNaN(Number(part)))
|
if ((type === "number" && Number.isNaN(Number(part))) || type === "pvs")
|
||||||
{
|
{
|
||||||
setErrorText("Some values are not numbers");
|
invalidCount++;
|
||||||
}
|
|
||||||
else if (type === "pvs")
|
|
||||||
{
|
|
||||||
setErrorText("Some values are not valid");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (invalidCount > 0)
|
||||||
|
{
|
||||||
|
if (type === "number")
|
||||||
|
{
|
||||||
|
let suffix = invalidCount === 1 ? " value is not a number" : " values are not numbers";
|
||||||
|
setErrorText(invalidCount + suffix + "numbers and will not be added to the filter");
|
||||||
|
}
|
||||||
|
else if (type === "pvs")
|
||||||
|
{
|
||||||
|
let suffix = invalidCount === 1 ? " value was" : " values were";
|
||||||
|
setErrorText(invalidCount + suffix + " not found and will not be added to the filter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setChipData(chipData);
|
setChipData(chipData);
|
||||||
|
|
||||||
}, [inputText, delimiterCharacter, customDelimiterValue, detectedText, chipValidity]);
|
}, [inputText, delimiterCharacter, customDelimiterValue, detectedText, chipValidity]);
|
||||||
|
|
||||||
|
const slotName = type === "pvs" ? "bulkAddFilterValuesPossibleValueSource" : "bulkAddFilterValues";
|
||||||
|
const helpRoles = ["QUERY_SCREEN"];
|
||||||
|
const formattedHelpContent = <HelpContent helpContents={metaData?.helpContent?.get(slotName)} roles={helpRoles} heading={null} helpContentKey={`instanceLevel:true;slot:${slotName}`} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Tooltip title="Quickly add many values to your filter by pasting them from a spreadsheet or any other data source.">
|
<Tooltip title="Quickly add many values to your filter by pasting them from a spreadsheet or any other data source.">
|
||||||
@ -339,11 +365,13 @@ function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
|||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item pr={3} xs={12} lg={12}>
|
<Grid item pr={3} xs={12} lg={12}>
|
||||||
<Typography variant="h5">Bulk Add Filter Values</Typography>
|
<Typography variant="h5">Bulk Add Filter Values</Typography>
|
||||||
<Typography sx={{display: "flex", lineHeight: "1.7", textTransform: "revert"}} variant="button">
|
{
|
||||||
Paste into the box on the left.
|
formattedHelpContent && <Box sx={{display: "flex", lineHeight: "1.7", textTransform: "none"}}>
|
||||||
Review the filter values in the box on the right.
|
<Typography sx={{display: "flex", lineHeight: "1.7", textTransform: "revert"}} variant="button">
|
||||||
If the filter values are not what are expected, try changing the separator using the dropdown below.
|
{formattedHelpContent}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
@ -441,7 +469,7 @@ function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid sx={{display: "flex", justifyContent: "flex-start", alignItems: "flex-start"}} item pl={1} xs={3} lg={3}>
|
<Grid sx={{display: "flex", justifyContent: "flex-start", alignItems: "flex-start"}} item pl={1} xs={4} lg={4}>
|
||||||
{
|
{
|
||||||
errorText && chipData.length > 0 && (
|
errorText && chipData.length > 0 && (
|
||||||
<Box sx={{display: "flex", justifyContent: "flex-start", alignItems: "flex-start"}}>
|
<Box sx={{display: "flex", justifyContent: "flex-start", alignItems: "flex-start"}}>
|
||||||
@ -459,7 +487,7 @@ function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid sx={{display: "flex", justifyContent: "flex-end", alignItems: "flex-start"}} item pr={1} xs={3} lg={3}>
|
<Grid sx={{display: "flex", justifyContent: "flex-end", alignItems: "flex-start"}} item pr={1} xs={2} lg={2}>
|
||||||
{
|
{
|
||||||
chipData && chipData.length > 0 && (
|
chipData && chipData.length > 0 && (
|
||||||
<Typography sx={{textTransform: "revert"}} variant="button">{chipData.length.toLocaleString()} {chipData.length === 1 ? "value" : "values"}</Typography>
|
<Typography sx={{textTransform: "revert"}} variant="button">{chipData.length.toLocaleString()} {chipData.length === 1 ? "value" : "values"}</Typography>
|
||||||
@ -473,7 +501,7 @@ function FilterCriteriaPaster({table, field, type, onSave}: Props): JSX.Element
|
|||||||
onClickHandler={handleCancelClicked}
|
onClickHandler={handleCancelClicked}
|
||||||
iconName="cancel"
|
iconName="cancel"
|
||||||
disabled={false} />
|
disabled={false} />
|
||||||
<QSaveButton onClickHandler={handleSaveClicked} label="Add Filters" disabled={saveDisabled} />
|
<QSaveButton onClickHandler={handleSaveClicked} label="Add Values" disabled={saveDisabled} />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
</Card>
|
</Card>
|
||||||
|
Reference in New Issue
Block a user