2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-07-04 14:10:52 +00:00

[UI] Calendar Updates (#12161)

* Adjust delay values

* Add extra info to tooltip

* Additional padding

* Adjust padding for scrollbar

* Adjust month title as calendar scrolls
This commit is contained in:
Oliver
2026-06-14 10:52:22 +10:00
committed by GitHub
parent 457fe16f9c
commit b294bba66b
4 changed files with 91 additions and 11 deletions
@@ -41,6 +41,7 @@ import {
useCallback,
useEffect,
useMemo,
useRef,
useState
} from 'react';
import { useShallow } from 'zustand/react/shallow';
@@ -168,8 +169,8 @@ export default function Calendar({
return (
<HoverCard
openDelay={300}
closeDelay={100}
openDelay={1000}
closeDelay={50}
shadow='md'
position='top-start'
>
@@ -183,6 +184,40 @@ export default function Calendar({
[calendarProps.eventContent, eventTooltipContent]
);
const scrollBoxRef = useRef<HTMLDivElement>(null);
const updateMonthFromScroll = useCallback(() => {
if (!scrollBoxRef.current) return;
const container = scrollBoxRef.current;
const containerTop = container.getBoundingClientRect().top;
const cells = Array.from(
container.querySelectorAll<HTMLElement>(
'.fc-daygrid-day[data-date$="-01"]'
)
);
let dateStr: string | null = null;
for (const cell of cells) {
if (cell.getBoundingClientRect().top <= containerTop + 1) {
dateStr = cell.getAttribute('data-date');
} else {
break;
}
}
if (!dateStr) dateStr = cells[0]?.getAttribute('data-date') ?? null;
if (dateStr) {
const date = new Date(`${dateStr}T12:00:00`);
state.setMonthName(
new Intl.DateTimeFormat(calendarLocale, {
month: 'long',
year: 'numeric'
}).format(date)
);
}
}, [calendarLocale, state.setMonthName]);
const monthDayCellClassNames = useCallback(
(arg: DayCellContentArg): string[] => {
const monthClass =
@@ -303,7 +338,19 @@ export default function Calendar({
)}
</Group>
</Group>
<Box pos='relative'>
<Box
ref={scrollBoxRef}
pos='relative'
onScroll={isScrollView ? updateMonthFromScroll : undefined}
{...(isScrollView && {
style: {
height: 'calc(100vh - 160px)',
overflowY: 'scroll',
scrollbarGutter: 'stable',
paddingRight: '12px'
}
})}
>
<LoadingOverlay visible={state.query.isFetching} />
<FullCalendar
ref={state.ref}
@@ -316,7 +363,7 @@ export default function Calendar({
duration: { months: horizonMonths }
}
},
height: 'calc(100vh - 160px)'
height: 'auto'
})}
locales={allLocales}
locale={calendarLocale}
@@ -189,7 +189,7 @@ export default function OrderCalendar({
}
return (
<Group gap='xs' wrap='nowrap'>
<Group gap='xs' wrap='nowrap' style={{ paddingLeft: 5 }}>
{order.overdue && (
<ActionIcon
color='orange-7'
@@ -10,10 +10,13 @@ import { RenderOwner } from '../render/User';
export default function OrderCalendarToolTip({
event,
instanceLookup,
extraEntries,
modelType
}: {
event: EventContentArg;
prefix?: string | React.ReactNode;
instanceLookup: string;
extraEntries?: { label: string; value: string | React.ReactNode }[];
modelType: ModelType;
}) {
// Extract the order instance from the event
@@ -23,24 +26,41 @@ export default function OrderCalendarToolTip({
if (!order) return null;
const entries = extraEntries || [];
if (order.project_code_detail?.code) {
entries.push({
label: t`Project Code`,
value: order.project_code_detail.code
});
}
return (
<Stack gap='xs'>
<Stack gap='xs' style={{ minWidth: 250 }}>
<RenderInstance model={modelType} instance={instance} />
<Divider />
<Group gap='xs'>
<Group grow gap='xs' justify='space-between'>
<Text size='sm' fw='bold'>
{order.reference}
</Text>
<Text size='xs'>{order.description || order.title}</Text>
</Group>
{entries.map((entry, index) => (
<Group key={index} grow gap='xs' justify='space-between'>
<Text size='sm' fw='bold'>
{entry.label}
</Text>
<Text size='xs'>{entry.value}</Text>
</Group>
))}
{order.start_date && (
<Group gap='xs'>
<Group grow gap='xs' justify='space-between'>
<Text size='sm' fw='bold'>{t`Start Date`}</Text>
<Text size='xs'>{formatDate(order.start_date)}</Text>
</Group>
)}
{order.target_date && (
<Group gap='xs'>
<Group grow gap='xs' justify='space-between'>
<Text size='sm' fw='bold'>{t`Target Date`}</Text>
<Text size='xs'>{formatDate(order.target_date)}</Text>
{order.overdue && (
@@ -51,7 +71,7 @@ export default function OrderCalendarToolTip({
</Group>
)}
{order.responsible && (
<Group gap='xs'>
<Group grow gap='xs' justify='space-between'>
<Text size='sm' fw='bold'>{t`Responsible`}</Text>
<RenderOwner instance={order.responsible_detail} />
</Group>
+14 -1
View File
@@ -37,10 +37,23 @@ function BuildOrderCalendar() {
}, [globalSettings]);
const renderTooltip = useCallback((event: EventContentArg) => {
const order = event?.event?._def?.extendedProps?.order;
const extraEntries: { label: string; value: string | React.ReactNode }[] =
[];
if (order?.quantity) {
extraEntries.push({
label: t`Quantity`,
value: order.quantity
});
}
return OrderCalendarToolTip({
event: event,
modelType: ModelType.part,
instanceLookup: 'part_detail'
instanceLookup: 'part_detail',
extraEntries: extraEntries
});
}, []);