How to build a daily planner using NiceGUI

6 min read

Waking up in the morning, we first check our phone or laptop to see what upcoming meetings we have and how many new emails we receive. Wouldn’t it be nice to have both in the same place? We can create a daily planner to do exactly that!

In order to build our daily planner, we will use NiceGUI, a Python-based Web-UI Framework.

Is your system ready?

Continue with the blog if you already have the Nylas Python SDK installed and your Python environment configured. Also, you can check the Nylas Quickstart Guides.

Otherwise, I recommend reading the post how to send emails with the Nylas Python SDK, where the basic setup is clearly explained.

What are we going to talk about?

  • What our NiceGUI daily planner will look like
  • Installing the required packages
  • Coding our daily planner
  • Running our NiceGUI daily planner

What our application will look like

When we run our daily planner, we will be presented with a calendar, all the events for the day, and the newest five unread emails, provided that we have new emails. We can also, of course, select any other day from the calendar.

Here is what the UI looks like:

Daily Planner with NiceGUI

Installing the required packages

Besides the Nylas and Dotenv packages, we need to install the NiceGUI package:

$ pip3 install nicegui

That’s it. Nothing too complex or complicated.

Coding our daily planner

And it’s coding time. We’re going to create a file called nicegui_planner.py:

Let’s break up the code:

Dependency Setup

# Import your dependencies
from dotenv import load_dotenv
import os
from nylas import APIClient  # type: ignore
from nicegui import ui
from datetime import date
from datetime import datetime
from dataclasses import dataclass
from typing import List

# Load your env variables
load_dotenv()

# Initialize an instance of the Nylas SDK using the client credentials
nylas = APIClient(
    os.environ.get("CLIENT_ID"),
    os.environ.get("CLIENT_SECRET"),
    os.environ.get("ACCESS_TOKEN"),
)

@dataclass # Class decorator
class EventItems:
    event_name: str

# To hold events
events: List[EventItems] = [

]

@dataclass # Class decorator
class EmailItems:
    email_name: str

# To hold emails
emails: List[EmailItems] = [

]

Nylas integration

# Get list of events
def get_events(current_date) -> None:
    # Get today's date as Year, month, day
    today_date = datetime.strptime(current_date, '%Y-%m-%d').date() 
    # Today’s date at 12:00:00 am
    AFTER = int(datetime(today_date.year, today_date.month, today_date.day, 0, 0, 0).strftime('%s'))
    # Today’s date at 11:59:59 pm 
    BEFORE = int(datetime(today_date.year, today_date.month,today_date.day, 23, 59, 59).strftime('%s'))
    # Get all events in the specified range
    events = nylas.events.where(calendar_id=os.environ.get("CALENDAR_ID"),  starts_after = AFTER, ends_before = BEFORE)
    # Auxiliary variables
    event_info = ""
    counter = 0
    # Loop events
    for event in events:
        counter += 1
        # Does the event have a start and end time?
        if "start_time" in event.when:
			# Grab from and end time, as well as the event title
            event_info = f"From:  {datetime.fromtimestamp(event.when['start_time']).strftime('%H:%M:%S')} \
                                 To: {datetime.fromtimestamp(event.when['end_time']).strftime('%H:%M:%S')} \
                                 | {event.title}"
            add(event_info, "event")
        # Does the event last all day?    
        else:
			# As an all day event, simply grab the title 
            add(f"All day event | {event.title}")
    # No events?
    if counter == 0:
        add("No events today", "event")		

