Complete the repo.

This commit is contained in:
Oleksandr Kozachuk 2025-06-08 13:49:38 +02:00
parent 94ea328614
commit f077bf1f0f
3 changed files with 371 additions and 144 deletions

169
.gitignore vendored
View File

@ -1,170 +1,55 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
# Byte-compiled files
**pycache**/
*.py[cod]
*$py.class
# C extensions
*.so
# Virtual environments
.env/
.venv/
env/
venv/
# Distribution
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
# Python coverage
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
.nox/
# Translations
*.mo
*.pot
# Logs
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# IDEs
# Scrapy stuff:
.scrapy
.vscode/
.idea/
# Sphinx documentation
docs/_build/
# macOS
# PyBuilder
.pybuilder/
target/
.DS_Store
# Jupyter Notebook
.ipynb_checkpoints
# Linux
# IPython
profile_default/
ipython_config.py
*~
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Data files and locks
data/
*.json
*.lock

343
README.md
View File

@ -1,3 +1,342 @@
# TourPlanner
# Tour Voting App
Tour Planner is a lightweight FastAPI-based service that lets you create “tours,” propose ideas for each tour, and vote on those ideas. It stores each tour as a JSON file in a configurable data directory (with filelevel locking for safe concurrent access), and ships with a minimal static HTML/JavaScript frontend along with helper scripts for local development or deployment under Supervisor.
Tour Voting App is a full-stack web application for planning tours, proposing ideas, and voting on those ideas. It consists of:
* **Backend API** built with FastAPI
* **Data persistence** using per-tour JSON files in a configurable directory, with concurrency safety via file locks
* **Frontend**: Single-page HTML/JavaScript application that consumes the API
* **Helper scripts** for local development or Supervisor-based deployment
## Table of Contents
1. Features
2. Tech Stack
3. Prerequisites
4. Installation
5. Configuration
6. Development
7. Running in Production
8. Frontend Usage
9. API Reference
* Models
* Endpoints
10. Directory Structure
11. Contributing
12. License
## Features
* Create and manage tours with metadata (name, start/end dates, description)
* Add multiple ideas per tour, each with its own name, description, and optional time window
* Vote on ideas by recording unique voter names
* No external database: JSON filebased persistence
* Concurrency-safe via file locking
* Minimal static HTML/JavaScript frontend for user interaction
* Helper scripts for local development or Supervisor deployment
## Tech Stack
* **Backend**: Python 3.10+, FastAPI, Uvicorn, Pydantic, filelock
* **Frontend**: HTML, CSS, JavaScript (Fetch API)
* **Process Control (optional)**: Supervisor
* **Data storage**: JSON files, one per tour
## Prerequisites
* Python 3.10 or higher
* pip (Python package installer)
* (Optional) Supervisor for process management
## Installation
1. **Clone the repository**
git clone [https://github.com/your-organization/tour-voting-app.git](https://github.com/your-organization/tour-voting-app.git)
cd tour-voting-app
2. **Create virtual environment and install dependencies**
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
If `requirements.txt` is not provided, install directly:
pip install fastapi uvicorn pydantic filelock
## Configuration
Configure via environment variables or command-line flags:
* **DATA\_DIR**: directory to store tour JSON files (default: `./data`)
* **HOST**: address to bind the API (default: `0.0.0.0`)
* **PORT**: port for the API (default: `8000`)
Example using environment variables:
```
export DATA_DIR=./data
export HOST=0.0.0.0
export PORT=8000
```
Or via flags:
```
python server.py --data-dir ./data --host 0.0.0.0 --port 8000
```
## Development
1. Activate your virtual environment.
2. Start the server in reload mode:
```
uvicorn server:app --reload --host 0.0.0.0 --port 8000
```
3. Open `index.html` in your browser (or serve it via a local HTTP server to avoid CORS issues).
## Running in Production
Use the provided `service.sh` script and Supervisor config:
**service.sh**
```bash
#!/usr/bin/env bash
cd /path/to/tour-voting-app || exit 1
exec uvicorn server:app \
--host 0.0.0.0 \
--port 3002 \
--loop uvloop \
--workers 2 \
--access-log \
--log-level info
```
**tour.ini** (Supervisor)
```ini
[program:tour_voting_app]
command=/path/to/service.sh
directory=/path/to/tour-voting-app
autostart=true
autorestart=true
stderr_logfile=/var/log/tour_voting_app.err.log
stdout_logfile=/var/log/tour_voting_app.out.log
```
## Frontend Usage
The frontend is a single `index.html` file that interacts with the API. By default, `API_URL` is set to `http://localhost:8000/tour/v1`. To point it at a remote server, edit the `API_URL` constant near the top of `index.html`.
## API Reference
Base path: `/tour/v1`
### Models
**Tour**
```json
{
"id": "string",
"name": "string",
"description": "string",
"startDate": "ISO-8601 timestamp",
"endDate": "ISO-8601 timestamp",
"createdAt": "ISO-8601 timestamp",
"ideas": [ Idea ]
}
```
**Idea**
```json
{
"id": "string",
"name": "string",
"description": "string",
"startTime": "ISO-8601 timestamp | null",
"endTime": "ISO-8601 timestamp | null",
"voters": [ "string" ]
}
```
### Endpoints
#### 1. List Tours
* **Method**: GET
* **URL**: `/tours`
* **Response**: `200 OK`
```json
[ { Tour }, ... ]
```
#### 2. Create a Tour
* **Method**: POST
* **URL**: `/tours`
* **Request Body**:
```json
{
"name": "Europe Explorer",
"description": "A tour across Europe",
"startDate": "2025-07-01T00:00:00Z",
"endDate": "2025-07-15T00:00:00Z"
}
```
* **Response**: `201 Created`
```json
{ Tour }
```
#### 3. Get Tour Details
* **Method**: GET
* **URL**: `/tours/{tour_id}`
* **Path Parameters**:
* `tour_id` (string): ID of the tour
* **Response**: `200 OK`
```json
{ Tour }
```
* **Error**: `404 Not Found` if tour does not exist.
#### 4. Add an Idea to a Tour
* **Method**: POST
* **URL**: `/tours/{tour_id}/ideas`
* **Path Parameters**:
* `tour_id` (string): ID of the tour
* **Request Body**:
```json
{
"name": "Visit the Louvre",
"description": "Guided museum tour",
"startTime": "2025-07-03T10:00:00Z",
"endTime": "2025-07-03T14:00:00Z"
}
```
* **Response**: `201 Created`
```json
{ Idea }
```
* **Error**: `404 Not Found` if tour does not exist.
#### 5. Vote for an Idea
* **Method**: POST
* **URL**: `/tours/{tour_id}/ideas/{idea_id}/vote`
* **Path Parameters**:
* `tour_id` (string): ID of the tour
* `idea_id` (string): ID of the idea
* **Request Body**:
```json
{ "voterName": "alice@example.com" }
```
* **Response**: `200 OK`
```json
{ Idea } // Updated idea with new voter
```
* **Errors**:
* `404 Not Found` if tour or idea does not exist.
* `400 Bad Request` if voter name is missing or already voted.
## Directory Structure
```
tour-voting-app/
├── server.py # FastAPI application
├── index.html # Static frontend
├── service.sh # Startup helper script
├── tour.ini # Supervisor config
├── data/ # JSON files for tours (runtime)
├── requirements.txt # Python dependencies (optional)
└── README.md # Project documentation
```
## Contributing
1. Fork the repository.
2. Create a feature branch:
git checkout -b feature/my-feature
3. Commit your changes:
git commit -m "Add my feature"
4. Push to your branch:
git push origin feature/my-feature
5. Open a pull request.
## License
This project is licensed under the WTFPL License.
---
.gitignore
# Byte-compiled files
**pycache**/
\*.py\[cod]
\*\$py.class
# Virtual environments
.env/
.venv/
env/
venv/
# Distribution
build/
dist/
\*.egg-info/
\*.egg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Python coverage
htmlcov/
.tox/
.coverage
.pytest\_cache/
.nox/
# Logs
\*.log
# IDEs
.vscode/
.idea/
# macOS
.DS\_Store
# Linux
\*\~
# Data files and locks
data/
\*.json
\*.lock

3
tour.ini Normal file
View File

@ -0,0 +1,3 @@
[program:tour]
command=/home/kaizen/repos/tourplanner/service.sh
startsecs=60