# Pip install full-calendar-component 📅

**URL:** <https://community.plotly.com/t/pip-install-full-calendar-component/83460>\
**Category:** Dash Python\
**Tags:** show-and-tell, community-components\
**Created:** [March 31, 2024, 8:26am UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460 "2024-03-31T08:26:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [March 31, 2024, 8:26am UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/1 "2024-03-31T08:26:31Z")

</div>

![20242-ezgif.com-optimize (1)](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/3/8/38779798f7d1907e3c75c4cec8ce5754b4893fd2.gif)  
[![Downloads](https://static.pepy.tech/badge/full-calendar-component)](https://pepy.tech/project/full-calendar-component)  
This is an actual published version of what was started based on my prior post: [Dash-full-calendar component](https://community.plotly.com/t/dash-full-calendar-component/82293)

The goal was to build out a full feature component to provide [https://fullcalendar.io/](https://fullcalendar.io/) for dash.

You can use this component with `pip install full-calendar-component==0.0.3` its was built on top of the the hard work and backs of `dash-mantine-components==0.13.0a2`, `dash-quill` and obviously `dash`.

So you’ll also need to `pip install dash dash-mantine-components==0.13.0a2 dash-quill` to get the most out of this package.

You can also change the styling of the calendar with adding this code into your `style.css` file:

```auto
/* the main calendar container theme */

.fc { /* the main calendar container */
    background-color: #ffffff;
    color: #ecf0f1;
}

.fc-daygrid-day { /* the individual day cells */
    background-color: #1d2731;
}

.fc-event { /* the events */
    background-color: #3498db;
    border-color: #3498db;
}

```

These are some of the features and capabilities this full-calendar-component has access to:  
_props_: `id, initialView, headerToolbar, initialDate, selectable, editable, events, views, multiMonthMaxColumns, resources, navLinks, businessHours, nowIndicator`

This is a basic example of how to get this project up and running:

```auto
import full_calendar_component as fcc
from dash import *
import dash_mantine_components as dmc
from dash.exceptions import PreventUpdate
from datetime import datetime, date, timedelta
import dash_quill

app = Dash( __name__ , prevent_initial_callbacks=True)

quill_mods = [
    [{"header": "1"}, {"header": "2"}, {"font": []}],
    [{"size": []}],
    ["bold", "italic", "underline", "strike", "blockquote"],
    [{"list": "ordered"}, {"list": "bullet"}, {"indent": "-1"}, {"indent": "+1"}],
    ["link", "image"],
]

# Get today's date
today = datetime.now()

# Format the date
formatted_date = today.strftime("%Y-%m-%d")

app.layout = html.Div(
    [
        fcc.FullCalendarComponent(
            id="calendar", # Unique ID for the component
            initialView="listWeek", # dayGridMonth, timeGridWeek, timeGridDay, listWeek,
            # dayGridWeek, dayGridYear, multiMonthYear, resourceTimeline, resourceTimeGridDay, resourceTimeLineWeek
            headerToolbar={
                "left": "prev,next today",
                "center": "",
                "right": "listWeek,timeGridDay,timeGridWeek,dayGridMonth",
            }, # Calendar header
            initialDate=f"{formatted_date}", # Start date for calendar
            editable=True, # Allow events to be edited
            selectable=True, # Allow dates to be selected
            events=[],
            nowIndicator=True, # Show current time indicator
            navLinks=True, # Allow navigation to other dates
        ),
        dmc.MantineProvider(
            theme={"colorScheme": "dark"},
            children=[
                dmc.Modal(
                    id="modal",
                    size="xl",
                    title="Event Details",
                    zIndex=10000,
                    children=[
                        html.Div(id="modal_event_display_context"),
                        dmc.Space(h=20),
                        dmc.Group(
                            [
                                dmc.Button(
                                    "Close",
                                    color="red",
                                    variant="outline",
                                    id="modal-close-button",
                                ),
                            ],
                            position="right",
                        ),
                    ],
                )
            ],
        ),
        dmc.MantineProvider(
            theme={"colorScheme": "dark"},
            children=[
                dmc.Modal(
                    id="add_modal",
                    title="New Event",
                    size="xl",
                    children=[
                        dmc.Grid(
                            children=[
                                dmc.Col(
                                    html.Div(
                                        dmc.DatePicker(
                                            id="start_date",
                                            label="Start Date",
                                            value=datetime.now().date(),
                                            styles={"width": "100%"},
                                            disabled=True,
                                        ),
                                        style={"width": "100%"},
                                    ),
                                    span=6,
                                ),
                                dmc.Col(
                                    html.Div(
                                        dmc.TimeInput(
                                            label="Start Time",
                                            withSeconds=True,
                                            value=datetime.now(),
                                            format="12",
                                            id="start_time",
                                        ),
                                        style={"width": "100%"},
                                    ),
                                    span=6,
                                ),
                            ],
                            gutter="xl",
                        ),
                        dmc.Grid(
                            children=[
                                dmc.Col(
                                    html.Div(
                                        dmc.DatePicker(
                                            id="end_date",
                                            label="End Date",
                                            value=datetime.now().date(),
                                            styles={"width": "100%"},
                                        ),
                                        style={"width": "100%"},
                                    ),
                                    span=6,
                                ),
                                dmc.Col(
                                    html.Div(
                                        dmc.TimeInput(
                                            label="End Time",
                                            withSeconds=True,
                                            value=datetime.now(),
                                            format="12",
                                            id="end_time",
                                        ),
                                        style={"width": "100%"},
                                    ),
                                    span=6,
                                ),
                            ],
                            gutter="xl",
                        ),
                        dmc.Grid(
                            children=[
                                dmc.Col(
                                    span=6,
                                    children=[
                                        dmc.TextInput(
                                            label="Event Title:",
                                            style={"width": "100%"},
                                            id="event_name_input",
                                            required=True,
                                        )
                                    ],
                                ),
                                dmc.Col(
                                    span=6,
                                    children=[
                                        dmc.Select(
                                            label="Select event color",
                                            placeholder="Select one",
                                            id="event_color_select",
                                            value="ng",
                                            data=[
                                                {
                                                    "value": "bg-gradient-primary",
                                                    "label": "bg-gradient-primary",
                                                },
                                                {
                                                    "value": "bg-gradient-secondary",
                                                    "label": "bg-gradient-secondary",
                                                },
                                                {
                                                    "value": "bg-gradient-success",
                                                    "label": "bg-gradient-success",
                                                },
                                                {
                                                    "value": "bg-gradient-info",
                                                    "label": "bg-gradient-info",
                                                },
                                                {
                                                    "value": "bg-gradient-warning",
                                                    "label": "bg-gradient-warning",
                                                },
                                                {
                                                    "value": "bg-gradient-danger",
                                                    "label": "bg-gradient-danger",
                                                },
                                                {
                                                    "value": "bg-gradient-light",
                                                    "label": "bg-gradient-light",
                                                },
                                                {
                                                    "value": "bg-gradient-dark",
                                                    "label": "bg-gradient-dark",
                                                },
                                                {
                                                    "value": "bg-gradient-white",
                                                    "label": "bg-gradient-white",
                                                },
                                            ],
                                            style={"width": "100%", "marginBottom": 10},
                                            required=True,
                                        )
                                    ],
                                ),
                            ]
                        ),
                        dash_quill.Quill(
                            id="rich_text_input",
                            modules={
                                "toolbar": quill_mods,
                                "clipboard": {
                                    "matchVisual": False,
                                },
                            },
                        ),
                        dmc.Accordion(
                            children=[
                                dmc.AccordionItem(
                                    [
                                        dmc.AccordionControl("Raw HTML"),
                                        dmc.AccordionPanel(
                                            html.Div(
                                                id="rich_text_output",
                                                style={
                                                    "height": "300px",
                                                    "overflowY": "scroll",
                                                },
                                            )
                                        ),
                                    ],
                                    value="raw_html",
                                ),
                            ],
                        ),
                        dmc.Space(h=20),
                        dmc.Group(
                            [
                                dmc.Button(
                                    "Submit",
                                    id="modal_submit_new_event_button",
                                    color="green",
                                ),
                                dmc.Button(
                                    "Close",
                                    color="red",
                                    variant="outline",
                                    id="modal_close_new_event_button",
                                ),
                            ],
                            position="right",
                        ),
                    ],
                ),
            ],
        ),
    ]
)

@app.callback(
    Output("modal", "opened"),
    Output("modal", "title"),
    Output("modal_event_display_context", "children"),
    Input("modal-close-button", "n_clicks"),
    Input("calendar", "clickedEvent"),
    State("modal", "opened"),
)
def open_event_modal(n, clickedEvent, opened):
    ctx = callback_context

    if not ctx.triggered:
        raise PreventUpdate
    else:
        button_id = ctx.triggered[0]["prop_id"].split(".")[0]

    if button_id == "calendar" and clickedEvent is not None:
        event_title = clickedEvent["title"]
        event_context = clickedEvent["extendedProps"]["context"]
        return (
            True,
            event_title,
            html.Div(
                dash_quill.Quill(
                    id="input3",
                    value=f"{event_context}",
                    modules={
                        "toolbar": False,
                        "clipboard": {
                            "matchVisual": False,
                        },
                    },
                ),
                style={"width": "100%", "overflowY": "auto"},
            ),
        )
    elif button_id == "modal-close-button" and n is not None:
        return False, dash.no_update, dash.no_update

    return opened, dash.no_update

@app.callback(
    Output("add_modal", "opened"),
    Output("start_date", "value"),
    Output("end_date", "value"),
    Output("start_time", "value"),
    Output("end_time", "value"),
    Input("calendar", "dateClicked"),
    Input("modal_close_new_event_button", "n_clicks"),
    State("add_modal", "opened"),
)
def open_add_modal(dateClicked, close_clicks, opened):

    ctx = callback_context

    if not ctx.triggered:
        raise PreventUpdate
    else:
        button_id = ctx.triggered[0]["prop_id"].split(".")[0]

    if button_id == "calendar" and dateClicked is not None:
        try:
            start_time = datetime.strptime(dateClicked, "%Y-%m-%dT%H:%M:%S%z").time()
            start_date_obj = datetime.strptime(dateClicked, "%Y-%m-%dT%H:%M:%S%z")
            start_date = start_date_obj.strftime("%Y-%m-%d")
            end_date = start_date_obj.strftime("%Y-%m-%d")
        except ValueError:
            start_time = datetime.now().time()
            start_date_obj = datetime.strptime(dateClicked, "%Y-%m-%d")
            start_date = start_date_obj.strftime("%Y-%m-%d")
            end_date = start_date_obj.strftime("%Y-%m-%d")
        end_time = datetime.combine(date.today(), start_time) + timedelta(hours=1)
        start_time_str = start_time.strftime("%Y-%m-%d %H:%M:%S")
        end_time_str = end_time.strftime("%Y-%m-%d %H:%M:%S")
        return True, start_date, end_date, start_time_str, end_time_str

    elif button_id == "modal_close_new_event_button" and close_clicks is not None:
        return False, dash.no_update, dash.no_update, dash.no_update, dash.no_update

    return opened, dash.no_update, dash.no_update, dash.no_update, dash.no_update

@app.callback(
    Output("calendar", "events"),
    Output("add_modal", "opened", allow_duplicate=True),
    Output("event_name_input", "value"),
    Output("event_color_select", "value"),
    Output("rich_text_input", "value"),
    Input("modal_submit_new_event_button", "n_clicks"),
    State("start_date", "value"),
    State("start_time", "value"),
    State("end_date", "value"),
    State("end_time", "value"),
    State("event_name_input", "value"),
    State("event_color_select", "value"),
    State("rich_text_output", "children"),
    State("calendar", "events"),
)
def add_new_event(
    n,
    start_date,
    start_time,
    end_date,
    end_time,
    event_name,
    event_color,
    event_context,
    current_events,
):
    if n is None:
        raise PreventUpdate

    start_time_obj = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
    end_time_obj = datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S")

    start_time_str = start_time_obj.strftime("%H:%M:%S")
    end_time_str = end_time_obj.strftime("%H:%M:%S")

    start_date = f"{start_date}T{start_time_str}"
    end_date = f"{end_date}T{end_time_str}"

    new_event = {
        "title": event_name,
        "start": start_date,
        "end": end_date,
        "className": event_color,
        "context": event_context,
    }

    return current_events + [new_event], False, "", "bg-gradient-primary", ""

@app.callback(
    Output("rich_text_output", "children"),
    [Input("rich_text_input", "value")],
    [State("rich_text_input", "charCount")],
)
def display_output(value, charCount):
    return value

if __name__ == " __main__":
    app.run_server(debug=True, port=8556)

```

Basically the layout is the calendar component I’ve built out as a package:

```auto
fcc.FullCalendarComponent(
            id="calendar",
            initialDate=f"2024-04-01",
            editable=True,
            selectable=True,
            events=[
                {
                    "title": "Pip Install Python",
                    "start": f"{formatted_date}",
                    "end": f"{formatted_date}",
                    "className": "bg-gradient-success",
                    "context": "Pip Install FullCalendar",
                }
            ],
        )

```

I’ve also created some more complex examples to showcase the full capabilities of this project.

**timeGridWeek:**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/b/e/be4870155551e5e25293d7a35e636b4b7d99642e.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/c/5/c5c2c834340aac7d5fd899de1ff70ab14e9ab743.png)

**Custom time grid date range (example) timeGridFourDay:**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/d/2/d26bed5b4c4950b43f9c4c52a515f7c716919375.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/a/6/a619e812404e289535d932b5b80b6a99a093ded5.png)

**listWeek:**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/a/0/a088c7945186dbd4f1c91341eab5ae2a44f34a77.jpeg)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/c/7/c7ccaf6ddd2c7ba8b4f18cb54afac13123cf9ebb.png)

**listWeek (multiple initial events):**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/f/1/f16c65a1d67225cf1973f3ab960c168e1774f14e.jpeg)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/e/5/e5c57d43f833d10409a3247dc51928f06c6b7a64.png)

