LEF laboratory project tracker

Quick start in RStudio

  1. Extract this folder. Keep app.R and the supplied projects.rds together.
  2. Install the packages once:
install.packages(c("shiny", "DT", "digest", "filelock", "googledrive"))
  1. Open this folder as your working directory and run:
shiny::runApp()

The default is local mode. It reads the original projects.rds and creates data/lef-projects-v2.rds on the first successful save. The original file is never overwritten. Subsequent launches use the version 2 file.

Enter your name in the sidebar before saving. This is an attribution field, not an authenticated identity. Use your hosting platform’s access controls for a private lab deployment.

Everyday use

  • Overview: ongoing projects and check-in needs. Counts follow sidebar filters.
  • Board: click a card to edit any project. Stages are current activities.
  • Projects: searchable/sortable table; select a row to open details.
  • Lab meeting: discussion requests, blocked projects, and deadlines within 14 days (including overdue). Export an agenda as CSV.
  • Archive: open a project to restore it. Archived projects retain all history.
  • Details editor: set lead, supervisor, collaborators, theme, stage, status, health, summary, next action, action owner, deadline, blockers, and links.
  • Add a progress note to record a check-in even if the main activity is unchanged.
  • Refresh to see colleagues’ latest saved changes. Unsaved work is not autosaved.
  • If a stale-save conflict appears, copy your unsaved notes, close the form, refresh, and reapply the changes. The app does not silently merge edits.
  • The archive confirmation discards unsaved form edits; save those first.
  • Download full backup preserves all fields and history. CSV exports include project fields only, not history; exports neutralise potential spreadsheet formulas.
  • Sidebar filters affect all views, including Archive. Reset filters to find archived projects that do not match the current filters.

Migration of the original projects

Project names and original stage dates are preserved. People are not guessed from underscore-separated titles. Lead, supervisor, and collaborators are blank until reviewed. Creation and last-update dates remain unknown until appropriate; legacy projects are therefore initially flagged for a check-in, not as overdue.

The old stage codes look like completed milestones. The initial mapping is:

Original value New current activity Status
initiated Planning Active
data_collected Laboratory analyses Active
lab_analyses_done Data analysis Active
data_processing_done Writing Active
paper_submitted Submitted / revision Active
paper_published Published Completed
project_terminated Planning (placeholder) Discontinued, archived

Review these mappings for each project: old UI labels were ambiguous. Projects without laboratory work can move directly to data analysis; old analysis/writing projects may already be further ahead. The original code is retained in legacy_stage, visible in Details. The original date is retained in stage_changed. A discontinued project’s earlier scientific stage is unknown.

Stage, health, status, and archive are independent. For example, an on-hold project can remain in Writing. Moving to Published does not automatically change status; set Completed when appropriate. There is no permanent-delete UI.

Google Drive mode

This retains the original Drive workflow but uses an exact filename and updates an existing file instead of deleting and re-uploading it.

Set environment variables before launching the app (or in a private .Renviron):

LEF_STORAGE=drive
LEF_DRIVE_FOLDER_ID=YOUR_EXISTING_FOLDER_ID
GOOGLE_APPLICATION_CREDENTIALS=/absolute/private/path/service-account.json
LEF_DATA_DIR=/absolute/writable/path/lef-cache

The service account needs access to the folder and permission to create/update files there. Shared Drive or ownership/quota restrictions can affect whether a service account can create the version 2 file. Resolve these in the Google Workspace configuration if the first save fails. Do not make the folder public.

The app first looks for lef-projects-v2.rds. If it does not exist, it reads projects.rds in that exact folder and creates the v2 file on first save. It never modifies the old file. Duplicate filenames cause an explicit error. The supplied credential JSON is deliberately not included in this package. Supply credentials privately to the host; do not commit them to a public repo or place them in a web-served directory.

Use ONE application instance with Drive mode. A file lock serialises saves on the same host/shared filesystem, and content checks reject stale sessions. These are NOT a distributed transaction: two independent instances or external Drive writers could race. For multi-instance hosting, use a transactional hosted PostgreSQL database in a later version. A local file lock does not fix that case.

If a Drive save reports a network failure, refresh before retrying: the remote write might have succeeded. The error does not imply the data was not written.

Hosting and persistence

For a university server with durable disk, local mode is simple and supports multiple sessions using the same data directory. Set:

LEF_STORAGE=local
LEF_DATA_DIR=/durable/server/path/lef-projects
LEF_LEGACY_FILE=/path/to/original/projects.rds

Local atomic replacement is intended for POSIX/macOS/Linux filesystems. On Windows, replacement of an existing file may fail safely; use a Linux server or Drive mode if this occurs. Never use local mode as durable storage on a host that discards application files on restart/redeployment. For shinyapps.io, configure Drive persistence, private credentials, and single-instance hosting; do not assume local backups survive restarts. Hosting/access configuration must be verified in your own account before inviting lab members.

Backups and restoration

Each successful save attempt first writes a timestamped snapshot of the previous state under LEF_DATA_DIR/backups/. A failed save may also leave a backup. There is no automatic pruning. Keep that directory on durable disk and include it in your institutional backup policy. In Drive mode, those local snapshots are NOT uploaded to Drive. Download full backups periodically for an independent copy.

To restore a trusted version 2 RDS backup:

  1. Stop the app / prevent other edits.
  2. Preserve a copy of the current version 2 file.
  3. In local mode, replace LEF_DATA_DIR/lef-projects-v2.rds with the backup. In Drive mode, update the contents of the exact lef-projects-v2.rds file.
  4. Restart the app and verify a few records.

Only use trusted RDS files. The interface does not accept arbitrary uploads.

Implementation

One app.R file; no database installation required. Version 2 stores a list with schema_version, projects, and history. Project IDs are stable; duplicate names are allowed and do not affect record identity. History records field changes, notes, timestamps, and the name entered by the editor. Text is escaped in cards/tables and links are restricted to HTTP(S).

Run the included checks from this folder with Rscript tests.R. These cover legacy migration, local persistence, stale-save rejection, and key server workflows. Google Drive authentication and deployment need a live test in your environment.

API references: https://googledrive.tidyverse.org/reference/drive_update.html and https://rstudio.github.io/DT/shiny.html