added cal project
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ nohup.out
|
||||
dm.out
|
||||
dm.err
|
||||
sample_task_file
|
||||
dmfnt
|
||||
|
||||
100
CLAUDE.md
Normal file
100
CLAUDE.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Deskmeter is a productivity tool that measures time spent across desktop workspaces. It consists of three main components:
|
||||
|
||||
- **dmcore**: Core tracking daemon (`dmapp/dmcore/main.py`) that monitors active workspace and task changes
|
||||
- **dmweb**: Flask web application (`dmapp/dmweb/`) for viewing productivity data
|
||||
- **dmfnt**: Angular frontend (`dmapp/dmfnt/`) for enhanced UI (in development)
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Components
|
||||
|
||||
**Task Management System**:
|
||||
- Task definitions stored in files, tracked via `dmapp/dmcore/task.py`
|
||||
- File modification time monitoring for automatic task switching
|
||||
- Hierarchical task organization under workspace paths (e.g., `work/default`, `work/dlt`)
|
||||
|
||||
**Workspace Tracking**:
|
||||
- Uses `wmctrl` to detect active X11 workspace (requires XORG, not Wayland)
|
||||
- Maps workspace indices to labels in `dmapp/dmcore/main.py:desktops`
|
||||
- Special handling for "work" desktops with automatic task enforcement
|
||||
|
||||
**Data Storage**:
|
||||
- MongoDB backend storing workspace switches with timestamps and durations
|
||||
- State persistence in `dmapp/dmcore/state.py` for current workspace/task tracking
|
||||
|
||||
### Web Interface Structure
|
||||
|
||||
**Flask Routes** (`dmapp/dmweb/dm.py`):
|
||||
- `/` - Today's productivity summary
|
||||
- `/day/<month>/<day>` - Single day view
|
||||
- `/calendar` - Monthly calendar view via `dmapp/dmweb/dmcal.py`
|
||||
- `/totals` - All-time statistics
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Python Backend
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Start MongoDB service
|
||||
sudo systemctl start mongod.service
|
||||
|
||||
# Run core tracking daemon
|
||||
cd dmapp/dmcore
|
||||
python3 main.py
|
||||
|
||||
# Run Flask web server
|
||||
cd dmapp/dmweb
|
||||
python3 run.py
|
||||
|
||||
# Run tests
|
||||
cd dmapp/tests
|
||||
python3 test_dmapp.py
|
||||
```
|
||||
|
||||
### Angular Frontend
|
||||
|
||||
```bash
|
||||
cd dmapp/dmfnt
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Development server
|
||||
npm run start
|
||||
|
||||
# Build for production
|
||||
npm run build
|
||||
|
||||
# Run tests
|
||||
npm run test
|
||||
```
|
||||
|
||||
### System Setup
|
||||
|
||||
The application requires:
|
||||
- MongoDB running locally
|
||||
- wmctrl installed (`apt install wmctrl`)
|
||||
- X11 desktop environment (not Wayland)
|
||||
- Python virtual environment recommended
|
||||
|
||||
## Key Configuration
|
||||
|
||||
**Workspace Labels**: Edit `desktops` tuple in `dmapp/dmcore/main.py:12`
|
||||
**Work Desktop Mapping**: Configure `work_desktops` dict in `dmapp/dmcore/main.py:13`
|
||||
**Timezone**: Set in `dmapp/dmcore/main.py:19` using zoneinfo
|
||||
|
||||
## Development Notes
|
||||
|
||||
- The system enforces task constraints within work desktops - switching to a non-work task automatically reverts to the designated work task
|
||||
- Task files are monitored for changes to enable automatic context switching
|
||||
- Web interface runs on port 10000 by default
|
||||
- Core daemon sleeps for 2 seconds between workspace checks
|
||||
5
dmapp/.env
Normal file
5
dmapp/.env
Normal file
@@ -0,0 +1,5 @@
|
||||
// dmcore
|
||||
task_file = "/home/mariano/LETRAS/adm/task/main"
|
||||
desktops = ("Plan", "Think", "Work", "Other", "Away", "Work", "Work", "Work")
|
||||
work_desktops = {2: "default", 5: "dlt", 6: "vhs", 7: "cal"}
|
||||
unlabeled = "Away"
|
||||
0
dmapp/__init__.py
Normal file
0
dmapp/__init__.py
Normal file
@@ -1,9 +1,9 @@
|
||||
sudo systemctl start mongod.service
|
||||
. /home/mariano/wdir/venv/dm/bin/activate
|
||||
cd /home/mariano/wdir/def/deskmeter
|
||||
nohup python3 dmmain.py >dm.out 2>dm.err &
|
||||
cd /home/mariano/wdir/def/deskmeter/dmapp/dmcore
|
||||
nohup python3 main.py >dm.out 2>dm.err &
|
||||
|
||||
cd /home/mariano/wdir/def/deskmeter/dmapp
|
||||
cd /home/mariano/wdir/def/deskmeter/dmapp/dmweb
|
||||
nohup python3 run.py >dm.out 2>dm.err &
|
||||
|
||||
cd ~
|
||||
|
||||
@@ -9,8 +9,8 @@ import task
|
||||
from config import logger, switches
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
desktops = ("Plan", "Think", "Work", "Other", "Away", "Work", "Work")
|
||||
work_desktops = {2: "default", 5: "dlt", 6: "vhs"}
|
||||
desktops = ("Plan", "Think", "Work", "Other", "Away", "Work", "Work", "Work")
|
||||
work_desktops = {2: "default", 5: "dlt", 6: "vhs", 7: "cal"}
|
||||
|
||||
unlabeled = "Away"
|
||||
|
||||
@@ -60,7 +60,6 @@ while True:
|
||||
current_mtime = state.retrieve("current").get("filetime")
|
||||
file_mtime = task.get_file_mtime(None)
|
||||
|
||||
logger.debug(f"current_mtime: {current_mtime}, file_mtime:{file_mtime}")
|
||||
# First handle file changes
|
||||
if current_mtime != file_mtime:
|
||||
task_id = task.read_and_extract(None)
|
||||
@@ -86,9 +85,6 @@ while True:
|
||||
f"work/{work_desktops[current_workspace]}"
|
||||
)
|
||||
work_task_ids = {t["task_id"] for t in workspace_tasks if "task_id" in t}
|
||||
logger.debug(
|
||||
f"work_task_ids:{work_task_ids}, current_work_task: {current_work_task},current_task: {current_task}"
|
||||
)
|
||||
|
||||
# if current_task in work_task_ids and current_task != current_work_task:
|
||||
if current_task not in work_task_ids:
|
||||
@@ -97,6 +93,7 @@ while True:
|
||||
current_task = current_work_task
|
||||
state.save("current", task=current_task)
|
||||
task.db_to_file_as_is(None)
|
||||
|
||||
elif current_task != current_work_task:
|
||||
# Update work state when switching to a different valid task
|
||||
state.update_work_state(work_desktops[current_workspace], current_task)
|
||||
|
||||
@@ -7,7 +7,7 @@ import state
|
||||
from bson import ObjectId
|
||||
from config import logger, tasks
|
||||
|
||||
task_file = "/home/mariano/wdir/def/deskmeter/dmapp/dmcore/sample_task_file"
|
||||
task_file = "/home/mariano/LETRAS/adm/task/main"
|
||||
|
||||
|
||||
def parse_line(line: str) -> tuple[Optional[str], Optional[str]]:
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
from flask import Flask
|
||||
from dmweb import dm, dmcal
|
||||
|
||||
from . import dm, dmcal
|
||||
|
||||
|
||||
def create_app():
|
||||
|
||||
app = Flask("deskmeter")
|
||||
|
||||
app.debug = True
|
||||
app.register_blueprint(dm.dmbp)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ def index(task=None):
|
||||
end = datetime.today().replace(hour=23, minute=59, second=59, tzinfo=timezone)
|
||||
|
||||
rows = get_period_totals(start, end, task)
|
||||
print(rows)
|
||||
|
||||
return render_template("main.html", rows=rows)
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@ import calendar
|
||||
from datetime import datetime
|
||||
from pprint import pprint
|
||||
|
||||
# import pytz
|
||||
from dmweb.dm import dmbp
|
||||
from flask import Blueprint, render_template
|
||||
|
||||
# import pytz
|
||||
from .dm import dmbp
|
||||
from .get_period_times import (
|
||||
get_period_totals,
|
||||
read_and_extract,
|
||||
@@ -77,6 +77,8 @@ class DMHTMLCalendar(calendar.HTMLCalendar):
|
||||
|
||||
rows = get_period_totals(start, end, self.task)
|
||||
|
||||
print(rows)
|
||||
|
||||
returnstr = "<table class='totaltable'>"
|
||||
for row in rows:
|
||||
returnstr += "<tr><td>{}</td><td>{}</td></tr>".format(
|
||||
|
||||
@@ -178,8 +178,6 @@ def get_period_totals(start, end, task=None):
|
||||
|
||||
aux_results = list(switches.aggregate(pipeline_before_after))
|
||||
|
||||
print(aux_results)
|
||||
|
||||
bfirst = aux_results[0]["before_first"]
|
||||
|
||||
if bfirst:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from dmweb import create_app
|
||||
|
||||
app = create_app()
|
||||
Reference in New Issue
Block a user