How to create a scheduler with Python and Taipy

7 min read

While there are many scheduling applications available, nothing beats the DIY (Do It Yourself) philosophy, as you will learn a lot while building a Scheduler from scratch. However, not everyone is a web developer. To overcome this, we’re going to use Taipy, a full-stack Python framework that will make the entire process a pleasant experience.

What are we going to talk about?

  • What does our Taipy scheduler application look like
  • Installing the requirements
  • Creating the Taipy scheduler application
  • Running the Taipy scheduler application
  • Checking the generated event

What does our Taipy scheduler application look like

When we first launch the application, it will request us to log in using hosted authentication:

Taipy Scheduler Welcome Screen

Here, while we’re going to choose Gmail, we could choose any other provider:

Choose your provider

We need to choose the account we want to use:

Choose your account

We need to choose the account one more time, for security reasons:

Choose your account again

We will get a message saying that our application hasn’t been verified by Google, but that’s OK as we’re not using a production environment:

Google verification

Here, we need to confirm that we’re giving Nylas access to our account, although keep in mind that we’re only requesting calendar scopes:

Give Nylas access to your services

Once we are logged in, an availability check is going to be performed. This will include the logged user and the calendar owner. Simply, both calendars will be checked to determine common empty slots when a meeting can be scheduled.

Scheduler Main Screen

And the bottom, we have a button to create the event, after selecting it from the list, and also a a button to close the session and go back to the main screen.

Scheduler setup meeting button

We can select a day and time, and then select the Setup Meeting button:

Choose your time

A confirmation will appear once we create the event, whether it fails or not:

Event created successfully

The selected slot will be instantly taken from the list, as it is not available anymore:

Scheduler available times

Installing the requirements

While this is a Taipy application, we’re going to use Flask as well, as we need it to handle the hosted authentication. We’re going to install Pendulum as well to easily handle dates.

In a terminal window, type the following:

$ pip3 install taipy
$ pip3 install -U Flask
$ pip3 install pendulum
$ pip3 install python-dotenv

Creating the Taipy scheduler application

We are going to create a folder called Scheduler_Taipy. Inside this folder, we are going to create two files, one called Scheduler.py and the other one Scheduler.css (Note that they need to have the same name but with different extensions):

# Import your dependencies
from dotenv import load_dotenv
import os
from nylas import Client  # type: ignore
from taipy.gui import Gui, navigate, notify
import pendulum
from flask import Flask, redirect, session, request
import re
import time
from nylas.models.auth import URLForAuthenticationConfig
from nylas.models.availability import GetAvailabilityRequest
from nylas.models.auth import CodeExchangeRequest

flask_app = Flask(__name__)

# Global variables for the state
#email_address = ""
value = ""
schedules = {"available":''}

# Load your env variables
load_dotenv()

# Initialize an instance of the Nylas SDK using the client credentials
nylas = Client(
    api_key = os.environ.get("V3_API_KEY")
)

root_md=""
page1_md="""
# Welcome to Blag's Scheduler

<|Nyla_Space.png|image|>


<|Google.png|image|on_action=on_button_action|>
"""

page2_md = """
### Available dates and times

<|{value}|selector|lov={schedules.get("available")}|>

<|Setup meeting|button|on_action=on_schedule_action|>  

<|Log out|button|on_action=on_logout_action|>
"""

pages = {
     "/": root_md,
     "page1": page1_md,
     "page2": page2_md
}

@flask_app.route("/login/nylas/authorized")
def authorized():
    # Get the code generated by the hosted authentication
    code = request.args.get("code")
    # Exchange the code for a grant
    exchangeRequest = CodeExchangeRequest({"redirect_uri": "http://localhost:5000/login/nylas/authorized",
                                           "code": code,
                                           "client_id": os.environ.get("V3_CLIENT")})
    #print(exchangeRequest)
    # Get the information from the grant
    exchange = nylas.auth.exchange_code_for_token(exchangeRequest)
    response, _ = nylas.grants.find(exchange.grant_id)
    # Create a session
    session.permanent = True
    # Fill session details    
    session["email_address"] = response.email
    session["grant_id"] = exchange.grant_id
    # Call the login function to load availability
    dummy = login(session.get("state"))
    # Call the page to display availability
    return redirect("http://localhost:5000/page2")

