Skip to content

Calendarium is a Flask web application for managing and tracking events. It supports a range of functionalities including event creation, updates, and deletions, a timeline view, batch importing, and API data access, all containerized with Docker.

License

Notifications You must be signed in to change notification settings

whustedt/calendarium

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Calendarium

This is a Flask-based web application designed to manage events and visualize them on a dynamic timeline. This application supports integration with Grafana for visual analytics and the Giphy API for enhanced user interaction.

Getting Started

To get the application running locally, you have several options:

Using Docker

docker-compose up --build

The app will be available at http://127.0.0.1:5001/.

Using a Development Container or Python Environment

Alternatively, you can set up a development container or any other Python environment. After setting up, start the application with the following command:

flask run --debug

For production, you would use Gunicorn as a WSGI server:

gunicorn -w 4 -b "127.0.0.1:5000" "app:create_app()"

Ensure your environment has all the necessary dependencies installed as specified in the requirements.txt file.

Environment Variables

To integrate with Giphy, create a .env file in the project root and add the following key:

GIPHY_API_TOKEN=<your_giphy_api_token>

Filling the App with Sample Data

To populate the application with sample data, run:

curl -X POST http://127.0.0.1:5000/batch-import -H "Content-Type: application/json" -d @testdata.json

Scheduled Tasks

Task Configuration

  • Purge Old Entries
    • Set to automatically execute at the start of each month.
  • Update Serial Entries
    • Scheduled to run at the start of every new year.

These tasks use the APScheduler, with the scheduler API enabled for enhanced interaction through HTTP endpoints. More details and the API can be accessed here: APScheduler API Documentation.

API Endpoints

Below are the available API endpoints with their respective usage:

  • Home

    • GET /
    • Returns the main page of the application.
  • Timeline

    • GET /timeline?timeline-height=<height>&font-family=<font>&font-scale=<scale>&categories=<category_names>&load-past-images=<load>
    • Displays a timeline of all entries. Allows optional timeline-height, font-family, font-scale, categories, and load-past-images query parameters to adjust the height of the timeline, set the font, apply a scale factor to the font size, filter entries by specified categories, and control the loading of images for past entries respectively.
      • Example: /timeline?timeline-height=100%&font-family=Arial&font-scale=1.5&categories=Cake,Birthday&load-past-images=false This would render a timeline with Arial font, increased by 1.5 times, showing only entries under 'Cake' and 'Birthday' categories, without loading images for past events.
  • Create Entry

    • POST /create
    • Creates a new entry. Requires form data including date, category, title, and description.
  • Update Entry

    • GET/POST /update/<int:id>
    • Retrieves an entry for editing or updates an entry if POST method is used.
  • Delete Entry

    • POST /delete/<int:id>
    • Deletes an entry by ID.
  • Toggle Entry Cancellation

    • POST /toggle_canceled/<int:id>
    • Toggles the cancellation status of an entry by ID. The route changes the canceled state of the entry to either True or False depending on its current state. A successful operation will redirect back to the main page, updating the entry's status in the view.
  • API Data Access

    • GET /api/data
    • Returns all entries in JSON format, including additional attributes such as date_formatted and index which help in sorting and formatting entries relative to the current date.
  • Export Data

    • GET /export-data
    • Exports all entries and associated images as a zip file.
  • Batch Import

    • POST /batch-import
    • Imports a batch of entries from a JSON file.
  • Update Serial Entries

    • POST /update-serial-entries
    • Updates all entries linked to categories that are set to repeat annually, adjusting their dates to the current year.
  • Purge Old Entries

    • POST /purge-old-entries
    • Deletes all entries where the date is in the past and the category is not marked as protected.

Category Management

  • View and Manage Categories

    • GET/POST /categories
    • Displays and allows management of categories including creation and update.
  • Update Category

    • POST /categories/update/<int:id>
    • Allows updating details for a specific category by ID.
  • Delete Category

    • POST /categories/delete/<int:id>
    • Deletes a category if it is not associated with any entries.

Database Schema

Below is the database schema visualized using a Mermaid diagram:

