mirror of
https://github.com/inventree/InvenTree.git
synced 2026-07-05 06:32:55 +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:
@@ -41,6 +41,7 @@ import {
|
|||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
|
useRef,
|
||||||
useState
|
useState
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { useShallow } from 'zustand/react/shallow';
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
@@ -168,8 +169,8 @@ export default function Calendar({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<HoverCard
|
<HoverCard
|
||||||
openDelay={300}
|
openDelay={1000}
|
||||||
closeDelay={100}
|
closeDelay={50}
|
||||||
shadow='md'
|
shadow='md'
|
||||||
position='top-start'
|
position='top-start'
|
||||||
>
|
>
|
||||||
@@ -183,6 +184,40 @@ export default function Calendar({
|
|||||||
[calendarProps.eventContent, eventTooltipContent]
|
[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(
|
const monthDayCellClassNames = useCallback(
|
||||||
(arg: DayCellContentArg): string[] => {
|
(arg: DayCellContentArg): string[] => {
|
||||||
const monthClass =
|
const monthClass =
|
||||||
@@ -303,7 +338,19 @@ export default function Calendar({
|
|||||||
)}
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
</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} />
|
<LoadingOverlay visible={state.query.isFetching} />
|
||||||
<FullCalendar
|
<FullCalendar
|
||||||
ref={state.ref}
|
ref={state.ref}
|
||||||
@@ -316,7 +363,7 @@ export default function Calendar({
|
|||||||
duration: { months: horizonMonths }
|
duration: { months: horizonMonths }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
height: 'calc(100vh - 160px)'
|
height: 'auto'
|
||||||
})}
|
})}
|
||||||
locales={allLocales}
|
locales={allLocales}
|
||||||
locale={calendarLocale}
|
locale={calendarLocale}
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ export default function OrderCalendar({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group gap='xs' wrap='nowrap'>
|
<Group gap='xs' wrap='nowrap' style={{ paddingLeft: 5 }}>
|
||||||
{order.overdue && (
|
{order.overdue && (
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
color='orange-7'
|
color='orange-7'
|
||||||
|
|||||||
@@ -10,10 +10,13 @@ import { RenderOwner } from '../render/User';
|
|||||||
export default function OrderCalendarToolTip({
|
export default function OrderCalendarToolTip({
|
||||||
event,
|
event,
|
||||||
instanceLookup,
|
instanceLookup,
|
||||||
|
extraEntries,
|
||||||
modelType
|
modelType
|
||||||
}: {
|
}: {
|
||||||
event: EventContentArg;
|
event: EventContentArg;
|
||||||
|
prefix?: string | React.ReactNode;
|
||||||
instanceLookup: string;
|
instanceLookup: string;
|
||||||
|
extraEntries?: { label: string; value: string | React.ReactNode }[];
|
||||||
modelType: ModelType;
|
modelType: ModelType;
|
||||||
}) {
|
}) {
|
||||||
// Extract the order instance from the event
|
// Extract the order instance from the event
|
||||||
@@ -23,24 +26,41 @@ export default function OrderCalendarToolTip({
|
|||||||
|
|
||||||
if (!order) return null;
|
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 (
|
return (
|
||||||
<Stack gap='xs'>
|
<Stack gap='xs' style={{ minWidth: 250 }}>
|
||||||
<RenderInstance model={modelType} instance={instance} />
|
<RenderInstance model={modelType} instance={instance} />
|
||||||
<Divider />
|
<Divider />
|
||||||
<Group gap='xs'>
|
<Group grow gap='xs' justify='space-between'>
|
||||||
<Text size='sm' fw='bold'>
|
<Text size='sm' fw='bold'>
|
||||||
{order.reference}
|
{order.reference}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size='xs'>{order.description || order.title}</Text>
|
<Text size='xs'>{order.description || order.title}</Text>
|
||||||
</Group>
|
</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 && (
|
{order.start_date && (
|
||||||
<Group gap='xs'>
|
<Group grow gap='xs' justify='space-between'>
|
||||||
<Text size='sm' fw='bold'>{t`Start Date`}</Text>
|
<Text size='sm' fw='bold'>{t`Start Date`}</Text>
|
||||||
<Text size='xs'>{formatDate(order.start_date)}</Text>
|
<Text size='xs'>{formatDate(order.start_date)}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
)}
|
)}
|
||||||
{order.target_date && (
|
{order.target_date && (
|
||||||
<Group gap='xs'>
|
<Group grow gap='xs' justify='space-between'>
|
||||||
<Text size='sm' fw='bold'>{t`Target Date`}</Text>
|
<Text size='sm' fw='bold'>{t`Target Date`}</Text>
|
||||||
<Text size='xs'>{formatDate(order.target_date)}</Text>
|
<Text size='xs'>{formatDate(order.target_date)}</Text>
|
||||||
{order.overdue && (
|
{order.overdue && (
|
||||||
@@ -51,7 +71,7 @@ export default function OrderCalendarToolTip({
|
|||||||
</Group>
|
</Group>
|
||||||
)}
|
)}
|
||||||
{order.responsible && (
|
{order.responsible && (
|
||||||
<Group gap='xs'>
|
<Group grow gap='xs' justify='space-between'>
|
||||||
<Text size='sm' fw='bold'>{t`Responsible`}</Text>
|
<Text size='sm' fw='bold'>{t`Responsible`}</Text>
|
||||||
<RenderOwner instance={order.responsible_detail} />
|
<RenderOwner instance={order.responsible_detail} />
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -37,10 +37,23 @@ function BuildOrderCalendar() {
|
|||||||
}, [globalSettings]);
|
}, [globalSettings]);
|
||||||
|
|
||||||
const renderTooltip = useCallback((event: EventContentArg) => {
|
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({
|
return OrderCalendarToolTip({
|
||||||
event: event,
|
event: event,
|
||||||
modelType: ModelType.part,
|
modelType: ModelType.part,
|
||||||
instanceLookup: 'part_detail'
|
instanceLookup: 'part_detail',
|
||||||
|
extraEntries: extraEntries
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user