# Get list of emails
def get_emails(current_date) -> None:
    # Get today's date as Year, month, day
    today_date = datetime.strptime(current_date, '%Y-%m-%d').date() 
    # Today’s date at 12:00:00 am
    AFTER = int(datetime(today_date.year, today_date.month, today_date.day, 0, 0, 0).strftime('%s'))
    # Today’s date at 11:59:59 pm 
    BEFORE = int(datetime(today_date.year, today_date.month,today_date.day, 23, 59, 59).strftime('%s'))	
    # Get all emails in the specified range
    messages = nylas.messages.where(in_ = "inbox", unread = "true", limit = 5, received_after = AFTER, received_before = BEFORE)
    # Auxiliary variables
    email_info = ""
    counter = 0
    # Loop emails    
    for message in messages:
        counter += 1
        # Grab the time, who's sending the email and the title of the email
        email_info = f"Time: {datetime.fromtimestamp(message.date).strftime('%H:%M:%S')} \
                             | From: {message.from_[0]['name']} | Title: {message.subject}"
        add(email_info, "email")
    # No emails?
    if counter == 0:
        add("No new emails today", "email")

# Function to add events and emails		
def add(name: str, type_ : str) -> None:
    # If it's an event, add it to the events list
    if type_ == "event":
        events.append(EventItems(name))
        render_events_list.refresh()
    # If it's an email, add it to the email list
    else:
        emails.append(EmailItems(name))
        render_emails_list.refresh()         

# Clear the list of events
def clear_events() -> None:
    events.clear()

# Clear the list of emails
def clear_emails() -> None:
    emails.clear()

# When we click on the calendar 
# to select a new date
def handle_input(e):
    # We pass the selected date
    current_date = e.value
    # If for some reason, there's no date
    # grab the current date
    if current_date is None:
        date.today()
        current_date = str(date.today())
    clear_events()
    # Get events for the selected date
    get_events(current_date)
    clear_emails()
    # Get emails for the selected date
    get_emails(current_date)

NiceGUI UI setup

# Decorator to refresh the events list
@ui.refreshable
def render_events_list():
    # Title using Tailwind CSS
    ui.label('Events').tailwind.font_weight('black').font_size('4xl').text_color('blue-700')
    # Loop events
    for event in events:
        # Put events one after the other
        with ui.row().classes('items-center'):
            # Detail of event
            ui.label(event.event_name).tailwind.font_weight('semibold').font_size('lg')

# Decorator to refresh the emails list            
@ui.refreshable
def render_emails_list():
    # Title using Tailwind CSS
    ui.label('Emails').tailwind.font_weight('black').font_size('4xl').text_color('blue-700')
    # Loop emails
    for email in emails:
       # Put events one after the other
        with ui.row().classes('items-center'):
            # Detail of event
            ui.label(email.email_name).tailwind.font_weight('semibold').font_size('lg')

# Main layout with everything centered
with ui.column().classes('w-full items-center'):
    # Get today's date
    today = date.today()
    current_date = str(date.today())
    # Clear all events and emails	
    clear_events()
    clear_emails()
    # Set application title
    ui.label('Daily Planner').tailwind.font_weight('black').font_size('6xl').text_color('blue-700')
    # Create the calendar widget
    ui.date(value=today, on_change=handle_input)
    # Show all events
    get_events(current_date)
    render_events_list()
    # Show all emails
    get_emails(current_date)
    render_emails_list()

# Run our application
ui.run(title = 'NiceGUI Planner')

Running our NiceGUI daily planner

In order to run our application, we just need to type the following on the terminal window:

$ python nicegui_planner.py

Our application will be running on port 8080 of localhost and on 10.0.0.161. We don’t even need to open our favourite browser, as it will be open automagically.

To learn more about our Email APIs, please go to our documentation Email API Overview.

You can sign up Nylas for free and start building!

Don’t miss the action. Join our LiveStream Coding with Nylas:

Related resources

How to customize the Nylas Scheduler workflow with custom events

We’re excited to announce the launch of the Nylas Scheduler v3! Efficient scheduling is essential…

How to block time slots in Outlook and Google calendar with Nylas Calendar API

Key Takeaways Managing calendar availability is essential for professionals, teams, and businesses to stay organized…

How to Solve Webhook Integration Challenges with PubSub Notification Channel

Key Takeaways This article addresses the challenges of webhook integration and introduces the PubSub Notification…