Feature: Calendar widget 🗓 (#1368)

* Insert required boilerplate code for Calendar widget

* Display basic calendar

* Display events on calendar widget

* Pass JS date object as calendar default event date

* Add resource scheduling to Calendar widget

* Add icon for Calendar widget

* Allow configuration of views and default view for calendar

* Add onEventSelect event to Calendar widget

* Accept date as string for Calendar

* Option to disable/enable toolbar in Calendar

* Add default date to Calendar

* Add support for setting color of calendar events

* Set calendar cell size to 50px

* Allow spacious and compact cell sizes for Calendar

* Add support for "select slots" event for calendar

* Add support for custom event tooltip for Calendar

* Add support to not highlight today and now in Calendar

* Add visible border for Calendar events

* Set 14px font size for calendar toolbar

* Add dark mode styles for calendar

* Make calendar view mode controllable with logic

* Add documentation for calendar widget

* Add additional documentation for calendar events

* Expose default view instead of view for calendar

* Add documentation for changes in calendar

* Style updates to calendar

* Increase padding for calendar events
This commit is contained in:
Sherfin Shamsudeen 2021-11-04 14:23:50 +05:30 committed by GitHub
parent a6f99f6fba
commit 8bbbbfc869
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 584 additions and 1 deletions

View file

@ -0,0 +1,109 @@
---
sidebar_position: 22
---
# Calendar
Calendar widget comes with the following features:
- Day, month and week level views
- Events
- Resource scheduling
<img class="screenshot-full" src="/img/widgets/calendar/calendar1.png" alt="ToolJet - Widget Reference - Calendar" height="600"/>
### Properties
#### Date format
Determines the format in which any date passed to the calendar via any of the properties will be parsed.
It also determines the format in which any date made available by the calendar via exposed variables will be displayed.
It uses the date format conventions of [moment.js](https://momentjs.com/).
#### Default date
Determines the date on which the calendar's view will be centered on.
If the calendar is on `month` view, it will show the month on which this date exists.
If the calendar is on `week` view, it will show the week on which this date exists.
This property needs to be formatted using the `Date format` property which is configurable on the inspector.
#### Events
`Events` property should contain an array of objects, each of which describes the events that the calendar needs to display.
Assuming that you set the date format to `MM-DD-YYYY HH:mm:ss A Z`, setting the `Events` property to the following code snippet will display an event titled `Sample Event` at the first hour of this day, as displayed in the image of calendar at the beginning of this page.
```javascript
{{[
{
title: 'Sample event',
start: `${moment().startOf('day').format('MM-DD-YYYY HH:mm:ss A Z')}`,
end: `${moment().endOf('day').format('MM-DD-YYYY HH:mm:ss A Z')}`,
allDay: false,
tooltip: 'Sample event',
color: 'lightgreen',
}
]}}
```
##### Event object properties
| Name | Description |
|------|-------------|
| title | Title of the event |
| start | The date(and time) on which this event begins. Needs to be formatted in the `Date format` you've supplied |
| end | The date(and time) on which this event ends. Needs to be formatted in the `Date format` you've supplied |
| allDay | Optional. Qualifies the event as an 'All day event', which will pin it to date headers on `day` and `week` level views |
| tooltip | Tooltip which will be display when the user hovers over the event |
| color | Background color of the event, any css supported color name or hex code can be used |
| textOrientation | Optional. If it is set to `vertical`, the title of the event will be oriented vertically. |
| resourceId | Applicable only if you're using resource scheduling. This is the id of the resource to which this event correspond to. |
You may supply any other additional property to the event(s). These additional properties will available to you when the calendar widget
exposes any of the events via its exposed variables.
#### Resources
Specifying resources will make the calendar categorize `week` view and `day` view for each of the resources specified.
For example, to categorize week/day view into for three rooms, we specify `resources` this way:
```javascript
{{
[
{resourceId: 1, title: 'Room A'},
{resourceId: 2, title: 'Room B'},
{resourceId: 3, title: 'Room C'},
]
}}
```
If we specify the `resourceId` of any of the events as `1`, then that event will be assigned to `Room A`, generating the following calendar, assuming that we've set the view to `day` and are viewing the day on which this event exists.
<img class="screenshot-full" src="/img/widgets/calendar/calendar-resource.png" alt="ToolJet - Widget Reference - Calendar Resources" height="600"/>
#### Default view
Determines whether the calendar would display a `day`, a `week` or a `month`.
Setting this property to anything other than these values will make the calendar default to `month` view.
#### Show toolbar
Determines whether the calendar toolbar should be displayed or not.
#### Show view switcher
Determinues whether the calendar's buttons that allow user to switch between `month`, `week` and `day` level views will be displayed.
### Styles
#### Cell size in views classified by resource
When `resources` are specified, the calendar could take up quite a lot of horizontal space, making the horizontal scroll bar of calendar having to be relied upon all the time.
If we set this property to `compact`, the cell sizes will be smaller in `week` and `day` views.
### Events
#### On Event selected
This event is fired when the user clicks on a calendar event.
Last selected event is exposed as `selectedEvent`.
#### on Slot selected
This event is fired when the user either clicks on an calendar slot(empty cell or empty space of a cell with event) or when they click and drag to select multiple slots.
Last selected slot(s) are exposed as `selectedSlots`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 470 470" style="enable-background:new 0 0 470 470;" xml:space="preserve">
<g>
<path d="M462.5,425H7.5c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h455c4.143,0,7.5-3.358,7.5-7.5S466.643,425,462.5,425z"/>
<path d="M462.5,455H7.5c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h455c4.143,0,7.5-3.358,7.5-7.5S466.643,455,462.5,455z"/>
<path d="M462.5,30h-25v-7.5C437.5,10.093,427.406,0,415,0s-22.5,10.093-22.5,22.5V30h-75v-7.5C317.5,10.093,307.406,0,295,0
s-22.5,10.093-22.5,22.5V30h-75v-7.5C197.5,10.093,187.407,0,175,0s-22.5,10.093-22.5,22.5V30h-75v-7.5C77.5,10.093,67.407,0,55,0
S32.5,10.093,32.5,22.5V30h-25C3.358,30,0,33.358,0,37.5v365c0,4.142,3.358,7.5,7.5,7.5h455c4.143,0,7.5-3.358,7.5-7.5v-365
C470,33.358,466.643,30,462.5,30z M407.5,22.5c0-4.136,3.364-7.5,7.5-7.5s7.5,3.364,7.5,7.5v30c0,4.136-3.364,7.5-7.5,7.5
s-7.5-3.364-7.5-7.5V22.5z M287.5,22.5c0-4.136,3.364-7.5,7.5-7.5s7.5,3.364,7.5,7.5v30c0,4.136-3.364,7.5-7.5,7.5
s-7.5-3.364-7.5-7.5V22.5z M167.5,22.5c0-4.136,3.364-7.5,7.5-7.5s7.5,3.364,7.5,7.5v30c0,4.136-3.364,7.5-7.5,7.5
s-7.5-3.364-7.5-7.5V22.5z M47.5,22.5c0-4.136,3.364-7.5,7.5-7.5s7.5,3.364,7.5,7.5v30c0,4.136-3.364,7.5-7.5,7.5
s-7.5-3.364-7.5-7.5V22.5z M32.5,45v7.5C32.5,64.907,42.593,75,55,75s22.5-10.093,22.5-22.5V45h75v7.5
c0,12.407,10.093,22.5,22.5,22.5s22.5-10.093,22.5-22.5V45h75v7.5c0,12.407,10.094,22.5,22.5,22.5s22.5-10.093,22.5-22.5V45h75v7.5
c0,12.407,10.094,22.5,22.5,22.5s22.5-10.093,22.5-22.5V45H455v77.3H15V45H32.5z M15,395V137.3h440V395H15z"/>
<path d="M412,226.8h-30c-4.143,0-7.5,3.358-7.5,7.5s3.357,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S416.143,226.8,412,226.8z"/>
<path d="M331,226.8h-30c-4.143,0-7.5,3.358-7.5,7.5s3.357,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S335.143,226.8,331,226.8z"/>
<path d="M250,226.8h-30c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S254.143,226.8,250,226.8z"/>
<path d="M169,226.8h-30c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.142,0,7.5-3.358,7.5-7.5S173.142,226.8,169,226.8z"/>
<path d="M88,226.8H58c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.142,0,7.5-3.358,7.5-7.5S92.142,226.8,88,226.8z"/>
<path d="M331,280.8h-30c-4.143,0-7.5,3.358-7.5,7.5s3.357,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S335.143,280.8,331,280.8z"/>
<path d="M250,280.8h-30c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S254.143,280.8,250,280.8z"/>
<path d="M169,280.8h-30c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.142,0,7.5-3.358,7.5-7.5S173.142,280.8,169,280.8z"/>
<path d="M88,280.8H58c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.142,0,7.5-3.358,7.5-7.5S92.142,280.8,88,280.8z"/>
<path d="M331,334.8h-30c-4.143,0-7.5,3.358-7.5,7.5s3.357,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S335.143,334.8,331,334.8z"/>
<path d="M412,280.8h-30c-4.143,0-7.5,3.358-7.5,7.5s3.357,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S416.143,280.8,412,280.8z"/>
<path d="M412,334.8h-30c-4.143,0-7.5,3.358-7.5,7.5s3.357,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S416.143,334.8,412,334.8z"/>
<path d="M250,334.8h-30c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S254.143,334.8,250,334.8z"/>
<path d="M169,334.8h-30c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.142,0,7.5-3.358,7.5-7.5S173.142,334.8,169,334.8z"/>
<path d="M88,334.8H58c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.142,0,7.5-3.358,7.5-7.5S92.142,334.8,88,334.8z"/>
<path d="M412,172.8h-30c-4.143,0-7.5,3.358-7.5,7.5s3.357,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S416.143,172.8,412,172.8z"/>
<path d="M331,172.8h-30c-4.143,0-7.5,3.358-7.5,7.5s3.357,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S335.143,172.8,331,172.8z"/>
<path d="M250,172.8h-30c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.143,0,7.5-3.358,7.5-7.5S254.143,172.8,250,172.8z"/>
<path d="M169,172.8h-30c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.142,0,7.5-3.358,7.5-7.5S173.142,172.8,169,172.8z"/>
<path d="M88,172.8H58c-4.142,0-7.5,3.358-7.5,7.5s3.358,7.5,7.5,7.5h30c4.142,0,7.5-3.358,7.5-7.5S92.142,172.8,88,172.8z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -41,6 +41,7 @@
"plotly.js-basic-dist-min": "^1.58.4",
"query-string": "^6.13.6",
"react": "^16.14.0",
"react-big-calendar": "^0.38.0",
"react-bootstrap": "^1.5.2",
"react-color": "^2.19.3",
"react-copy-to-clipboard": "^5.0.3",
@ -7594,6 +7595,11 @@
"webidl-conversions": "^4.0.2"
}
},
"node_modules/date-arithmetic": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz",
"integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg=="
},
"node_modules/date-fns": {
"version": "1.30.1",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
@ -14233,6 +14239,11 @@
"node": ">= 0.6"
}
},
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
},
"node_modules/memory-fs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@ -17404,6 +17415,47 @@
"pure-color": "^1.2.0"
}
},
"node_modules/react-big-calendar": {
"version": "0.38.0",
"resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-0.38.0.tgz",
"integrity": "sha512-eoVkt9gTo+f1HBL09+o7dYLxp6QxHv52fcn50P5PfaWp3S98uGLQqoqsvghT85koMKvGfDVa5V0+J7yHcaF07Q==",
"dependencies": {
"@babel/runtime": "^7.1.5",
"clsx": "^1.0.4",
"date-arithmetic": "^4.1.0",
"dom-helpers": "^5.1.0",
"invariant": "^2.2.4",
"lodash": "^4.17.11",
"lodash-es": "^4.17.11",
"memoize-one": "^5.1.1",
"prop-types": "^15.7.2",
"react-overlays": "^4.1.1",
"uncontrollable": "^7.0.0"
},
"peerDependencies": {
"react": "^16.6.1 || ^17",
"react-dom": "^16.6.1 || ^17"
}
},
"node_modules/react-big-calendar/node_modules/react-overlays": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-4.1.1.tgz",
"integrity": "sha512-WtJifh081e6M24KnvTQoNjQEpz7HoLxqt8TwZM7LOYIkYJ8i/Ly1Xi7RVte87ZVnmqQ4PFaFiNHZhSINPSpdBQ==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@popperjs/core": "^2.5.3",
"@restart/hooks": "^0.3.25",
"@types/warning": "^3.0.0",
"dom-helpers": "^5.2.0",
"prop-types": "^15.7.2",
"uncontrollable": "^7.0.0",
"warning": "^4.0.3"
},
"peerDependencies": {
"react": ">=16.3.0",
"react-dom": ">=16.3.0"
}
},
"node_modules/react-bootstrap": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.5.2.tgz",
@ -30304,6 +30356,11 @@
}
}
},
"date-arithmetic": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz",
"integrity": "sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg=="
},
"date-fns": {
"version": "1.30.1",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
@ -35470,6 +35527,11 @@
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
},
"memory-fs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@ -38058,6 +38120,41 @@
"pure-color": "^1.2.0"
}
},
"react-big-calendar": {
"version": "0.38.0",
"resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-0.38.0.tgz",
"integrity": "sha512-eoVkt9gTo+f1HBL09+o7dYLxp6QxHv52fcn50P5PfaWp3S98uGLQqoqsvghT85koMKvGfDVa5V0+J7yHcaF07Q==",
"requires": {
"@babel/runtime": "^7.1.5",
"clsx": "^1.0.4",
"date-arithmetic": "^4.1.0",
"dom-helpers": "^5.1.0",
"invariant": "^2.2.4",
"lodash": "^4.17.11",
"lodash-es": "^4.17.11",
"memoize-one": "^5.1.1",
"prop-types": "^15.7.2",
"react-overlays": "^4.1.1",
"uncontrollable": "^7.0.0"
},
"dependencies": {
"react-overlays": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-4.1.1.tgz",
"integrity": "sha512-WtJifh081e6M24KnvTQoNjQEpz7HoLxqt8TwZM7LOYIkYJ8i/Ly1Xi7RVte87ZVnmqQ4PFaFiNHZhSINPSpdBQ==",
"requires": {
"@babel/runtime": "^7.12.1",
"@popperjs/core": "^2.5.3",
"@restart/hooks": "^0.3.25",
"@types/warning": "^3.0.0",
"dom-helpers": "^5.2.0",
"prop-types": "^15.7.2",
"uncontrollable": "^7.0.0",
"warning": "^4.0.3"
}
}
}
},
"react-bootstrap": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.5.2.tgz",