**dayGridWeek:**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/1/0/10b85fb4513937d882d52634025b12c0f9c787e7.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/b/c/bc0832dea860f411798f55ce067446feb80ef10f.png)

**multiMonthYear (multiMonthMaxColumns=int):**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/c/6/c69420acd00fc2b45948a43201187e73d1d6a1ad.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/1/4/1495ee8b0b0f2a6e1e657165577001171055e096.png)

**multiMonthYear:**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/7/9/796d90b3cd9c05abb34d7c87d25c112d2f2fc5ba.jpeg)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/1/9/19a981a8605bcf8763b10a0642479d5e23a820e2.png)

**Custom multiMonthYear date range (example):**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/1/7/174c9427ee35485d7cf462781367ac8bc44cacfb.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/2/0/20e03b7253dc456d1909c8268fc8c086368d4df0.png)

**resourceTimeLineWeek:**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/1/7/1733a9a8c3234b9feed1824755348e36ea22fdd2.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/9/8/9803e6544783d6b7045e7a6600a1e9f019fa11af.png)

**resourceTimeGridDay:**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/5/0/508f3e3dc8a06dd07caac18aa65080aeeedf8b1b.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/5/2/52043081dd373119528808e1a864672cc23be4f7.png)

**dayGridMonth with (navLinks=True, headerToolBar=dic):**  
 ![pasted-movie](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/d/d/dd1267d02c370dd99e0d8fdca05ce0823772f2f2.gif)

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/8/e/8ecd2d4717eca97d4dc67a4118dd1ffba886b1f2.png)

