mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-17 12:50:43 +00:00
Small updates to widgets; ok-ish version of filter query with relative time expressions; initial version of multi-select query for possible-values
This commit is contained in:
@ -21,7 +21,7 @@ Coded by www.creative-tim.com
|
||||
<meta name="theme-color" content="#04aaef" />
|
||||
<link id="appleIcon" rel="apple-touch-icon" sizes="76x76" href="%PUBLIC_URL%/" />
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<title>QQQ Material Dashboard</title>
|
||||
<title></title>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Two+Tone|Material+Icons+Round|Material+Icons+Sharp" rel="stylesheet" />
|
||||
</head>
|
||||
|
@ -243,7 +243,7 @@ function DashboardWidgets({widgetMetaDataList, tableName, entityPrimaryKey, omit
|
||||
{
|
||||
widgetMetaData.type === "html" && (
|
||||
<Widget widgetMetaData={widgetMetaData}>
|
||||
<Box px={1} pt={0} pb={2}>
|
||||
<Box px={3} pt={0} pb={2}>
|
||||
<MDTypography component="div" variant="button" color="text" fontWeight="light">
|
||||
{
|
||||
widgetData && widgetData[i] && widgetData[i].html ? (
|
||||
|
@ -142,7 +142,7 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
||||
{
|
||||
const link = component as HeaderLink
|
||||
return (
|
||||
<Typography variant="body2" p={2} display="inline">
|
||||
<Typography variant="body2" p={2} display="inline" fontSize=".875rem">
|
||||
{link.to ? <Link to={link.to}>{link.label}</Link> : null}
|
||||
</Typography>
|
||||
);
|
||||
@ -153,7 +153,7 @@ function Widget(props: React.PropsWithChildren<Props>): JSX.Element
|
||||
const addNewRecordButton = component as AddNewRecordButton
|
||||
return (
|
||||
<Typography variant="body2" p={2} pr={1} display="inline">
|
||||
<Button onClick={() => openEditForm(addNewRecordButton.table, null, addNewRecordButton.defaultValues, addNewRecordButton.disabledFields)}>{addNewRecordButton.label}</Button>
|
||||
<Button sx={{mt: 0.75}} onClick={() => openEditForm(addNewRecordButton.table, null, addNewRecordButton.defaultValues, addNewRecordButton.disabledFields)}>{addNewRecordButton.label}</Button>
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ function AppHome({app}: Props): JSX.Element
|
||||
const widgetCount = widgets ? widgets.length : 0;
|
||||
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
const tileSizeLg = (widgetCount === 0 ? 3 : widgetCount === 1 ? 4 : 6);
|
||||
const tileSizeLg = 3;
|
||||
|
||||
const handleDropdownOnChange = (value: string, index: number) =>
|
||||
{
|
||||
@ -207,7 +207,7 @@ function AppHome({app}: Props): JSX.Element
|
||||
<Grid container spacing={3}>
|
||||
{
|
||||
app.sections ? (
|
||||
<Grid item xs={12} lg={widgetCount === 0 ? 12 : widgetCount === 1 ? 9 : 6}>
|
||||
<Grid item xs={12} lg={12}>
|
||||
{app.sections.map((section) => (
|
||||
<Box key={section.name} mb={3}>
|
||||
<Card sx={{overflow: "visible"}}>
|
||||
|
@ -731,6 +731,73 @@ function InputPossibleValueSourceSingle(tableName: string, field: QFieldMetaData
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// input element for multiple possible values //
|
||||
////////////////////////////////////////////////
|
||||
function InputPossibleValueSourceMultiple(tableName: string, field: QFieldMetaData, props: GridFilterInputValueProps)
|
||||
{
|
||||
const SUBMIT_FILTER_STROKE_TIME = 500;
|
||||
const {item, applyValue, focusElementRef = null} = props;
|
||||
|
||||
console.log("Item.value? " + item.value);
|
||||
|
||||
const filterTimeout = useRef<any>();
|
||||
const [ selectedPossibleValues, setSelectedPossibleValues ] = useState(item.value as QPossibleValue[]);
|
||||
const [ applying, setIsApplying ] = useState(false);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
clearTimeout(filterTimeout.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const itemValue = item.value ?? null;
|
||||
}, [ item.value ]);
|
||||
|
||||
const updateFilterValue = (value: QPossibleValue) =>
|
||||
{
|
||||
clearTimeout(filterTimeout.current);
|
||||
|
||||
setIsApplying(true);
|
||||
filterTimeout.current = setTimeout(() =>
|
||||
{
|
||||
setIsApplying(false);
|
||||
applyValue({...item, value: value});
|
||||
}, SUBMIT_FILTER_STROKE_TIME);
|
||||
};
|
||||
|
||||
const handleChange = (value: QPossibleValue) =>
|
||||
{
|
||||
updateFilterValue(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "inline-flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "end",
|
||||
height: 48,
|
||||
}}
|
||||
>
|
||||
<DynamicSelect
|
||||
tableName={tableName}
|
||||
fieldName={field.name}
|
||||
isMultiple={true}
|
||||
fieldLabel="Value"
|
||||
initialValues={selectedPossibleValues}
|
||||
inForm={false}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// possible value set operators //
|
||||
//////////////////////////////////
|
||||
@ -749,6 +816,18 @@ export const buildQGridPvsOperators = (tableName: string, field: QFieldMetaData)
|
||||
getApplyFilterFn: () => null,
|
||||
InputComponent: (props: GridFilterInputValueProps<GridApiCommunity>) => InputPossibleValueSourceSingle(tableName, field, props)
|
||||
},
|
||||
{
|
||||
label: "is any of",
|
||||
value: "isAnyOf",
|
||||
getApplyFilterFn: () => null,
|
||||
InputComponent: (props: GridFilterInputValueProps<GridApiCommunity>) => InputPossibleValueSourceMultiple(tableName, field, props)
|
||||
},
|
||||
{
|
||||
label: "is none of",
|
||||
value: "isNone",
|
||||
getApplyFilterFn: () => null,
|
||||
InputComponent: (props: GridFilterInputValueProps<GridApiCommunity>) => InputPossibleValueSourceMultiple(tableName, field, props)
|
||||
},
|
||||
{
|
||||
label: "is empty",
|
||||
value: "isEmpty",
|
||||
|
@ -344,7 +344,8 @@ class FilterUtils
|
||||
{
|
||||
try
|
||||
{
|
||||
const qQueryFilter = (filterString !== null) ? JSON.parse(filterString) : JSON.parse(searchParams.get("filter")) as QQueryFilter;
|
||||
const filterJSON = (filterString !== null) ? JSON.parse(filterString) : JSON.parse(searchParams.get("filter"));
|
||||
const qQueryFilter = filterJSON as QQueryFilter;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// translate from a qqq-style filter to one that the grid wants //
|
||||
@ -377,6 +378,53 @@ class FilterUtils
|
||||
}
|
||||
}
|
||||
|
||||
if (field && field.type == "DATE_TIME" && !values)
|
||||
{
|
||||
try
|
||||
{
|
||||
const criteria = filterJSON.criteria[i];
|
||||
if (criteria && criteria.expression)
|
||||
{
|
||||
let value = new Date();
|
||||
let amount = Number(criteria.expression.amount);
|
||||
switch (criteria.expression.timeUnit)
|
||||
{
|
||||
case "MINUTES":
|
||||
{
|
||||
amount = amount * 60;
|
||||
break;
|
||||
}
|
||||
case "HOURS":
|
||||
{
|
||||
amount = amount * 60 * 60;
|
||||
break;
|
||||
}
|
||||
case "DAYS":
|
||||
{
|
||||
amount = amount * 60 * 60 * 24;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
console.log("Unrecognized time unit: " + criteria.expression.timeUnit);
|
||||
}
|
||||
}
|
||||
|
||||
if (criteria.expression.operator == "MINUS")
|
||||
{
|
||||
amount = -amount;
|
||||
}
|
||||
|
||||
value.setTime(value.getTime() + 1000 * amount);
|
||||
values = [ValueUtils.formatDateTimeISO8601(value)];
|
||||
}
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
defaultFilter.items.push({
|
||||
columnField: criteria.fieldName,
|
||||
operatorValue: FilterUtils.qqqCriteriaOperatorToGrid(criteria.operator, field, values),
|
||||
|
@ -131,7 +131,7 @@ class ValueUtils
|
||||
|
||||
if (field.hasAdornment(AdornmentType.RENDER_HTML))
|
||||
{
|
||||
return (parse(rawValue));
|
||||
return (rawValue ? parse(rawValue) : "");
|
||||
}
|
||||
|
||||
if (field.hasAdornment(AdornmentType.CHIP))
|
||||
@ -253,6 +253,16 @@ class ValueUtils
|
||||
return (`${date.toString("yyyy-MM-dd hh:mm:ss")} ${date.getHours() < 12 ? "AM" : "PM"} ${date.getTimezone()}`);
|
||||
}
|
||||
|
||||
public static formatDateTimeISO8601(date: Date)
|
||||
{
|
||||
if(!(date instanceof Date))
|
||||
{
|
||||
date = new Date(date)
|
||||
}
|
||||
// @ts-ignore
|
||||
return (`${date.toString("yyyy-MM-ddThh:mm:ssZ")}`);
|
||||
}
|
||||
|
||||
public static getFullWeekday(date: Date)
|
||||
{
|
||||
if(!(date instanceof Date))
|
||||
|
Reference in New Issue
Block a user