Skip to content

Repository files navigation

OpenProject - Time Saver

Log hours in seconds, not minutes. Quietly tracks your OpenProject activity, so everything you need is one click away at the end.

A Chrome extension that runs in the background while you work in OpenProject, noting which work packages you visit, how long you spend on them, and whether you comment or make changes. When it's time to log hours, open the popup and your day is already laid out -- tracked activity, today's meetings, your assignments, and your favorites, all in one place. Adjust the hours, add a note, hit save.

Features

  • Passive activity tracking -- Content scripts monitor which work packages and documents you visit, measure foreground time, and detect comments and updates. No manual input required.
  • Daily timesheet popup -- View and manage time entries for any date. Adjust hours per entry (+/- 15 min or +/- 1 h), add comments, and save individually or in batch.
  • Calendar with hour bars -- Navigate dates with a monthly calendar that shows logged hours per day as visual bars and highlights weeks that exceed a configurable threshold.
  • Sidebar panels -- Six categories of context at your fingertips:
    • Favorites -- Pinned work packages for quick access
    • Recent -- Work packages you've recently interacted with
    • Assigned to me -- Your current assignments from OpenProject
    • Meetings -- Today's meetings, with the ability to link each meeting to a work package
    • Activity -- Live feed of tracked page visits for the selected date, grouped by hour
    • Notes -- Per-day notes and todos stored locally
  • Work package search -- Search by text with type-prefix filtering (e.g. filter by Task, Bug, Feature).
  • Out-of-office tracking -- Mark days as vacation, sick leave, or public holiday (full or half day). OOO hours are reflected in the date bar and calendar.
  • Draft persistence -- Unsaved time entries are stored as drafts and survive popup close / browser restart.
  • Meeting-WP linking -- Associate a meeting with a work package so you can log time against it with one click.

Installation

  1. Clone or download this repository.
  2. Open Chrome and navigate to chrome://extensions.
  3. Enable Developer mode (toggle in the top-right corner).
  4. Click Load unpacked and select the project folder.
  5. The extension icon appears in the toolbar.

Setup

On first launch the settings panel opens automatically.

  1. Enter your Host URL (e.g. https://community.openproject.org).
  2. Enter your API Key. You can generate one in your OpenProject account under My account > Access tokens.
  3. Click Test Connection to verify. Once successful, the popup loads your time entries.

Settings

Setting Tab Description
Host URL OpenProject access Base URL of your OpenProject instance
API Key OpenProject access Personal API token for authentication
Weekly Hours Threshold Advanced settings Weeks meeting or exceeding this value are highlighted in the calendar (default: 40)

Architecture

File structure

├── manifest.json              MV3 Chrome extension manifest
├── background.js              Service worker -- aggregates activity data, prunes old entries daily
├── content-script.js          Isolated-world content script -- detects OP pages, sends heartbeats, tracks interactions
├── content-script-main.js     MAIN-world content script -- intercepts fetch/XHR/pushState to detect writes and SPA navigations
├── openproject-api.js         OpenProject API v3 client (time entries, work packages, meetings, search, types, projects)
├── storage.js                 Storage modules: Settings (sync), ActivityStorage, NotesStorage, MeetingsStorage (local)
├── utils.js                   Shared utilities
├── popup.html                 Popup shell -- loads all scripts and defines the layout skeleton
├── popup.js                   Popup orchestrator -- initializes components, wires callbacks, manages API client lifecycle
├── popup.css                  All popup styles
├── icons/                     Extension icons (16, 32, 48, 128)
└── components/
    ├── top-bar.js             Header bar with settings button
    ├── settings.js            Full-screen settings overlay with tabbed panels
    ├── date-bar.js            Date navigation (prev/next, date display, total hours, OOO indicator)
    ├── calendar-popup.js      Monthly calendar dropdown with per-day hour bars and weekly totals
    ├── time-entries.js        Time entry cards with hour adjustment, comments, WP reassignment, batch save
    ├── sidebar.js             Icon rail + flyout panels (Favorites, Recent, Assigned, Meetings, Activity, Notes)
    ├── ooo-manager.js         OOO data storage and retrieval (vacation, sick, public holiday)
    └── ooo-popup.js           OOO entry creation/editing UI

Data flow

flowchart LR
    subgraph browser [Browser]
        CS_MAIN["content-script-main.js\n(MAIN world)"]
        CS["content-script.js\n(isolated world)"]
        BG["background.js\n(service worker)"]
    end

    subgraph storage [Chrome Storage]
        LOCAL["chrome.storage.local\n(activities, notes, meetings cache, drafts)"]
        SYNC["chrome.storage.sync\n(settings, favorites, OOO)"]
    end

    subgraph popup [Popup]
        POP["popup.js + components"]
    end

    OP["OpenProject API"]

    CS_MAIN -->|"CustomEvents\n(writes, navigations)"| CS
    CS -->|"chrome.runtime\nmessages"| BG
    BG -->|"read/write"| LOCAL
    POP -->|"read/write"| LOCAL
    POP -->|"read/write"| SYNC
    POP -->|"API v3 calls"| OP
Loading

Content scripts run on every page. When the URL matches the configured OpenProject host, the isolated-world script identifies work-package and document pages, sends a pageVisit message to the background, and starts a 15-second heartbeat that increments foreground time. The MAIN-world script intercepts fetch, XMLHttpRequest, and history.pushState/replaceState to detect write operations (comments, updates) and SPA navigations, forwarding them as DOM events to the isolated-world script.

Background service worker receives messages and aggregates activity into chrome.storage.local keyed by date (YYYY-MM-DD). Entries older than 30 days are pruned on startup and via a daily alarm.

Popup reads time entries and work-package data from the OpenProject API, and reads activity, notes, and draft data from local storage. All UI state flows through the component modules wired together by popup.js.

Permissions

Permission Reason
storage Persist settings (sync) and activity/notes/cache data (local)
alarms Schedule daily cleanup of old activity data
notifications Reserved for future reminder notifications
tabs Access tab URLs for activity context
windows Open OpenProject links in popup windows so the extension popup stays open
host_permissions: *://*/* Content scripts need to run on the OpenProject instance (URL is user-configured, so the broad pattern is required); API calls go directly to the host

About

A Chrome extension that helps you save time logging your time entries

Resources

Stars

0 stars

Watchers

0 watching

Forks

Used by

Contributors

Languages