**prop - buisnessHours=[dic]:**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/3/b/3b84af6f20d19473d006afda8c0637d6ee9fcbd0.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/5/f/5fa67ffc9a105074d9a6444fd3149dcf277173ac.png)

**prop - nowIndicator=True**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/7/b/7b8d3f9297e9bf357ded00262c366c5f6fdef276.png)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/0/d/0d151e6ef88b3c829ada83642e834eba8b56b695.png)

**Setting up time range for events:**

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/7/f/7f29815f84bf18d503c5cc18a28f43ae038b71f9.jpeg)  
 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/8/4/8415dd3fd7b8eb7be40cc1668db2fd1e9935cfb6.png)

Some base improvements I’d like to make in the coming days are the style.css should be automatically included in the pip install, and not needed to be be manually added in the future. Add start time, end day and time for create event modal.

Would appreciate plotly’s team support in taking over this component as [fullcalendar.io](http://fullcalendar.io) has Premium api points that I’ve connected that would be useful if a direct collaboration is setup between the two projects [https://fullcalendar.io/pricing](https://fullcalendar.io/pricing)

For more refrence check out [fullcalendar.io](http://fullcalendar.io) directly at: [Documentation | FullCalendar](https://fullcalendar.io/docs)

Github project (support with a ⭐): [GitHub - pip-install-python/full\_calendar\_component: https://fullcalendar.io/ for Plotly Dash.](https://github.com/pip-install-python/full_calendar_component)

Pypi: [full-calendar-component · PyPI](https://pypi.org/project/full-calendar-component/)

Anything else that would be a cool addition just post in the comments and if I find the time I might add it to the project.

Also special thanks to @AnnMarieW, @jinnyzor, @adamschroeder.

Follow me on github:  
[![Pip Install Python GitHub stats](https://github-readme-stats.vercel.app/api?username=pip-install-python&show_icons=true&theme=radical)](https://github.com/pip-install-python)  
Also if you like this project check out my other dash packages I’ve built:

1. `dash-summernote`: [Pip install dash-summernote 📝 - #2 by AnnMarieW](https://community.plotly.com/t/pip-install-dash-summernote/83562/2)

2. `dash-swiper`: [Pip install dash-swiper 🌠](https://community.plotly.com/t/pip-install-dash-swiper/83573)

3. `dash-insta-stories`: [Pip install dash-insta-stories 🐇](https://community.plotly.com/t/pip-install-dash-insta-stories/83566)

4. `dash-emoji-mart`: [Pip install dash-emoji-mart 😀](https://community.plotly.com/t/pip-install-dash-emoji-mart/83615)

Cheers,  
Pip

---

<div class="post-metadata">

**Author:** ![jinnyzor](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/jinnyzor/32/21194_2.png) [@jinnyzor](https://community.plotly.com/u/jinnyzor)\
**Post date:** [March 31, 2024, 1:29pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/2 "2024-03-31T13:29:48Z")

</div>

Hello @PipInstallPython,

Is this an AIO component? Or did you wrap the full calendar as a dash component? Was looking for repo.

If it is a wrapped component, you can include it in the component.

If it is an AIO, you can include it in the bundle and app. Check out here for an example:

> <https://github.com/BSd3v/dash-yada/blob/dev/dash_yada/ __init__.py>

---

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [March 31, 2024, 4:01pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/3 "2024-03-31T16:01:47Z")

</div>

Originally I attempted:

`_css_dist = [{"relative_package_path": "../style.css", "namespace": package_name}]`

but it crashed the app, eventually just set \_css\_dist to a blank list to proceed.

I started the project like 3 weeks ago don’t remember specifically how i set it up, believe it was just following through a base dash-boiler-plate.

Just pushed the repo to github: [GitHub - pip-install-python/full\_calendar\_component: https://fullcalendar.io/ for Plotly Dash.](https://github.com/pip-install-python/full_calendar_component)

---

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [April 1, 2024, 5:05am UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/4 "2024-04-01T05:05:29Z")

</div>

updated the package to full-calendar-component 0.0.2

- initialView (supports): `dayGridMonth, timeGridWeek, timeGridDay, listWeek, # dayGridWeek, dayGridYear, multiMonthYear, resourceTimeline, resourceTimeGridDay, resourceTimeLineWeek`

- headerToolbar editable directly from `fcc.FullCalendarComponent`

- added multiMonthMaxColumns

- resources editable from `fcc.FullCalendarComponent`

- navLink added to `fcc.FullCalendarComponent`

- businessHours added to `fcc.FullCalendarComponent`

- nowIndicator added to `fcc.FullCalendarComponent`

---

<div class="post-metadata">

**Author:** ![adamschroeder](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/adamschroeder/32/17280_2.png) [@adamschroeder](https://community.plotly.com/u/adamschroeder)\
**Post date:** [April 1, 2024, 2:28pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/5 "2024-04-01T14:28:22Z")

</div>

what a great component @PipInstallPython.

I’m having so much fun playing around with it.

Would it make sense to add all these example codes and images to the Project’s Readme so people can have quick access to them?

Do you know why at the bottom left corner there is a notification: “Your license key is invalid. [More Info](https://fullcalendar.io/docs/schedulerLicenseKey#invalid)”. What is this referring to?

I was even able to build an app with this component on [WasmDash](https://wasmdash.vercel.app/). Find code below the image (I hope I used the external\_stylesheets correcty).

 ![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/9/1/91347c8bc4d26c56cdebd92493746afc89d917f0.png)

```auto
import micropip
await micropip.install('dash-mantine-components')
await micropip.install('dash-quill')
await micropip.install('full-calendar-component==0.0.2')

import full_calendar_component as fcc
from dash import *
import dash_mantine_components as dmc
from dash.exceptions import PreventUpdate
from datetime import datetime
import dash_quill

app = Dash( __name__ , prevent_initial_callbacks=True, external_stylesheets=["https://raw.githubusercontent.com/pip-install-python/dash-full-calendar/master/assets/fullcalendar.css"])

quill_mods = [
    [{"header": "1"}, {"header": "2"}, {"font": []}],
    [{"size": []}],
    ["bold", "italic", "underline", "strike", "blockquote"],
    [{"list": "ordered"}, {"list": "bullet"}, {"indent": "-1"}, {"indent": "+1"}],
    ["link", "image"],
    # ['clean'],
]

# Get today's date
today = datetime.now()

# Format the date
formatted_date = today.strftime("%Y-%m-%d")

app.layout = html.Div(
    [
        fcc.FullCalendarComponent(
            id="calendar",
            initialDate=f"2024-04-01",
            editable=True,
            selectable=True,
            events=[
                {
                    "title": "Pip Install Python",
                    "start": f"{formatted_date}",
                    "end": f"{formatted_date}",
                    "className": "bg-gradient-success",
                    "context": "Pip Install FullCalendar",
                }
            ],
        ),
        dmc.Modal(
            id="modal",
            size="xl",
            title="Event Details",
            zIndex=10000,
            children=[
                html.Div(id="modal_event_display_context"),
                dmc.Space(h=20),
                dmc.Group(
                    [
                        dmc.Button(
                            "Close",
                            color="red",
                            variant="outline",
                            id="modal-close-button",
                        ),
                    ],
                    position="right",
                ),
            ],
        ),
        dmc.Modal(
            id="add_modal",
            title="New Event",
            size="xl",
            children=[
                dmc.Grid(
                    children=[
                        dmc.Col(
                            html.Div(
                                dmc.DatePicker(
                                    id="add_modal_date",
                                    label="Start Date",
                                    value=datetime.now().date(),
                                    styles={"width": "100%"},
                                    disabled=True,
                                ),
                                style={"width": "100%"},
                            ),
                            span=6,
                        ),
                        dmc.Col(
                            html.Div(
                                dmc.TextInput(
                                    label="Event Name:",
                                    style={"width": "100%"},
                                    id="event_name_input",
                                    required=True,
                                ),
                                style={"width": "100%"},
                            ),
                            span=6,
                        ),
                    ],
                    gutter="xl",
                ),
                dmc.Select(
                    label="Select event color",
                    placeholder="Select one",
                    id="event_color_select",
                    value="ng",
                    data=[
                        {
                            "value": "bg-gradient-primary",
                            "label": "bg-gradient-primary",
                        },
                        {
                            "value": "bg-gradient-secondary",
                            "label": "bg-gradient-secondary",
                        },
                        {
                            "value": "bg-gradient-success",
                            "label": "bg-gradient-success",
                        },
                        {"value": "bg-gradient-info", "label": "bg-gradient-info"},
                        {
                            "value": "bg-gradient-warning",
                            "label": "bg-gradient-warning",
                        },
                        {"value": "bg-gradient-danger", "label": "bg-gradient-danger"},
                        {"value": "bg-gradient-light", "label": "bg-gradient-light"},
                        {"value": "bg-gradient-dark", "label": "bg-gradient-dark"},
                        {"value": "bg-gradient-white", "label": "bg-gradient-white"},
                    ],
                    style={"width": "100%", "marginBottom": 10},
                    required=True,
                ),
                dash_quill.Quill(
                    id="rich_text_input",
                    modules={
                        "toolbar": quill_mods,
                        "clipboard": {
                            "matchVisual": False,
                        },
                    },
                ),
                dmc.Accordion(
                    children=[
                        dmc.AccordionItem(
                            [
                                dmc.AccordionControl("Raw HTML"),
                                dmc.AccordionPanel(
                                    html.Div(
                                        id="rich_text_output",
                                        style={
                                            "height": "300px",
                                            "overflowY": "scroll",
                                        },
                                    )
                                ),
                            ],
                            value="raw_html",
                        ),
                    ],
                ),
                dmc.Space(h=20),
                dmc.Group(
                    [
                        dmc.Button("Submit", id="modal_submit_new_event_button"),
                        dmc.Button(
                            "Close",
                            color="red",
                            variant="outline",
                            id="modal_close_new_event_button",
                        ),
                    ],
                    position="right",
                ),
            ],
        ),
    ]
)

@app.callback(
    Output("modal", "opened"),
    Output("modal", "title"),
    Output("modal_event_display_context", "children"),
    Input("modal-close-button", "n_clicks"),
    Input("calendar", "clickedEvent"),
    State("modal", "opened"),
)
def open_event_modal(n, clickedEvent, opened):
    ctx = callback_context

    if not ctx.triggered:
        raise PreventUpdate
    else:
        button_id = ctx.triggered[0]["prop_id"].split(".")[0]

    if button_id == "calendar" and clickedEvent is not None:
        event_title = clickedEvent["title"]
        event_context = clickedEvent["extendedProps"]["context"]
        return (
            True,
            event_title,
            html.Div(
                dash_quill.Quill(
                    id="input3",
                    value=f"{event_context}",
                    modules={
                        "toolbar": False,
                        "clipboard": {
                            "matchVisual": False,
                        },
                    },
                ),
                style={"width": "100%", "overflowY": "auto"},
            ),
        )
    elif button_id == "modal-close-button" and n is not None:
        return False, dash.no_update, dash.no_update

    return opened, dash.no_update

@app.callback(
    Output("add_modal", "opened"),
    Output("add_modal_date", "value"),
    Input("calendar", "dateClicked"),
    Input("modal_close_new_event_button", "n_clicks"),
    State("add_modal", "opened"),
)
def open_add_modal(dateClicked, close_clicks, opened):
    ctx = callback_context

    if not ctx.triggered:
        raise PreventUpdate
    else:
        button_id = ctx.triggered[0]["prop_id"].split(".")[0]

    if button_id == "calendar" and dateClicked is not None:
        return True, dateClicked
    elif button_id == "modal_close_new_event_button" and close_clicks is not None:
        return False, dash.no_update

    return opened, dash.no_update

@app.callback(
    Output("calendar", "events"),
    Output("add_modal", "opened", allow_duplicate=True),
    Output("event_name_input", "value"),
    Output("event_color_select", "value"),
    Output("rich_text_input", "value"),
    Input("modal_submit_new_event_button", "n_clicks"),
    State("add_modal_date", "value"),
    State("event_name_input", "value"),
    State("event_color_select", "value"),
    State("rich_text_output", "children"),
    State("calendar", "events"),
)
def add_new_event(n, date, event_name, event_color, event_context, current_events):
    if n is None:
        raise PreventUpdate

    new_event = {
        "title": event_name,
        "start": date,
        "end": date,
        "className": event_color,
        "context": event_context,
    }

    return current_events + [new_event], False, "", "bg-gradient-primary", ""

@app.callback(
    Output("rich_text_output", "children"),
    [Input("rich_text_input", "value")],
    [State("rich_text_input", "charCount")],
)
def display_output(value, charCount):
    return value

if __name__ == " __main__":
    app.run_server(debug=True, port=8257)

```

---

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [April 1, 2024, 2:44pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/6 "2024-04-01T14:44:12Z")

</div>

Planning on building and hosting an app similar to [https://www.dash-mantine-components.com/](https://www.dash-mantine-components.com/) and [https://www.dash-leaflet.com/](https://www.dash-leaflet.com/) and better defining the readme.md just haven’t had the time. I’ve only put like two days worth of work into the project. Just used this as an initial place to put some context for those interested in playing around and testing it before the official 1.0.0 release.

The license key is in reference to: [https://fullcalendar.io/pricing](https://fullcalendar.io/pricing) specifically the initialView= ‘timeline’ and ‘vertical resource’ I’ve build out connections to those endpoints, if the plotly team find this useful might be worth reaching out to [fullcalendar.io](http://fullcalendar.io) directly from yall’s end and see if we could work out a direct collaboration to support those premium features.

Doesn’t look like the stylesheet was loaded correctly for you, still trying to work out the best way to reference it within \_css\_dist in the **init** so its just automatically added for users.

---

<div class="post-metadata">

**Author:** ![AnnMarieW](https://avatars.discourse-cdn.com/v4/letter/a/ec9cab/32.png) [@AnnMarieW](https://community.plotly.com/u/AnnMarieW)\
**Post date:** [April 1, 2024, 3:24pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/7 "2024-04-01T15:24:41Z")

</div>

Split this topic on April 1, 2024, 3:24pm UTC

A post was split to a new topic: [More info on WASM Dash](https://community.plotly.com/t/more-info-on-wasm-dash/83480)

---

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [April 3, 2024, 4:24am UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/8 "2024-04-03T04:24:13Z")

</div>

**Updated the package to:** `full-calendar-component==0.0.3`

 ![Screenshot 2024-04-02 at 11.16.35 PM](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/d/e/ded5954a8e57cb5a627bb63dd862afa5612c8f24.png)

- Now supporting Start Time, End Date and End Time based on selection of the day or week grid’s time slots from the fields outlined in the picture

- Automatically sets up time’s based on a new slotClick={handleTimeClick}

- Style is automatically provided via the pip install , also trimmed the .css file

- Changed the modals to reflect improvements in usage.py and styled modals dark for better contrast.

- Setup style for better mobile viewing

Goals for future 0.0.4 release:

- Ability to delete events

- Create a check on add\_event fields so they all need to be populated before attempting to create event

- maybe language support

… any other suggestions just lmk.

---

<div class="post-metadata">

**Author:** ![clemen](https://avatars.discourse-cdn.com/v4/letter/c/dbc845/32.png) [@clemen](https://community.plotly.com/u/clemen)\
**Post date:** [April 17, 2024, 8:40am UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/9 "2024-04-17T08:40:28Z")

</div>

Hello @PipInstallPython first of all many thanks for your work!  
Though, I encountered the following issue when I try to update the `headerToolbar`’s title. Updating `initialDate`’s value does not seem to have any effect on the `headerToolbar`’s title, and the **calendar’s date view**.

On the other hand `prev` and `next` buttons work well. What I want to do here is to set a new date using a date picker `start_date` attribute, and update the calendar’s view based on `start_date` changes.

Here is the relevant layout and callback part of my code:

```python
    @app.callback(
        Output("calendar", "initialDate"),
        Input("datepickerrange-limits", "start_date"),
    )
    def update_initial_date(start_date: str) -> str:
        if start_date is None:
            raise PreventUpdate
        formated_date = datetime.fromisoformat(start_date).strftime("%Y-%m-%d")
        return formated_date

```

```python
        fcc.FullCalendarComponent(
            id="calendar", # Unique ID for the component
            initialView="dayGridMonth", # dayGridMonth, timeGridWeek, timeGridDay, listWeek,
            # dayGridWeek, dayGridYear, multiMonthYear, resourceTimeline, resourceTimeGridDay, resourceTimeLineWeek
            headerToolbar={
                "left": "prev,next today",
                "center": "title",
                "right": "listWeek,timeGridDay,timeGridWeek,dayGridMonth",
            }, # Calendar header
            initialDate=f"{formatted_date}", # Start date for calendar
            editable=True, # Allow events to be edited
            selectable=True, # Allow dates to be selected
            events=[],
            nowIndicator=True, # Show current time indicator
            navLinks=True, # Allow navigation to other dates
        ),

```

Thanks in advance for your help!  
Best,

---

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [April 17, 2024, 5:18pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/10 "2024-04-17T17:18:33Z")

</div>

Hey @clemen ,

Welcome to the plotly form. At the moment their is no `gotoDate` or an equivalent `start_date` prop setup so you can’t define a date via a date picker and use that to change the display of the calendar. Once a calendar is rendered, whatever you set as the initialDate is what it will always render on.

However the headertoolbar title seems to be working for me, its based on the initialDate, you can try `initialDate=f"2024-01-17"` and you’ll see July 17 within the title, also looks like you set it up correctly with the:

```auto
headerToolbar={
                "left": "prev,next today",
                "center": "title",
                "right": "listWeek,timeGridDay,timeGridWeek,dayGridMonth",
            }

```

So not an ideal response, can only confirm no way of changing a date of a calendar’s render from an outside component after its been rendered. But the `title` should work. However I’ll look into building a `start_date` or `gotoDate` prop and see if I can get a solution setup for the next release.

---

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [May 13, 2024, 3:21pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/12 "2024-05-13T15:21:50Z")

</div>

Hey Nick,

Most of the calendar is free, their is a timeline-view, that I have showcased - you can learn more about here: [Timeline View - Docs | FullCalendar](https://fullcalendar.io/docs/timeline-view) . This aspect of full calendar is not free and needs a license. In the repo, I included the endpoints to connect to some of the paid features for any enterprise users and as a hopeful way to get plotly to 🤞 hopefully network with full calendar directly and get a partnership worked out. Maybe with more community interest the component could evolve further.

---

<div class="post-metadata">

**Author:** ![nicobockko](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@nicobockko](https://community.plotly.com/u/nicobockko)\
**Post date:** [May 14, 2024, 2:42pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/13 "2024-05-14T14:42:38Z")

</div>

but… Now I’d like to hide that “your license key is invalid. More Info” comment… may I…?

---

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [May 14, 2024, 2:55pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/14 "2024-05-14T14:55:00Z")

</div>

Sure, currently on 0.0.3 but you could try 0.0.2 or 0.0.1 if neither of those work let me know and ill take a look into it

---

<div class="post-metadata">

**Author:** ![clemen](https://avatars.discourse-cdn.com/v4/letter/c/dbc845/32.png) [@clemen](https://community.plotly.com/u/clemen)\
**Post date:** [June 3, 2024, 3:16pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/15 "2024-06-03T15:16:32Z")

</div>

Hello @PipInstallPython, about the **license** I tested 0.0.2 and the problem is remaining, with 0.0.1 my whole app breaks. Do you have any advise on how I could adapt the latest version so it gets rid of the premium end points and thus the license problems?  
Thank you very much!

---

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [June 3, 2024, 3:38pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/16 "2024-06-03T15:38:37Z")

</div>

> <https://github.com/pip-install-python/full_calendar_component/blob/main/src/lib/components/FullCalendarComponent.react.js>

Fork the repo:

npm uninstall @fullcalendar/resource-timeline  
npm uninstall @fullcalendar/resource-timegrid

remove both resource-timegrid and resource-timeline from the FullCalendarComponent.react.js

npm run build

pip install -r requirements.txt

run usage.py to test it out

from [https://fullcalendar.io/pricing](https://fullcalendar.io/pricing) it looks like [Timeline View](https://fullcalendar.io/docs/timeline-view) and  
[Vertical Resource View](https://fullcalendar.io/docs/vertical-resource-view) are the only two views that could be causing the problem.

Once you have npm and pip setyp, mainly be working within rebuilding FullCalendarComponent.react.js and running python usage.py to test the changes you make.

Would avoid using 0.0.1, many things where broken on the first release 😅

---

<div class="post-metadata">

**Author:** ![clemen](https://avatars.discourse-cdn.com/v4/letter/c/dbc845/32.png) [@clemen](https://community.plotly.com/u/clemen)\
**Post date:** [June 5, 2024, 12:34pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/17 "2024-06-05T12:34:14Z")

</div>

Thank you very much, worked perfectly!!

---

<div class="post-metadata">

**Author:** ![nicobockko](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@nicobockko](https://community.plotly.com/u/nicobockko)\
**Post date:** [June 21, 2024, 3:30pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/18 "2024-06-21T15:30:42Z")

</div>

> [@PipInstallPython](#):
>
> 0.2 or 0.0.1 if neither of those work let me know and ill take a look i

sir!! i’m using 0.0.3 but i don’t know how to remove timegrid, timeline for hide a licence message

i can’t see ‘FullCalendarComponent.react.js’ file …

---

<div class="post-metadata">

**Author:** ![PipInstallPython](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/pipinstallpython/32/34539_2.png) [@PipInstallPython](https://community.plotly.com/u/PipInstallPython)\
**Post date:** [June 21, 2024, 4:27pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/20 "2024-06-21T16:27:27Z")

</div>

![Screenshot 2024-06-21 at 11.18.15 AM](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/c/b/cba1a6c3847cfe9fd2fb02a6973400d9c41723dc.png)

Upgrade to 0.0.4, just pushed an update that removes:

@fullcalendar/resource-timeline  
@fullcalendar/resource-timegrid

which also removes the license message.

Also made changes to allow the prop business hours for the calendar and changed the styling to reflect blacking out days and hours which are not in the business hours. Example code:

```auto
from dash import *
import full_calendar_component as fcc
from datetime import datetime

# Get today's date
today = datetime.now()

# Format the date
formatted_date = today.strftime("%Y-%m-%d")

events = [
    {
        'title': 'All Day Event',
        'start': f'{formatted_date}T01:00:00',
        'end': f'{formatted_date}T02:00:00',
        'className': 'bg-info',
        'context': 'Welcome to my packages.'
    },
]

fcc.FullCalendarComponent(
            id="calendar", # Unique ID for the component
            initialView="listWeek", # dayGridMonth, timeGridWeek, timeGridDay, listWeek,
            # dayGridWeek, dayGridYear, multiMonthYear, resourceTimeline, resourceTimeGridDay, resourceTimeLineWeek
            headerToolbar={
                'start': '',
                "left": "prev,next today",
                "center": 'title',
                "right": "listWeek,timeGridDay,timeGridWeek,dayGridMonth",
            }, # Calendar header
            initialDate=f"{formatted_date}", # Start date for calendar
            editable=True, # Allow events to be edited
            selectable=True, # Allow dates to be selected
            events=events,
            nowIndicator=True, # Show current time indicator
            navLinks=True, # Allow navigation to other dates
            businessHours=[{
                    'daysOfWeek': [1, 2, 3, 4, 5], # Monday, Tuesday, Wednesday, Thursday, Friday
                    'startTime': '10:00', # Business start time
                    'endTime': '18:00', # Business end time
                }],
        )

```

---

<div class="post-metadata">

**Author:** ![nicobockko](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@nicobockko](https://community.plotly.com/u/nicobockko)\
**Post date:** [June 21, 2024, 8:57pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/21 "2024-06-21T20:57:20Z")

</div>

Oh my …  
Literally you are my GOD Thanks

2024년 6월 22일 (토) 오전 1:37, Pip Install Python via Plotly Community Forum \<[notifications@plot.discoursemail.com](mailto:notifications@plot.discoursemail.com)\>님이 작성:

---

<div class="post-metadata">

**Author:** ![nicobockko](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@nicobockko](https://community.plotly.com/u/nicobockko)\
**Post date:** [June 22, 2024, 3:00pm UTC](https://community.plotly.com/t/pip-install-full-calendar-component/83460/22 "2024-06-22T15:00:49Z")

</div>

sir!! can i catch event of ‘\<, \>, today’ ???  
i’d like to lazy loading for schedules!!!

![image](https://us1.discourse-cdn.com/flex024/uploads/plot/original/3X/b/f/bf7a76c8864b645332988510d49c52115740fc5c.png)

[Next page](https://community.plotly.com/t/pip-install-full-calendar-component/83460.md?page=2)
