Skip to content

[WC-2790]: update design/structure modes on Calendar #1626

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 18, 2025
Merged
31 changes: 31 additions & 0 deletions packages/pluggableWidgets/calendar-web/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import commonjs from "@rollup/plugin-commonjs";

export default args => {
const result = args.configDefaultConfig;
return result.map(config => {
config.output.inlineDynamicImports = true;
if (config.output.format !== "es") {
return config;
}
return {
...config,
plugins: [
...config.plugins.map(plugin => {
if (plugin && plugin.name === "commonjs") {
// replace common js plugin that transforms
// external requires to imports
// this is needed in order to work with modern client
return commonjs({
extensions: [".js", ".jsx", ".tsx", ".ts"],
transformMixedEsModules: true,
requireReturnsDefault: "auto",
esmExternals: true
});
}

return plugin;
})
]
};
});
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import {
StructurePreviewProps,
container,
rowLayout,
structurePreviewPalette,
StructurePreviewProps,
svgImage,
text
} from "@mendix/widget-plugin-platform/preview/structure-preview-api";
import { Properties, hidePropertyIn, hidePropertiesIn } from "@mendix/pluggable-widgets-tools";
import { CalendarPreviewProps } from "../typings/CalendarProps";
import IconSVGDark from "./assets/StructureCalendarDark.svg";
import IconSVG from "./assets/StructureCalendarLight.svg";

export function getProperties(values: CalendarPreviewProps, defaultProperties: Properties): Properties {
if (values.heightUnit === "percentageOfWidth") {
Expand Down Expand Up @@ -41,10 +44,20 @@ export function getProperties(values: CalendarPreviewProps, defaultProperties: P

export function getPreview(_values: CalendarPreviewProps, isDarkMode: boolean): StructurePreviewProps {
const palette = structurePreviewPalette[isDarkMode ? "dark" : "light"];
const readOnly = _values.readOnly;

return rowLayout({ columnSize: "grow", borders: true, backgroundColor: palette.background.containerFill })(
container()(),
rowLayout({ grow: 2, padding: 8 })(text({ fontColor: palette.text.primary, grow: 10 })("calendar")),
container()()
return container({
backgroundColor: readOnly ? palette.background.containerDisabled : palette.background.topbarData,
borders: true
})(
rowLayout({
columnSize: "grow",
padding: 6
})(
svgImage({ width: 16, height: 16, grow: 0 })(
decodeURIComponent((isDarkMode ? IconSVGDark : IconSVG).replace("data:image/svg+xml,", ""))
),
text({ fontColor: palette.text.primary })("Calendar")
)
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { ReactElement, createElement } from "react";
import { Calendar, dateFnsLocalizer } from "react-big-calendar";
import { CalendarPreviewProps } from "../typings/CalendarProps";
import { CustomToolbar } from "./components/Toolbar";
import "react-big-calendar/lib/css/react-big-calendar.css";
import { constructWrapperStyle, WrapperStyleProps } from "./utils/style-utils";
import { eventPropGetter } from "./utils/calendar-utils";

import "react-big-calendar/lib/css/react-big-calendar.css";
import "./ui/Calendar.scss";

const localizer = dateFnsLocalizer({
format: dateFns.format,
parse: dateFns.parse,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ exports[`Calendar renders correctly with basic props 1`] = `
class="calendar-toolbar"
>
<div
class="align-left btn-group"
class="btn-group"
>
<button
class="btn btn-default"
Expand Down Expand Up @@ -44,7 +44,7 @@ exports[`Calendar renders correctly with basic props 1`] = `
</button>
</div>
<div
class="align-center btn-group"
class="btn-group"
>
<span
class="calendar-label"
Expand All @@ -53,7 +53,7 @@ exports[`Calendar renders correctly with basic props 1`] = `
</span>
</div>
<div
class="align-right btn-group"
class="btn-group"
>
<button
class="btn btn-default"
Expand Down Expand Up @@ -767,7 +767,7 @@ exports[`Calendar renders correctly with basic props 1`] = `
class="calendar-toolbar"
>
<div
class="align-left btn-group"
class="btn-group"
>
<button
class="btn btn-default"
Expand Down Expand Up @@ -795,7 +795,7 @@ exports[`Calendar renders correctly with basic props 1`] = `
</button>
</div>
<div
class="align-center btn-group"
class="btn-group"
>
<span
class="calendar-label"
Expand All @@ -804,7 +804,7 @@ exports[`Calendar renders correctly with basic props 1`] = `
</span>
</div>
<div
class="align-right btn-group"
class="btn-group"
>
<button
class="btn btn-default"
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "react-big-calendar/lib/css/react-big-calendar.css";
export function CustomToolbar({ label, localizer, onNavigate, onView, view, views }: ToolbarProps): ReactElement {
return (
<div className="calendar-toolbar">
<div className="align-left btn-group">
<div className="btn-group">
<Button className="btn btn-default" onClick={() => onNavigate(Navigate.PREVIOUS)}>
<IconInternal icon={{ type: "glyph", iconClass: "glyphicon-backward" }} />
</Button>
Expand All @@ -20,11 +20,11 @@ export function CustomToolbar({ label, localizer, onNavigate, onView, view, view
</Button>
</div>

<div className="align-center btn-group">
<div className="btn-group">
<span className="calendar-label">{label}</span>
</div>

<div className="align-right btn-group">
<div className="btn-group">
{Array.isArray(views) &&
views.map(name => {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as dateFns from "date-fns";
import { Calendar, dateFnsLocalizer, ViewsProps } from "react-big-calendar";
import withDragAndDrop from "react-big-calendar/lib/addons/dragAndDrop";
import { Calendar, CalendarProps, dateFnsLocalizer, ViewsProps } from "react-big-calendar";
import withDragAndDrop, { withDragAndDropProps } from "react-big-calendar/lib/addons/dragAndDrop";
import { CalendarContainerProps } from "../../typings/CalendarProps";
import { CustomToolbar } from "../components/Toolbar";

Expand All @@ -25,9 +25,9 @@ const localizer = dateFnsLocalizer({
locales: {}
});

export const DnDCalendar = withDragAndDrop(Calendar);
export const DnDCalendar = withDragAndDrop(Calendar<CalEvent, object>);

function getViewRange(view: string, date: Date) {
function getViewRange(view: string, date: Date): { start: Date; end: Date } {
switch (view) {
case "month":
return { start: dateFns.startOfMonth(date), end: dateFns.endOfMonth(date) };
Expand All @@ -44,13 +44,25 @@ function getViewRange(view: string, date: Date) {
}
}

export function eventPropGetter(event: CalEvent) {
type EventPropGetterReturnType = {
style:
| {
backgroundColor: string;
}
| undefined;
};

export function eventPropGetter(event: CalEvent): EventPropGetterReturnType {
return {
style: event.color ? { backgroundColor: event.color } : undefined
};
}

export function extractCalendarProps(props: CalendarContainerProps) {
interface DragAndDropCalendarProps<TEvent extends object = Event, TResource extends object = object>
extends CalendarProps<TEvent, TResource>,
withDragAndDropProps<TEvent, TResource> {}

export function extractCalendarProps(props: CalendarContainerProps): DragAndDropCalendarProps<CalEvent, object> {
const items = props.databaseDataSource?.items ?? [];
const events: CalEvent[] = items.map(item => {
const title =
Expand All @@ -69,7 +81,7 @@ export function extractCalendarProps(props: CalendarContainerProps) {
const viewsOption: ViewsProps<CalEvent, object> =
props.view === "standard" ? ["day", "week", "month"] : ["month", "week", "work_week", "day", "agenda"];

const handleSelectEvent = (event: CalEvent) => {
const handleSelectEvent = (event: CalEvent): void => {
if (props.onClickEvent?.canExecute) {
props.onClickEvent.execute({
startDate: event.start,
Expand All @@ -80,7 +92,7 @@ export function extractCalendarProps(props: CalendarContainerProps) {
}
};

const handleSelectSlot = (slotInfo: { start: Date; end: Date; action: string }) => {
const handleSelectSlot = (slotInfo: { start: Date; end: Date; action: string }): void => {
if (props.enableCreate && props.onCreateEvent?.canExecute) {
props.onCreateEvent.execute({
startDate: slotInfo.start,
Expand All @@ -90,7 +102,7 @@ export function extractCalendarProps(props: CalendarContainerProps) {
}
};

const handleEventDropOrResize = ({ event, start, end }: { event: CalEvent; start: Date; end: Date }) => {
const handleEventDropOrResize = ({ event, start, end }: { event: CalEvent; start: Date; end: Date }): void => {
if (props.onChange?.canExecute) {
props.onChange.execute({
oldStart: event.start,
Expand All @@ -101,7 +113,7 @@ export function extractCalendarProps(props: CalendarContainerProps) {
}
};

const handleRangeChange = (date: Date, view: string) => {
const handleRangeChange = (date: Date, view: string): void => {
if (props.onRangeChange?.canExecute) {
const { start, end } = getViewRange(view, date);
props.onRangeChange.execute({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function getPreview(values: EventsPreviewProps, isDarkMode: boolean): Str
return rowLayout({ columnSize: "grow", borders: true, backgroundColor: palette.background.containerFill })(
container()(),
rowLayout({ grow: 2, padding: 8 })(
svgImage(doc, 15, 15),
svgImage({ width: 15, height: 15 })(doc),
text({ fontColor: palette.text.primary, grow: 10 })(getCaption(eventsCount))
),
container()()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export function getPreview(
return container()(
rowLayout({ columnSize: "grow" })(
container({ grow: 1 })(
svgImage(decodeURIComponent(CheckBoxIndeterminateSVG.replace("data:image/svg+xml,", "")), 24, 24)
svgImage({ width: 24, height: 24 })(
decodeURIComponent(CheckBoxIndeterminateSVG.replace("data:image/svg+xml,", ""))
)
),
container({ grow: 100, padding: 3 })(text({ fontSize: 10 })(values.checkboxCaption))
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,28 @@ export interface ImageProps extends BaseStylingProps {
height?: number; // sets a fixed maximum height
}

export function svgImage(svgTextData: string, width?: number, height?: number): ImageProps {
return {
type: "Image",
document: svgTextData,
width,
height
interface ImageStyleProps extends BaseStylingProps {
width?: number;
height?: number;
}

export function svgImage(style: ImageStyleProps): (document: string) => ImageProps {
return (document: string) => {
return {
type: "Image",
document,
...style
};
};
}

export function image(base64Data: string, width?: number, height?: number): ImageProps {
return {
type: "Image",
data: base64Data,
width,
height
export function image(style: ImageStyleProps): (data: string) => ImageProps {
return (data: string) => {
return {
type: "Image",
data,
...style
};
};
}

Expand Down
Loading