classDiagram
    class Category {
        +int id
        +string name : unique, not null
        +string symbol : not null
        +string color_hex : not null
        +bool repeat_annually : default=false, not null
        +bool display_celebration : default=false, not null
        +bool is_protected : default=false, not null
        +string last_updated_by : nullable [IP of last editor]
    }

    class Entry {
        +int id
        +string date : not null
        +int category_id : ForeignKey, not null
        +Category category : relationship
        +string title : not null
        +string description : nullable
        +string image_filename : nullable
        +string url : nullable
        +bool cancelled : default=false, not null
        +string last_updated_by : nullable [IP of last editor]
    }

    Category "1" o-- "*" Entry
Loading

Grafana Integration

This application supports integration with Grafana through a Simple JSON Datasource, enabling Grafana to pull data for visualization purposes. Here are the endpoints provided for Grafana:

Grafana Endpoint Descriptions

  • Test Connection (GET /grafana/)

    • Confirms the data source connection is functional.
  • Search (POST /grafana/search)

    • Returns a list of categories that can be queried (e.g., 'cake', 'birthday').
  • Query (POST /grafana/query)

    • Retrieves timeseries data based on specified categories.
  • Annotations (POST /grafana/annotations)

    • Delivers event annotations for graph overlays based on specific queries.
  • Tag Keys (POST /grafana/tag-keys)

    • Provides tag keys for Grafana's ad hoc filtering capabilities.
  • Tag Values (POST /grafana/tag-values)

    • Supplies values for the selected tag keys for further filtering.

Example Usage

Query Grafana for timeseries data in the 'cake' category using this curl command:

curl -X POST http://127.0.0.1:5000/grafana/query -H "Content-Type: application/json" -d '{"targets":[{"target": "Cake", "type": "timeserie"}]}'

This command will return timeseries data points for the 'cake' category if such data exists. Ensure the Grafana Simple JSON Datasource plugin is installed and properly configured to interact with these endpoints.

Giphy Integration

The Calendarium application features integration with the Giphy API to enhance the user interface with dynamic content. There are two different implementations of this integration, tailored to different deployment environments and security concerns.

Direct Backend Integration (Original Version)

In environments where the backend server has internet access, the application can directly interact with the Giphy API. This method involves the backend making API requests to Giphy and securely managing the API key via environment variables.

  • Endpoint: /search_gifs
  • Method: GET
  • Function: This endpoint takes a search query as a parameter, directly calls the Giphy API, and returns the GIF data. This keeps the API key secure and not exposed to the client-side.

Example usage:

curl http://127.0.0.1:5000/search_gifs?q=cats

This implementation is found in the JavaScript file search_gifs.js.

Proxied API Integration (New Version)

For environments where the backend does not have direct internet access, we employ a proxied approach. Here, the backend generates a URL with the API key, which is then used by the frontend to make the Giphy API call. This method ensures that the API key is not exposed in the client-side code.

  • Backend Endpoint: /get-giphy-url
  • Method: GET
  • Function: This endpoint constructs the request URL including the API key and returns it to the client. The client then uses this URL to fetch GIF data directly from Giphy.

Example usage:

curl http://127.0.0.1:5000/get-giphy-url?q=cats

This implementation is located in the JavaScript file search_gifs_proxied.js.

These methods are designed to accommodate different network security policies while maintaining functionality and protecting sensitive information.

Flickity License Information

This project uses Flickity, which is licensed under the GPLv3.

As such, modifications to the Flickity source code used in this project are documented in the repository. To comply with the GPLv3, all source code for this application is available under the same license. The full license text is included in the LICENSE file in this repository.

Icon Attribution

This project uses the icon "cracked glass" by Olena Panasovska from Noun Project licensed under CC BY 3.0. To meet the attribution requirements, this link points directly to the icon's detail page. Please refer to the Noun Project's guidelines for detailed information on how to properly attribute the creator in different formats and mediums.

Docker Image

Instead of Docker Hub, this project's Docker images are now built and pushed through GitHub Actions to the GitHub Container Registry.

About

Calendarium is a Flask web application for managing and tracking events. It supports a range of functionalities including event creation, updates, and deletions, a timeline view, batch importing, and API data access, all containerized with Docker.

Topics

Resources

License

Stars

Watchers

Forks

Packages