View file

@ -36,6 +36,7 @@
"plotly.js-basic-dist-min": "^1.58.4",
"query-string": "^6.13.6",
"react": "^16.14.0",
"react-big-calendar": "^0.38.0",
"react-bootstrap": "^1.5.2",
"react-color": "^2.19.3",
"react-copy-to-clipboard": "^5.0.3",

View file

@ -23,6 +23,7 @@ import { StarRating } from './Components/StarRating';
import { Divider } from './Components/Divider';
import { FilePicker } from './Components/FilePicker';
import { PasswordInput } from './Components/PasswordInput';
import { Calendar } from './Components/Calendar';
import { renderTooltip } from '../_helpers/appUtils';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import '@/_styles/custom.scss';
@ -54,6 +55,7 @@ const AllComponents = {
Divider,
FilePicker,
PasswordInput,
Calendar,
};
export const Box = function Box({

View file

@ -0,0 +1,84 @@
import React from 'react';
import { Calendar as ReactCalendar, momentLocalizer } from 'react-big-calendar';
import moment from 'moment';
import 'react-big-calendar/lib/css/react-big-calendar.css';
const localizer = momentLocalizer(moment);
const prepareEvent = (event, dateFormat) => ({
...event,
start: moment(event.start, dateFormat).toDate(),
end: moment(event.end, dateFormat).toDate(),
});
const parseDate = (date, dateFormat) => moment(date, dateFormat).toDate();
const allowedCalendarViews = ['month', 'week', 'day'];
export const Calendar = function ({ height, width, properties, styles, fireEvent, darkMode }) {
const style = { height, width };
const resourcesParam = properties.resources?.length === 0 ? {} : { resources: properties.resources };
const events = properties.events ? properties.events.map((event) => prepareEvent(event, properties.dateFormat)) : [];
const defaultDate = parseDate(properties.defaultDate, properties.dateFormat);
const eventPropGetter = (event) => {
const backgroundColor = event.color;
const textStyle =
event.textOrientation === 'vertical' ? { writingMode: 'vertical-rl', textOrientation: 'mixed' } : {};
const style = { backgroundColor, ...textStyle, padding: 3, paddingLeft: 5, paddingRight: 5 };
return { style };
};
const slotSelectHandler = (calendarSlots) => {
const { slots, start, end, resourceId, action } = calendarSlots;
const formattedSlots = slots.map((slot) => moment(slot).format(properties.dateFormat));
const formattedStart = moment(start).format(properties.dateFormat);
const formattedEnd = moment(end).format(properties.dateFormat);
const selectedSlots = {
slots: formattedSlots,
start: formattedStart,
end: formattedEnd,
resourceId,
action,
};
fireEvent('onCalendarSlotSelect', { selectedSlots });
};
const defaultView = allowedCalendarViews.includes(properties.defaultView)
? properties.defaultView
: allowedCalendarViews[0];
return (
<div>
<ReactCalendar
className={`calendar-widget
${darkMode ? 'dark-mode' : ''}
${styles.cellSizeInViewsClassifiedByResource}
${properties.highlightToday ? '' : 'dont-highlight-today'}
${properties.displayViewSwitcher ? '' : 'hide-view-switcher'}`}
localizer={localizer}
defaultDate={defaultDate}
events={events}
startAccessor="start"
endAccessor="end"
style={style}
views={allowedCalendarViews}
defaultView={defaultView}
{...resourcesParam}
resourceIdAccessor="resourceId"
resourceTitleAccessor="title"
onSelectEvent={(calendarEvent) => fireEvent('onCalendarEventSelect', { calendarEvent })}
selectable={true}
onSelectSlot={slotSelectHandler}
toolbar={properties.displayToolbar}
eventPropGetter={eventPropGetter}
tooltipAccessor="tooltip"
popup={true}
/>
</div>
);
};

View file

@ -1003,7 +1003,7 @@ export const componentTypes = [
canSearch: {
value: `{{true}}`,
},
addNewMarkers : {value:`{{true}}`},
addNewMarkers: { value: `{{true}}` },
},
events: [],
styles: {
@ -1189,4 +1189,85 @@ export const componentTypes = [
},
},
},
{
name: 'Calendar',
displayName: 'Calendar',
description: 'Calendar',
component: 'Calendar',
defaultSize: {
width: 700,
height: 600,
},
others: {
showOnDesktop: { type: 'toggle', displayName: 'Show on desktop' },
showOnMobile: { type: 'toggle', displayName: 'Show on mobile' },
},
properties: {
dateFormat: { type: 'code', displayName: 'Date format' },
defaultDate: { type: 'code', displayName: 'Default date' },
events: { type: 'code', displayName: 'Events' },
resources: { type: 'code', displayName: 'Resources' },
defaultView: { type: 'code', displayName: 'Default view' },
displayToolbar: { type: 'toggle', displayName: 'Show toolbar' },
displayViewSwitcher: { type: 'toggle', displayName: 'Show view switcher' },
highlightToday: { type: 'toggle', displayName: 'Highlight today' },
},
events: {
onCalendarEventSelect: { displayName: 'On Event Select' },
onCalendarSlotSelect: { displayName: 'On Slot Select' },
},
styles: {
visibility: { type: 'code', displayName: 'Visibility' },
cellSizeInViewsClassifiedByResource: {
type: 'select',
displayName: 'Cell size in views classified by resource',
options: [
{ name: 'Compact', value: 'compact' },
{ name: 'Spacious', value: 'spacious' },
],
},
},
exposedVariables: {
selectedEvent: {},
selectedSlots: {},
},
definition: {
others: {
showOnDesktop: { value: true },
showOnMobile: { value: false },
},
properties: {
dateFormat: {
value: 'MM-DD-YYYY HH:mm:ss A Z',
},
defaultDate: {
value: '{{moment().format("MM-DD-YYYY HH:mm:ss A Z")}}',
},
events: {
value:
"{{[\n\t\t{\n\t\t\t title: 'Sample event',\n\t\t\t start: `${moment().startOf('day').format('MM-DD-YYYY HH:mm:ss A Z')}`,\n\t\t\t end: `${moment().endOf('day').format('MM-DD-YYYY HH:mm:ss A Z')}`,\n\t\t\t allDay: false,\n\t\t\t color: '#4D72DA'\n\t\t}\n]}}",
},
resources: {
value: '{{[]}}',
},
defaultView: {
value: "{{'month'}}",
},
displayToolbar: {
value: true,
},
displayViewSwitcher: {
value: true,
},
highlightToday: {
value: true,
},
},
events: [],
styles: {
visibility: { value: '{{true}}' },
cellSizeInViewsClassifiedByResource: { value: 'spacious' },
},
},
},
];

