---
title: "Collaborative Report Management with `tm_report_manager`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Collaborative Report Management with `tm_report_manager`}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = FALSE
)
```

This vignette demonstrates how to add collaborative report management to a `teal`
application using the `tm_report_manager` module from `uteals`.

## Overview

The `tm_report_manager` module extends `teal.reporter` with persistent, multi-user
report management. It allows users to:

- Save and load reports across sessions
- Collaborate on shared reports with file-based locking
- Auto-save report changes
- Rebuild reports with updated data
- Merge multiple reports into one

## Library Calls

```{r setup}
library(uteals)
library(teal)
library(teal.data)
```

## Quick Start

Add `tm_report_manager()` to your `teal::modules()` call:

```{r}
app <- teal::init(
  data = teal.data::teal_data(IRIS = iris),
  modules = teal::modules(
    teal::example_module(),
    tm_report_manager()
  )
)

if (interactive()) {
  shinyApp(app$ui, app$server)
}
```

Reports are stored in a `reports/` folder relative to the working directory by default.

## Configuration

`tm_report_manager()` accepts two arguments:

| Argument | Default | Description |
|---|---|---|
| `reports_path` | `"reports"` | Absolute or relative path where reports are stored |
| `auto_save` | `TRUE` | Whether to auto-save the active report on every card change |

```{r}
tm_report_manager(
  reports_path = "/shared/network/drive/reports",
  auto_save = TRUE
)
```

Use an absolute path pointing to a shared network location to enable multi-user
collaboration.

## How It Works

### Creating a Report

When a user adds the first card to the `teal.reporter` previewer, a modal dialog
prompts them to name the new report. The report is then saved to `reports_path`
and locked for that user.

A report directory contains:

```
reports/
└── My Report/
    ├── Report.json       # Report cards (teal.reporter format)
    ├── code.rds          # R code for each card (used for rebuild)
    ├── .lockfile.rds     # Username of the locking user
    ├── .creator.rds      # Username of the report creator
    └── .rebuild_time.rds # Timestamp of last rebuild
```

### Locking

Each report can be locked by one user at a time. The lock prevents other users
from saving or deleting the report. The report table shows the lock status:

- **Active** (green): The report is currently loaded by you with full access.
- **Locked** (yellow): The report is locked by another user — you can view it
  in read-only mode.
- **Unlocked** (grey): No user holds the lock — you can view it in read-only
  mode or delete it.

Locks are automatically released when the Shiny session ends.

### Auto-Save

With `auto_save = TRUE` (the default), any change to the active report's cards
triggers an automatic save. A progress indicator is shown during the save.

If the active report is in read-only mode, a warning notification is shown
instead of saving.

### Loading a Report

Click the load/eye icon next to a report in the table:

- **Your locked report**: loaded with full edit access.
- **Another user's locked report**: loaded in read-only mode.
- **Unlocked report**: loaded in read-only mode.

### Rebuilding a Report

The rebuild action re-evaluates the R code stored for each card against the
current data environment. This is useful when the underlying data has changed
and you want to refresh the report output without manually re-adding cards.

Click the refresh icon next to any report to trigger a rebuild.

### Merging Reports

Click **Merge reports** (only enabled when you have an active report) to combine
cards from two or more reports into a single new report. Only reports that have
saved content (a `Report.json` file) appear as merge candidates.

## Complete Example

```{r}
app <- teal::init(
  data = teal.data::teal_data(
    ADSL = teal.data::rADSL,
    code = "ADSL <- teal.data::rADSL"
  ),
  modules = teal::modules(
    teal::example_module(label = "Summary"),
    tm_report_manager(
      reports_path = "reports",
      auto_save = TRUE
    )
  )
)

if (interactive()) {
  shinyApp(app$ui, app$server)
}
```

## Permissions Summary

The table below summarises which actions are available depending on the report
state:

| Action | Active report | Your locked report | Others' locked report | Unlocked report |
|---|---|---|---|---|
| Edit title | Yes | Yes | No | No |
| Delete | No | Yes | No | Yes |
| Rebuild | Yes | Yes | Yes | Yes |
| Load / View | Already active | Full access | Read-only | Read-only |
| Release lock | Yes | Yes | No | N/A |
| Merge | Yes* | Yes* | Yes* | Yes* |

\* Merge requires reports to have saved content (cards).

## Further Reading

- [`teal.reporter` Documentation](https://insightsengineering.github.io/teal.reporter/)
- [`teal` Documentation](https://insightsengineering.github.io/teal/)