def login(state):
    # Give some time for the grant to setup
    time.sleep(3)
    date_time = []
    schedules["available"] = ""

    # Get the availability for both email accounts
    request_body = GetAvailabilityRequest(
        participants = [
            {
                "email": os.environ.get("GRANT_ID"),
                "calendar_ids": [
                    os.environ.get("GRANT_ID")
                ],
            },
            {
                "email": session["email_address"],
                "calendar_ids": [
                    session["email_address"]
                ],
            },            
        ],
        
        duration_minutes = 60,
    )
    
    # Get today’s date
    today = pendulum.now()
    # Day of the week
    dow = today.day_of_week
    # Our working days goes from 10:00am to 5:00pm
    # And we don't want days that already passed by
    for x in range(dow, 6):
        start_time = pendulum.local(today.year, today.month, today.day, today.hour, 0, 0).int_timestamp
        end_time = pendulum.local(today.year, today.month, today.day, 17, 0, 0).int_timestamp
        
        request_body["start_time"] = start_time
        request_body["end_time"] = end_time

        # Get the available spots
        availability, _request_ids = nylas.calendars.get_availability(request_body)
        # Add the following day
        today = today.add(days=1)
        # Find available times
        for slot in availability.time_slots:
           ts = pendulum.from_timestamp(slot.start_time, today.timezone.name).strftime("%m/%d/%Y at %H:%M")
           te = pendulum.from_timestamp(slot.end_time ,today.timezone.name).strftime("%H:%M")
           date_time.insert(len(date_time), ts + " to " + te)

    # Here are all the available spots
    schedules["available"] = date_time
    return date_time

def on_button_action(state):
    # Generate the hosted authentication page
    session.pop("email_address", None)
    config = URLForAuthenticationConfig({"client_id": os.environ.get("V3_CLIENT"), 
                                         "redirect_uri" : "http://localhost:5000/login/nylas/authorized",
                                         "scope":["https://www.googleapis.com/auth/calendar.readonly"]})
    url = nylas.auth.url_for_oauth2(config)
    session["state"] = state
    # And call it
    navigate(state, url)

def on_schedule_action(state):
    # Extract the dates from the selected slot  
    pattern = r"(\d{1,2}/\d{1,2}/\d{4}) at (\d{1,2}:\d{2}) to (\d{1,2}:\d{2})"
    match = re.search(pattern, state.value)
    date = match.group(1)
    date_parts = date.split('/')
    start_time = match.group(2)
    start_time_parts = start_time.split(':')
    end_time = match.group(3)
    end_time_parts = end_time.split(':')
    
    query_params = {"calendar_id": os.environ.get("GRANT_ID")}
    
    # Define the events details
    request_body = {
        "when": { 
            "start_time": pendulum.local(int(date_parts[2]), int(date_parts[0]), 
                          int(date_parts[1]), int(start_time_parts[0]), 0, 0).int_timestamp,
            "end_time": pendulum.local(int(date_parts[2]), int(date_parts[0]), 
                          int(date_parts[1]), int(end_time_parts[0]), 0, 0).int_timestamp,        
        },
        "title": "Meeting with Blag",
       "location": "Blag's Online Den",
        "description": f"You're meeting with Blag on {date} from {start_time} to {end_time}",
        "participants": [{
            "email": session["email_address"], 
          }]
    }
    
    # Create the event
    event = nylas.events.create(os.environ.get("GRANT_ID"), 
                 query_params = query_params, request_body = request_body).data
    # Display a message with the status of the event creation
    if event.id:
        date_time = login(state)
        state.schedules["available"] = date_time
        navigate(state, "page2")
        notify(state, 'info', "The event was created successfully")
    else:
      notify(state, 'info', "There was an error creating the event") 

def on_logout_action(state):
    # We're logging out. Destroy the grant and clear all sessions
    nylas.grants.destroy(session["grant_id"])
    session.pop("email_address", None)
    session.pop("grant_id", None)
    navigate(state, "/")
    
Gui(pages=pages, flask=flask_app).run()

Next, we need to create the Scheduler.css file:

:root {
    height: 200px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center; 
}

This is just to put everything in the center of the screen.

Running the Taipy scheduler application

To run our application, we need to update our Nylas application. Head to the Hosted Authentication page on your dashboard, and click on Add a callback URI.

http://localhost:5000/login/nylas/authorized
Hosted authentication screen

Once that is done, we can type the following on the terminal window:

$ python3 Scheduler.py
Running the Taipy Scheduler

Checking the generated event

As we selected a spot and generated a meeting, why don’t we look at it? We just need to go to our mailbox or our calendar to find it:

The created event

What’s next?

Do you have any comments or feedback? Please use our forums 😎

Want to fetch the repo? Here you go scheduler_taipy 🥳

Learn more about Calendars in our documentation.

Don’t miss the action, join our LiveStream Coding with Nylas!

Related resources

How to build a CRM in 3 sprints with Nylas

What is a CRM? CRM stands for Customer Relationship Management, and it’s basically a way…

How to create an appointment scheduler in your React app

Learn how to create an appointment scheduler in your React app using Nylas Scheduler. Streamline bookings and UX with step-by-step guidance.

Beyond APIs: Designing elegant, smart Web Components

Dive into the world of smart Web Components for advanced API integration solutions. Design elegant, customizable elements to elevate user experiences.