View file

@ -224,6 +224,48 @@ export async function onEvent(_ref, eventName, options, mode = 'edit') {
);
}
if (eventName === 'onCalendarEventSelect') {
const { component, calendarEvent } = options;
_self.setState(
{
currentState: {
..._self.state.currentState,
components: {
..._self.state.currentState.components,
[component.name]: {
..._self.state.currentState.components[component.name],
selectedEvent: { ...calendarEvent },
},
},
},
},
() => {
executeActionsForEventId(_ref, 'onCalendarEventSelect', component, mode);
}
);
}
if (eventName === 'onCalendarSlotSelect') {
const { component, selectedSlots } = options;
_self.setState(
{
currentState: {
..._self.state.currentState,
components: {
..._self.state.currentState.components,
[component.name]: {
..._self.state.currentState.components[component.name],
selectedSlots,
},
},
},
},
() => {
executeActionsForEventId(_ref, 'onCalendarSlotSelect', component, mode);
}
);
}
if (eventName === 'onTableActionButtonClicked') {
const { component, data, action, rowId } = options;
_self.setState(

View file

@ -2391,6 +2391,104 @@ input[type='text'] {
overflow-y: scroll;
}
.calendar-widget.compact {
.rbc-time-view-resources .rbc-time-header-content {
min-width: auto;
}
.rbc-time-view-resources .rbc-day-slot {
min-width: 50px;
}
.rbc-time-view-resources .rbc-header,
.rbc-time-view-resources .rbc-day-bg {
width: 50px;
}
}
.calendar-widget.dont-highlight-today {
.rbc-today {
background-color: inherit;
}
.rbc-current-time-indicator {
display: none;
}
}
.calendar-widget {
padding: 10px;
background-color: white;
.rbc-day-slot .rbc-event, .rbc-day-slot .rbc-background-event {
border-left: 3px solid #26598533;
}
.rbc-toolbar {
font-size: 14px;
}
.rbc-event {
.rbc-event-label {
display: none;
}
}
.rbc-off-range-bg {
background-color: #f4f6fa;
}
.rbc-toolbar {
.rbc-btn-group {
button {
box-shadow: none;
border-radius: 0;
border-width: 1px;
}
}
}
}
.calendar-widget.hide-view-switcher {
.rbc-toolbar {
.rbc-btn-group:nth-of-type(3) {
display: none;
}
}
}
.calendar-widget.dark-mode {
background-color: #1d2a39;
.rbc-toolbar {
button {
color: white;
}
button:hover, button.rbc-active {
color: black;
}
}
.rbc-off-range-bg {
background-color: #2b394b;
}
.rbc-selected-cell {
background-color: #22242d;
}
.rbc-today {
background-color: #5a7ca8;
}
}
.calendar-widget.dark-mode.dont-highlight-today {
.rbc-today {
background-color: inherit;
}
}
.navbar .navbar-nav {
min-height: 2rem;
}