@isma91/react-scheduler 4.0.0 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{dist/index.js → index.js} +218 -203
- package/package.json +4 -76
- package/.github/workflows/publish.yml +0 -29
- package/.github/workflows/tests.yml +0 -35
- package/.gitignore +0 -32
- package/.husky/pre-commit +0 -2
- package/.prettierignore +0 -1
- package/.prettierrc.json +0 -7
- package/.yarnrc.yml +0 -1
- package/dist/LICENSE +0 -24
- package/dist/README.md +0 -172
- package/dist/package.json +0 -65
- package/eslint.config.js +0 -79
- package/index.html +0 -41
- package/jest.config.ts +0 -194
- package/public/favicon.ico +0 -0
- package/public/logo192.png +0 -0
- package/public/logo512.png +0 -0
- package/public/manifest.json +0 -25
- package/public/robots.txt +0 -3
- package/scripts/post-pack.js +0 -34
- package/src/App.tsx +0 -25
- package/src/Page1.tsx +0 -67
- package/src/events.tsx +0 -227
- package/src/index.tsx +0 -21
- package/src/lib/SchedulerComponent.tsx +0 -78
- package/src/lib/__tests__/index.test.tsx +0 -24
- package/src/lib/components/common/Cell.tsx +0 -52
- package/src/lib/components/common/LocaleArrow.tsx +0 -38
- package/src/lib/components/common/ResourceHeader.tsx +0 -73
- package/src/lib/components/common/Tabs.tsx +0 -119
- package/src/lib/components/common/TodayTypo.tsx +0 -44
- package/src/lib/components/common/WithResources.tsx +0 -98
- package/src/lib/components/events/Actions.tsx +0 -65
- package/src/lib/components/events/AgendaEventsList.tsx +0 -115
- package/src/lib/components/events/CurrentTimeBar.tsx +0 -59
- package/src/lib/components/events/EmptyAgenda.tsx +0 -27
- package/src/lib/components/events/EventItem.tsx +0 -180
- package/src/lib/components/events/EventItemPopover.tsx +0 -179
- package/src/lib/components/events/MonthEvents.tsx +0 -141
- package/src/lib/components/events/TodayEvents.tsx +0 -99
- package/src/lib/components/hoc/DateProvider.tsx +0 -19
- package/src/lib/components/inputs/DatePicker.tsx +0 -95
- package/src/lib/components/inputs/Input.tsx +0 -113
- package/src/lib/components/inputs/SelectInput.tsx +0 -164
- package/src/lib/components/month/MonthTable.tsx +0 -207
- package/src/lib/components/nav/DayDateBtn.tsx +0 -77
- package/src/lib/components/nav/MonthDateBtn.tsx +0 -80
- package/src/lib/components/nav/Navigation.tsx +0 -201
- package/src/lib/components/nav/WeekDateBtn.tsx +0 -89
- package/src/lib/components/week/WeekTable.tsx +0 -229
- package/src/lib/helpers/constants.ts +0 -4
- package/src/lib/helpers/generals.tsx +0 -354
- package/src/lib/hooks/useArrowDisable.ts +0 -26
- package/src/lib/hooks/useCellAttributes.ts +0 -67
- package/src/lib/hooks/useDragAttributes.ts +0 -31
- package/src/lib/hooks/useEventPermissions.ts +0 -42
- package/src/lib/hooks/useStore.ts +0 -8
- package/src/lib/hooks/useSyncScroll.ts +0 -31
- package/src/lib/hooks/useWindowResize.ts +0 -37
- package/src/lib/index.tsx +0 -14
- package/src/lib/positionManger/context.ts +0 -14
- package/src/lib/positionManger/provider.tsx +0 -113
- package/src/lib/positionManger/usePosition.ts +0 -8
- package/src/lib/store/context.ts +0 -5
- package/src/lib/store/default.ts +0 -157
- package/src/lib/store/provider.tsx +0 -211
- package/src/lib/store/types.ts +0 -33
- package/src/lib/styles/styles.ts +0 -256
- package/src/lib/types.ts +0 -423
- package/src/lib/views/Day.tsx +0 -265
- package/src/lib/views/DayAgenda.tsx +0 -57
- package/src/lib/views/Editor.tsx +0 -258
- package/src/lib/views/Month.tsx +0 -82
- package/src/lib/views/MonthAgenda.tsx +0 -84
- package/src/lib/views/Week.tsx +0 -92
- package/src/lib/views/WeekAgenda.tsx +0 -81
- package/src/vite-env.d.ts +0 -3
- package/tsconfig.build.json +0 -5
- package/tsconfig.json +0 -27
- package/vite.config.js +0 -40
- /package/{dist/SchedulerComponent.d.ts → SchedulerComponent.d.ts} +0 -0
- /package/{dist/components → components}/common/Cell.d.ts +0 -0
- /package/{dist/components → components}/common/LocaleArrow.d.ts +0 -0
- /package/{dist/components → components}/common/ResourceHeader.d.ts +0 -0
- /package/{dist/components → components}/common/Tabs.d.ts +0 -0
- /package/{dist/components → components}/common/TodayTypo.d.ts +0 -0
- /package/{dist/components → components}/common/WithResources.d.ts +0 -0
- /package/{dist/components → components}/events/Actions.d.ts +0 -0
- /package/{dist/components → components}/events/AgendaEventsList.d.ts +0 -0
- /package/{dist/components → components}/events/CurrentTimeBar.d.ts +0 -0
- /package/{dist/components → components}/events/EmptyAgenda.d.ts +0 -0
- /package/{dist/components → components}/events/EventItem.d.ts +0 -0
- /package/{dist/components → components}/events/EventItemPopover.d.ts +0 -0
- /package/{dist/components → components}/events/MonthEvents.d.ts +0 -0
- /package/{dist/components → components}/events/TodayEvents.d.ts +0 -0
- /package/{dist/components → components}/hoc/DateProvider.d.ts +0 -0
- /package/{dist/components → components}/inputs/DatePicker.d.ts +0 -0
- /package/{dist/components → components}/inputs/Input.d.ts +0 -0
- /package/{dist/components → components}/inputs/SelectInput.d.ts +0 -0
- /package/{dist/components → components}/month/MonthTable.d.ts +0 -0
- /package/{dist/components → components}/nav/DayDateBtn.d.ts +0 -0
- /package/{dist/components → components}/nav/MonthDateBtn.d.ts +0 -0
- /package/{dist/components → components}/nav/Navigation.d.ts +0 -0
- /package/{dist/components → components}/nav/WeekDateBtn.d.ts +0 -0
- /package/{dist/components → components}/week/WeekTable.d.ts +0 -0
- /package/{dist/helpers → helpers}/constants.d.ts +0 -0
- /package/{dist/helpers → helpers}/generals.d.ts +0 -0
- /package/{dist/hooks → hooks}/useArrowDisable.d.ts +0 -0
- /package/{dist/hooks → hooks}/useCellAttributes.d.ts +0 -0
- /package/{dist/hooks → hooks}/useDragAttributes.d.ts +0 -0
- /package/{dist/hooks → hooks}/useEventPermissions.d.ts +0 -0
- /package/{dist/hooks → hooks}/useStore.d.ts +0 -0
- /package/{dist/hooks → hooks}/useSyncScroll.d.ts +0 -0
- /package/{dist/hooks → hooks}/useWindowResize.d.ts +0 -0
- /package/{dist/index.d.ts → index.d.ts} +0 -0
- /package/{dist/positionManger → positionManger}/context.d.ts +0 -0
- /package/{dist/positionManger → positionManger}/provider.d.ts +0 -0
- /package/{dist/positionManger → positionManger}/usePosition.d.ts +0 -0
- /package/{dist/store → store}/context.d.ts +0 -0
- /package/{dist/store → store}/default.d.ts +0 -0
- /package/{dist/store → store}/provider.d.ts +0 -0
- /package/{dist/store → store}/types.d.ts +0 -0
- /package/{dist/styles → styles}/styles.d.ts +0 -0
- /package/{dist/types.d.ts → types.d.ts} +0 -0
- /package/{dist/views → views}/Day.d.ts +0 -0
- /package/{dist/views → views}/DayAgenda.d.ts +0 -0
- /package/{dist/views → views}/Editor.d.ts +0 -0
- /package/{dist/views → views}/Month.d.ts +0 -0
- /package/{dist/views → views}/MonthAgenda.d.ts +0 -0
- /package/{dist/views → views}/Week.d.ts +0 -0
- /package/{dist/views → views}/WeekAgenda.d.ts +0 -0
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { render, screen } from "@testing-library/react";
|
|
2
|
-
import { Scheduler } from "..";
|
|
3
|
-
import "@testing-library/jest-dom";
|
|
4
|
-
|
|
5
|
-
describe("Render scheduler", () => {
|
|
6
|
-
it("Default render", () => {
|
|
7
|
-
render(<Scheduler />);
|
|
8
|
-
|
|
9
|
-
// Scheduler component
|
|
10
|
-
const scheduler = screen.getByTestId("rs-wrapper");
|
|
11
|
-
expect(scheduler).toBeInTheDocument();
|
|
12
|
-
|
|
13
|
-
// Navigators
|
|
14
|
-
const viewNavigator = screen.getByTestId("view-navigator");
|
|
15
|
-
expect(viewNavigator).toBeInTheDocument();
|
|
16
|
-
|
|
17
|
-
const dateNavigator = screen.getByTestId("date-navigator");
|
|
18
|
-
expect(dateNavigator).toBeInTheDocument();
|
|
19
|
-
expect(dateNavigator.getElementsByTagName("button").length).toEqual(3);
|
|
20
|
-
|
|
21
|
-
const grid = screen.getByTestId("grid");
|
|
22
|
-
expect(grid).toBeInTheDocument();
|
|
23
|
-
});
|
|
24
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { Button } from "@mui/material";
|
|
2
|
-
import { useCellAttributes } from "../../hooks/useCellAttributes";
|
|
3
|
-
import { CellRenderedProps } from "../../types";
|
|
4
|
-
|
|
5
|
-
interface CellProps {
|
|
6
|
-
day: Date;
|
|
7
|
-
start: Date;
|
|
8
|
-
height: number;
|
|
9
|
-
end: Date;
|
|
10
|
-
resourceKey: string;
|
|
11
|
-
resourceVal: string | number;
|
|
12
|
-
cellRenderer?(props: CellRenderedProps): React.ReactNode;
|
|
13
|
-
children?: React.ReactNode;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const Cell = ({
|
|
17
|
-
day,
|
|
18
|
-
start,
|
|
19
|
-
end,
|
|
20
|
-
resourceKey,
|
|
21
|
-
resourceVal,
|
|
22
|
-
cellRenderer,
|
|
23
|
-
height,
|
|
24
|
-
children,
|
|
25
|
-
}: CellProps) => {
|
|
26
|
-
const props = useCellAttributes({ start, end, resourceKey, resourceVal });
|
|
27
|
-
|
|
28
|
-
if (cellRenderer) {
|
|
29
|
-
return cellRenderer({
|
|
30
|
-
day,
|
|
31
|
-
start,
|
|
32
|
-
end,
|
|
33
|
-
height,
|
|
34
|
-
...props,
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<Button
|
|
40
|
-
fullWidth
|
|
41
|
-
aria-label={`${start.toLocaleString("en", {
|
|
42
|
-
dateStyle: "full",
|
|
43
|
-
timeStyle: "long",
|
|
44
|
-
})} - ${end.toLocaleString("en", { dateStyle: "full", timeStyle: "long" })}`}
|
|
45
|
-
{...props}
|
|
46
|
-
>
|
|
47
|
-
{children}
|
|
48
|
-
</Button>
|
|
49
|
-
);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export default Cell;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import NavigateBeforeRoundedIcon from "@mui/icons-material/NavigateBeforeRounded";
|
|
2
|
-
import NavigateNextRoundedIcon from "@mui/icons-material/NavigateNextRounded";
|
|
3
|
-
import { IconButton, IconButtonProps } from "@mui/material";
|
|
4
|
-
import { MouseEvent } from "react";
|
|
5
|
-
import useStore from "../../hooks/useStore";
|
|
6
|
-
|
|
7
|
-
interface LocaleArrowProps extends Omit<IconButtonProps, "type"> {
|
|
8
|
-
type: "prev" | "next";
|
|
9
|
-
onClick?(e?: MouseEvent): void;
|
|
10
|
-
}
|
|
11
|
-
const LocaleArrow = ({ type, onClick, ...props }: LocaleArrowProps) => {
|
|
12
|
-
const { direction } = useStore();
|
|
13
|
-
|
|
14
|
-
let Arrow = NavigateNextRoundedIcon;
|
|
15
|
-
if (type === "prev") {
|
|
16
|
-
Arrow = direction === "rtl" ? NavigateNextRoundedIcon : NavigateBeforeRoundedIcon;
|
|
17
|
-
} else if (type === "next") {
|
|
18
|
-
Arrow = direction === "rtl" ? NavigateBeforeRoundedIcon : NavigateNextRoundedIcon;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<IconButton
|
|
23
|
-
style={{ padding: 2 }}
|
|
24
|
-
onClick={onClick}
|
|
25
|
-
onDragOver={(e) => {
|
|
26
|
-
e.preventDefault();
|
|
27
|
-
if (onClick) {
|
|
28
|
-
onClick();
|
|
29
|
-
}
|
|
30
|
-
}}
|
|
31
|
-
{...props}
|
|
32
|
-
>
|
|
33
|
-
<Arrow />
|
|
34
|
-
</IconButton>
|
|
35
|
-
);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export { LocaleArrow };
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Avatar,
|
|
3
|
-
ListItem,
|
|
4
|
-
ListItemAvatar,
|
|
5
|
-
ListItemText,
|
|
6
|
-
Typography,
|
|
7
|
-
useTheme,
|
|
8
|
-
} from "@mui/material";
|
|
9
|
-
import { DefaultResource } from "../../types";
|
|
10
|
-
import useStore from "../../hooks/useStore";
|
|
11
|
-
|
|
12
|
-
interface ResourceHeaderProps {
|
|
13
|
-
resource: DefaultResource;
|
|
14
|
-
}
|
|
15
|
-
const ResourceHeader = ({ resource }: ResourceHeaderProps) => {
|
|
16
|
-
const { resourceHeaderComponent, resourceFields, direction, resourceViewMode } = useStore();
|
|
17
|
-
const theme = useTheme();
|
|
18
|
-
|
|
19
|
-
const text = resource[resourceFields.textField];
|
|
20
|
-
const subtext = resource[resourceFields.subTextField || ""];
|
|
21
|
-
const avatar = resource[resourceFields.avatarField || ""];
|
|
22
|
-
const color = resource[resourceFields.colorField || ""];
|
|
23
|
-
|
|
24
|
-
if (resourceHeaderComponent instanceof Function) {
|
|
25
|
-
return resourceHeaderComponent(resource);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<ListItem
|
|
30
|
-
sx={{
|
|
31
|
-
padding: "2px 10px",
|
|
32
|
-
textAlign: direction === "rtl" ? "right" : "left",
|
|
33
|
-
...(resourceViewMode === "tabs"
|
|
34
|
-
? {}
|
|
35
|
-
: resourceViewMode === "vertical"
|
|
36
|
-
? {
|
|
37
|
-
display: "block",
|
|
38
|
-
textAlign: "center",
|
|
39
|
-
position: "sticky",
|
|
40
|
-
top: 4,
|
|
41
|
-
}
|
|
42
|
-
: {
|
|
43
|
-
borderColor: theme.palette.grey[300],
|
|
44
|
-
borderStyle: "solid",
|
|
45
|
-
borderWidth: 1,
|
|
46
|
-
}),
|
|
47
|
-
}}
|
|
48
|
-
component="div"
|
|
49
|
-
>
|
|
50
|
-
<ListItemAvatar>
|
|
51
|
-
<Avatar sx={{ background: color, margin: "auto" }} alt={text} src={avatar} />
|
|
52
|
-
</ListItemAvatar>
|
|
53
|
-
<ListItemText
|
|
54
|
-
primary={
|
|
55
|
-
<Typography variant="body2" noWrap={resourceViewMode !== "vertical"}>
|
|
56
|
-
{text}
|
|
57
|
-
</Typography>
|
|
58
|
-
}
|
|
59
|
-
secondary={
|
|
60
|
-
<Typography
|
|
61
|
-
variant="caption"
|
|
62
|
-
color="textSecondary"
|
|
63
|
-
noWrap={resourceViewMode !== "vertical"}
|
|
64
|
-
>
|
|
65
|
-
{subtext}
|
|
66
|
-
</Typography>
|
|
67
|
-
}
|
|
68
|
-
/>
|
|
69
|
-
</ListItem>
|
|
70
|
-
);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export { ResourceHeader };
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { CSSProperties } from "react";
|
|
2
|
-
import { Tabs, Tab } from "@mui/material";
|
|
3
|
-
import { styled } from "@mui/material/styles";
|
|
4
|
-
import { Theme } from "@mui/system";
|
|
5
|
-
|
|
6
|
-
interface TabPanelProps {
|
|
7
|
-
value: string | number;
|
|
8
|
-
index: string | number;
|
|
9
|
-
children: React.ReactNode;
|
|
10
|
-
}
|
|
11
|
-
function TabPanel(props: TabPanelProps) {
|
|
12
|
-
const { children, value, index } = props;
|
|
13
|
-
return value === index ? <>{children}</> : <></>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function a11yProps(index: string | number) {
|
|
17
|
-
return {
|
|
18
|
-
id: `scrollable-auto-tab-${index}`,
|
|
19
|
-
"aria-controls": `scrollable-auto-tabpanel-${index}`,
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const StyledTaps = styled("div")(({ theme }: { theme: Theme }) => ({
|
|
24
|
-
flexGrow: 1,
|
|
25
|
-
width: "100%",
|
|
26
|
-
backgroundColor: theme.palette.background.paper,
|
|
27
|
-
alignSelf: "center",
|
|
28
|
-
"& .tabs": {
|
|
29
|
-
borderColor: theme.palette.grey[300],
|
|
30
|
-
borderStyle: "solid",
|
|
31
|
-
borderWidth: 1,
|
|
32
|
-
"& button.MuiTab-root": {
|
|
33
|
-
borderColor: theme.palette.grey[300],
|
|
34
|
-
borderRightStyle: "solid",
|
|
35
|
-
borderWidth: 1,
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
"& .primary": {
|
|
39
|
-
background: theme.palette.primary.main,
|
|
40
|
-
},
|
|
41
|
-
"& .secondary": {
|
|
42
|
-
background: theme.palette.secondary.main,
|
|
43
|
-
},
|
|
44
|
-
"& .error": {
|
|
45
|
-
background: theme.palette.error.main,
|
|
46
|
-
},
|
|
47
|
-
"& .info": {
|
|
48
|
-
background: theme.palette.info.dark,
|
|
49
|
-
},
|
|
50
|
-
"& .text_primary": {
|
|
51
|
-
color: theme.palette.primary.main,
|
|
52
|
-
},
|
|
53
|
-
"& .text_secondary": {
|
|
54
|
-
color: theme.palette.secondary.main,
|
|
55
|
-
},
|
|
56
|
-
"& .text_error": {
|
|
57
|
-
color: theme.palette.error.main,
|
|
58
|
-
},
|
|
59
|
-
"& .text_info": {
|
|
60
|
-
color: theme.palette.info.dark,
|
|
61
|
-
},
|
|
62
|
-
}));
|
|
63
|
-
|
|
64
|
-
export type ButtonTabProps = {
|
|
65
|
-
id: string | number;
|
|
66
|
-
label: string | React.ReactNode;
|
|
67
|
-
component: React.ReactNode;
|
|
68
|
-
};
|
|
69
|
-
interface ButtonTabsProps {
|
|
70
|
-
tabs: ButtonTabProps[];
|
|
71
|
-
tab: string | number;
|
|
72
|
-
setTab(tab: string | number): void;
|
|
73
|
-
variant?: "scrollable" | "standard" | "fullWidth";
|
|
74
|
-
indicator?: "primary" | "secondary" | "info" | "error";
|
|
75
|
-
style?: CSSProperties;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const ButtonTabs = ({
|
|
79
|
-
tabs,
|
|
80
|
-
variant = "scrollable",
|
|
81
|
-
tab,
|
|
82
|
-
setTab,
|
|
83
|
-
indicator = "primary",
|
|
84
|
-
style,
|
|
85
|
-
}: ButtonTabsProps) => {
|
|
86
|
-
return (
|
|
87
|
-
<StyledTaps style={style}>
|
|
88
|
-
<Tabs
|
|
89
|
-
value={tab}
|
|
90
|
-
variant={variant}
|
|
91
|
-
scrollButtons
|
|
92
|
-
className="tabs"
|
|
93
|
-
classes={{ indicator: indicator }}
|
|
94
|
-
>
|
|
95
|
-
{tabs.map((tab: ButtonTabProps, i: number) => (
|
|
96
|
-
<Tab
|
|
97
|
-
key={tab.id || i}
|
|
98
|
-
label={tab.label}
|
|
99
|
-
sx={{ flex: 1, flexBasis: 200, flexShrink: 0 }}
|
|
100
|
-
value={tab.id}
|
|
101
|
-
{...a11yProps(tab.id)}
|
|
102
|
-
onClick={() => setTab(tab.id)}
|
|
103
|
-
onDragEnter={() => setTab(tab.id)}
|
|
104
|
-
/>
|
|
105
|
-
))}
|
|
106
|
-
</Tabs>
|
|
107
|
-
{tabs.map(
|
|
108
|
-
(t: ButtonTabProps, i: number) =>
|
|
109
|
-
t.component && (
|
|
110
|
-
<TabPanel key={i} value={tab} index={t.id}>
|
|
111
|
-
{t.component}
|
|
112
|
-
</TabPanel>
|
|
113
|
-
)
|
|
114
|
-
)}
|
|
115
|
-
</StyledTaps>
|
|
116
|
-
);
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
export { ButtonTabs };
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Typography } from "@mui/material";
|
|
2
|
-
import { format, Locale } from "date-fns";
|
|
3
|
-
import { isTimeZonedToday } from "../../helpers/generals";
|
|
4
|
-
import useStore from "../../hooks/useStore";
|
|
5
|
-
|
|
6
|
-
interface TodayTypoProps {
|
|
7
|
-
date: Date;
|
|
8
|
-
onClick?(day: Date): void;
|
|
9
|
-
locale: Locale;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const TodayTypo = ({ date, onClick, locale }: TodayTypoProps) => {
|
|
13
|
-
const { timeZone } = useStore();
|
|
14
|
-
const today = isTimeZonedToday({ dateLeft: date, timeZone });
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<div>
|
|
18
|
-
<Typography
|
|
19
|
-
style={{
|
|
20
|
-
fontWeight: today ? "bold" : "inherit",
|
|
21
|
-
}}
|
|
22
|
-
color={today ? "primary" : "inherit"}
|
|
23
|
-
className={onClick ? "rs__hover__op" : ""}
|
|
24
|
-
onClick={(e) => {
|
|
25
|
-
e.stopPropagation();
|
|
26
|
-
if (onClick) onClick(date);
|
|
27
|
-
}}
|
|
28
|
-
>
|
|
29
|
-
{format(date, "dd", { locale })}
|
|
30
|
-
</Typography>
|
|
31
|
-
<Typography
|
|
32
|
-
color={today ? "primary" : "inherit"}
|
|
33
|
-
style={{
|
|
34
|
-
fontWeight: today ? "bold" : "inherit",
|
|
35
|
-
fontSize: 11,
|
|
36
|
-
}}
|
|
37
|
-
>
|
|
38
|
-
{format(date, "eee", { locale })}
|
|
39
|
-
</Typography>
|
|
40
|
-
</div>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export default TodayTypo;
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
2
|
-
import { DefaultResource } from "../../types";
|
|
3
|
-
import { ResourceHeader } from "./ResourceHeader";
|
|
4
|
-
import { ButtonTabProps, ButtonTabs } from "./Tabs";
|
|
5
|
-
import useStore from "../../hooks/useStore";
|
|
6
|
-
import { Box, useTheme } from "@mui/material";
|
|
7
|
-
|
|
8
|
-
interface WithResourcesProps {
|
|
9
|
-
renderChildren(resource: DefaultResource): React.ReactNode;
|
|
10
|
-
}
|
|
11
|
-
const WithResources = ({ renderChildren }: WithResourcesProps) => {
|
|
12
|
-
const { resources, resourceFields, resourceViewMode } = useStore();
|
|
13
|
-
const theme = useTheme();
|
|
14
|
-
|
|
15
|
-
if (resourceViewMode === "tabs") {
|
|
16
|
-
return <ResourcesTabTables renderChildren={renderChildren} />;
|
|
17
|
-
} else if (resourceViewMode === "vertical") {
|
|
18
|
-
return (
|
|
19
|
-
<>
|
|
20
|
-
{resources.map((res: DefaultResource, i: number) => (
|
|
21
|
-
<Box key={`${res[resourceFields.idField]}_${i}`} sx={{ display: "flex" }}>
|
|
22
|
-
<Box
|
|
23
|
-
sx={{
|
|
24
|
-
borderColor: theme.palette.grey[300],
|
|
25
|
-
borderStyle: "solid",
|
|
26
|
-
borderWidth: "1px 1px 0 1px",
|
|
27
|
-
paddingTop: 1,
|
|
28
|
-
flexBasis: 140,
|
|
29
|
-
}}
|
|
30
|
-
>
|
|
31
|
-
<ResourceHeader resource={res} />
|
|
32
|
-
</Box>
|
|
33
|
-
<Box
|
|
34
|
-
//
|
|
35
|
-
sx={{ width: "100%", overflowX: "auto" }}
|
|
36
|
-
>
|
|
37
|
-
{renderChildren(res)}
|
|
38
|
-
</Box>
|
|
39
|
-
</Box>
|
|
40
|
-
))}
|
|
41
|
-
</>
|
|
42
|
-
);
|
|
43
|
-
} else {
|
|
44
|
-
return (
|
|
45
|
-
<>
|
|
46
|
-
{resources.map((res: DefaultResource, i: number) => (
|
|
47
|
-
<div key={`${res[resourceFields.idField]}_${i}`}>
|
|
48
|
-
<ResourceHeader resource={res} />
|
|
49
|
-
{renderChildren(res)}
|
|
50
|
-
</div>
|
|
51
|
-
))}
|
|
52
|
-
</>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const ResourcesTabTables = ({ renderChildren }: WithResourcesProps) => {
|
|
58
|
-
const { resources, resourceFields, selectedTab, handleState, onResourceChange } = useStore();
|
|
59
|
-
|
|
60
|
-
const tabs: ButtonTabProps[] = resources.map((res) => {
|
|
61
|
-
return {
|
|
62
|
-
id: res[resourceFields.idField],
|
|
63
|
-
label: <ResourceHeader resource={res} />,
|
|
64
|
-
component: <>{renderChildren(res)}</>,
|
|
65
|
-
};
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const setTab = (tab: DefaultResource["assignee"]) => {
|
|
69
|
-
handleState(tab, "selectedTab");
|
|
70
|
-
if (typeof onResourceChange === "function") {
|
|
71
|
-
const selected = resources.find((re) => re[resourceFields.idField] === tab);
|
|
72
|
-
if (selected) {
|
|
73
|
-
onResourceChange(selected);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const currentTabSafeId = useMemo(() => {
|
|
79
|
-
const firstId = resources[0][resourceFields.idField];
|
|
80
|
-
if (!selectedTab) {
|
|
81
|
-
return firstId;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Make sure current selected id is within the resources array
|
|
85
|
-
const idx = resources.findIndex((re) => re[resourceFields.idField] === selectedTab);
|
|
86
|
-
if (idx < 0) {
|
|
87
|
-
return firstId;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return selectedTab;
|
|
91
|
-
}, [resources, resourceFields.idField, selectedTab]);
|
|
92
|
-
|
|
93
|
-
return (
|
|
94
|
-
<ButtonTabs tabs={tabs} tab={currentTabSafeId} setTab={setTab} style={{ display: "grid" }} />
|
|
95
|
-
);
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
export { WithResources };
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import DeleteRounded from "@mui/icons-material/DeleteRounded";
|
|
2
|
-
import EditRounded from "@mui/icons-material/EditRounded";
|
|
3
|
-
import { Button, Grow, IconButton, Slide } from "@mui/material";
|
|
4
|
-
import { useState } from "react";
|
|
5
|
-
import { EventActions as Actions } from "../../styles/styles";
|
|
6
|
-
import { ProcessedEvent } from "../../types";
|
|
7
|
-
import useStore from "../../hooks/useStore";
|
|
8
|
-
import useEventPermissions from "../../hooks/useEventPermissions";
|
|
9
|
-
|
|
10
|
-
interface Props {
|
|
11
|
-
event: ProcessedEvent;
|
|
12
|
-
onDelete(): void;
|
|
13
|
-
onEdit(): void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const EventActions = ({ event, onDelete, onEdit }: Props) => {
|
|
17
|
-
const { translations, direction } = useStore();
|
|
18
|
-
const [deleteConfirm, setDeleteConfirm] = useState(false);
|
|
19
|
-
|
|
20
|
-
const handleDelete = () => {
|
|
21
|
-
if (!deleteConfirm) {
|
|
22
|
-
return setDeleteConfirm(true);
|
|
23
|
-
}
|
|
24
|
-
onDelete();
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const { canEdit, canDelete } = useEventPermissions(event);
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<Actions>
|
|
31
|
-
<Grow in={!deleteConfirm} exit={false} timeout={400} unmountOnExit>
|
|
32
|
-
<div>
|
|
33
|
-
{canEdit && (
|
|
34
|
-
<IconButton size="small" onClick={onEdit}>
|
|
35
|
-
<EditRounded />
|
|
36
|
-
</IconButton>
|
|
37
|
-
)}
|
|
38
|
-
{canDelete && (
|
|
39
|
-
<IconButton size="small" onClick={handleDelete}>
|
|
40
|
-
<DeleteRounded />
|
|
41
|
-
</IconButton>
|
|
42
|
-
)}
|
|
43
|
-
</div>
|
|
44
|
-
</Grow>
|
|
45
|
-
<Slide
|
|
46
|
-
in={deleteConfirm}
|
|
47
|
-
direction={direction === "rtl" ? "right" : "left"}
|
|
48
|
-
unmountOnExit
|
|
49
|
-
timeout={400}
|
|
50
|
-
exit={false}
|
|
51
|
-
>
|
|
52
|
-
<div>
|
|
53
|
-
<Button className="delete" size="small" onClick={handleDelete}>
|
|
54
|
-
{translations.form.delete.toUpperCase()}
|
|
55
|
-
</Button>
|
|
56
|
-
<Button className="cancel" size="small" onClick={() => setDeleteConfirm(false)}>
|
|
57
|
-
{translations.form.cancel.toUpperCase()}
|
|
58
|
-
</Button>
|
|
59
|
-
</div>
|
|
60
|
-
</Slide>
|
|
61
|
-
</Actions>
|
|
62
|
-
);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export default EventActions;
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { Fragment, MouseEvent, useState } from "react";
|
|
2
|
-
import {
|
|
3
|
-
useTheme,
|
|
4
|
-
List,
|
|
5
|
-
ListItemButton,
|
|
6
|
-
ListItemAvatar,
|
|
7
|
-
Avatar,
|
|
8
|
-
ListItemText,
|
|
9
|
-
} from "@mui/material";
|
|
10
|
-
import { format } from "date-fns";
|
|
11
|
-
import { ProcessedEvent } from "../../types";
|
|
12
|
-
import { getHourFormat, isTimeZonedToday } from "../../helpers/generals";
|
|
13
|
-
import useStore from "../../hooks/useStore";
|
|
14
|
-
import EventItemPopover from "./EventItemPopover";
|
|
15
|
-
|
|
16
|
-
interface AgendaEventsListProps {
|
|
17
|
-
day: Date;
|
|
18
|
-
events: ProcessedEvent[];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const AgendaEventsList = ({ day, events }: AgendaEventsListProps) => {
|
|
22
|
-
const [anchorEl, setAnchorEl] = useState<Element | null>(null);
|
|
23
|
-
const [selectedEvent, setSelectedEvent] = useState<ProcessedEvent>();
|
|
24
|
-
const [deleteConfirm, setDeleteConfirm] = useState(false);
|
|
25
|
-
const { locale, hourFormat, eventRenderer, onEventClick, timeZone, disableViewer } = useStore();
|
|
26
|
-
const theme = useTheme();
|
|
27
|
-
const hFormat = getHourFormat(hourFormat);
|
|
28
|
-
|
|
29
|
-
const triggerViewer = (el?: MouseEvent<Element>) => {
|
|
30
|
-
if (!el?.currentTarget && deleteConfirm) {
|
|
31
|
-
setDeleteConfirm(false);
|
|
32
|
-
}
|
|
33
|
-
setAnchorEl(el?.currentTarget || null);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<Fragment>
|
|
38
|
-
<List>
|
|
39
|
-
{events.map((event) => {
|
|
40
|
-
const startIsToday = isTimeZonedToday({
|
|
41
|
-
dateLeft: event.start,
|
|
42
|
-
dateRight: day,
|
|
43
|
-
timeZone,
|
|
44
|
-
});
|
|
45
|
-
const startFormat = startIsToday ? hFormat : `MMM d, ${hFormat}`;
|
|
46
|
-
const startDate = format(event.start, startFormat, {
|
|
47
|
-
locale,
|
|
48
|
-
});
|
|
49
|
-
const endIsToday = isTimeZonedToday({ dateLeft: event.end, dateRight: day, timeZone });
|
|
50
|
-
|
|
51
|
-
const endFormat = endIsToday ? hFormat : `MMM d, ${hFormat}`;
|
|
52
|
-
const endDate = format(event.end, endFormat, {
|
|
53
|
-
locale,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
if (typeof eventRenderer === "function") {
|
|
57
|
-
return eventRenderer({
|
|
58
|
-
event,
|
|
59
|
-
onClick: (e) => {
|
|
60
|
-
setSelectedEvent(event);
|
|
61
|
-
triggerViewer(e);
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<ListItemButton
|
|
68
|
-
key={`${event.start.getTime()}_${event.end.getTime()}_${event.event_id}`}
|
|
69
|
-
focusRipple
|
|
70
|
-
disableRipple={disableViewer}
|
|
71
|
-
tabIndex={disableViewer ? -1 : 0}
|
|
72
|
-
disabled={event.disabled}
|
|
73
|
-
onClick={(e) => {
|
|
74
|
-
e.preventDefault();
|
|
75
|
-
e.stopPropagation();
|
|
76
|
-
if (!disableViewer) {
|
|
77
|
-
triggerViewer(e);
|
|
78
|
-
}
|
|
79
|
-
setSelectedEvent(event);
|
|
80
|
-
if (typeof onEventClick === "function") {
|
|
81
|
-
onEventClick(event);
|
|
82
|
-
}
|
|
83
|
-
}}
|
|
84
|
-
>
|
|
85
|
-
<ListItemAvatar>
|
|
86
|
-
<Avatar
|
|
87
|
-
sx={{
|
|
88
|
-
bgcolor: event.disabled ? "#d0d0d0" : event.color || theme.palette.primary.main,
|
|
89
|
-
color: event.disabled
|
|
90
|
-
? "#808080"
|
|
91
|
-
: event.textColor || theme.palette.primary.contrastText,
|
|
92
|
-
}}
|
|
93
|
-
>
|
|
94
|
-
{event.agendaAvatar || " "}
|
|
95
|
-
</Avatar>
|
|
96
|
-
</ListItemAvatar>
|
|
97
|
-
<ListItemText primary={event.title} secondary={`${startDate} - ${endDate}`} />
|
|
98
|
-
</ListItemButton>
|
|
99
|
-
);
|
|
100
|
-
})}
|
|
101
|
-
</List>
|
|
102
|
-
|
|
103
|
-
{/* Viewer */}
|
|
104
|
-
{selectedEvent && (
|
|
105
|
-
<EventItemPopover
|
|
106
|
-
anchorEl={anchorEl}
|
|
107
|
-
event={selectedEvent}
|
|
108
|
-
onTriggerViewer={triggerViewer}
|
|
109
|
-
/>
|
|
110
|
-
)}
|
|
111
|
-
</Fragment>
|
|
112
|
-
);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
export default AgendaEventsList;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
2
|
-
import { differenceInMinutes, set } from "date-fns";
|
|
3
|
-
import { BORDER_HEIGHT } from "../../helpers/constants";
|
|
4
|
-
import { getTimeZonedDate } from "../../helpers/generals";
|
|
5
|
-
import { TimeIndicatorBar } from "../../styles/styles";
|
|
6
|
-
|
|
7
|
-
interface CurrentTimeBarProps {
|
|
8
|
-
startHour: number;
|
|
9
|
-
step: number;
|
|
10
|
-
minuteHeight: number;
|
|
11
|
-
timeZone?: string;
|
|
12
|
-
zIndex?: number;
|
|
13
|
-
currentTime?: Date;
|
|
14
|
-
color?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function calculateTop({
|
|
18
|
-
startHour,
|
|
19
|
-
step,
|
|
20
|
-
minuteHeight,
|
|
21
|
-
timeZone,
|
|
22
|
-
currentTime,
|
|
23
|
-
}: CurrentTimeBarProps): number {
|
|
24
|
-
const now = currentTime
|
|
25
|
-
? getTimeZonedDate(currentTime, timeZone)
|
|
26
|
-
: getTimeZonedDate(new Date(), timeZone);
|
|
27
|
-
|
|
28
|
-
const minutesFromTop = differenceInMinutes(now, set(now, { hours: startHour, minutes: 0 }));
|
|
29
|
-
const topSpace = minutesFromTop * minuteHeight;
|
|
30
|
-
const slotsFromTop = minutesFromTop / step;
|
|
31
|
-
const borderFactor = slotsFromTop + BORDER_HEIGHT;
|
|
32
|
-
const top = topSpace + borderFactor;
|
|
33
|
-
|
|
34
|
-
return top;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const CurrentTimeBar = (props: CurrentTimeBarProps) => {
|
|
38
|
-
const [top, setTop] = useState(calculateTop(props));
|
|
39
|
-
const { startHour, step, minuteHeight, timeZone, currentTime, color } = props;
|
|
40
|
-
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
const calcProps = { startHour, step, minuteHeight, timeZone, currentTime };
|
|
43
|
-
setTop(calculateTop(calcProps));
|
|
44
|
-
const interval = setInterval(() => setTop(calculateTop(calcProps)), 60 * 1000);
|
|
45
|
-
return () => clearInterval(interval);
|
|
46
|
-
}, [startHour, step, minuteHeight, timeZone, currentTime]);
|
|
47
|
-
|
|
48
|
-
// Prevent showing bar on top of days/header
|
|
49
|
-
if (top < 0) return null;
|
|
50
|
-
|
|
51
|
-
return (
|
|
52
|
-
<TimeIndicatorBar style={{ top, zIndex: props.zIndex }} color={color}>
|
|
53
|
-
<div />
|
|
54
|
-
<div />
|
|
55
|
-
</TimeIndicatorBar>
|
|
56
|
-
);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export default CurrentTimeBar;
|