---
title: "Publishing a glasstabs Workflow to Posit Connect"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Publishing a glasstabs Workflow to Posit Connect}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(eval = FALSE)
```

## Overview

`runGlassExample("connect-workflow")` opens a Shiny page designed to be
published to Posit Connect. It demonstrates a practical review workflow:

- filters define the active queue with `glassSelect()` and
  `glassMultiSelect()`
- `glassTabsUI(orientation = "vertical", indicator = "solid")` guides users
  through intake, exploration, and approval
- `updateGlassTabBadge()` keeps tab badges aligned with the filtered data
- `updateGlassTabsUI()` moves reviewers to the next stage from server actions
- `theme = "auto"` follows Bootstrap 5 / bslib light and dark modes
- `overflow = "scroll"`, `"multiline"`, and the horizontal-only `"menu"` mode can
  be compared without leaving the app
- opt-in swipes, dynamic tab controls, keyboard behavior, and the experimental
  `glassPage()` wrapper can be exercised in one published session

The page includes an open test checklist. It is there to make a review session
easy to repeat, not to turn the example into a wall of instructions.

## What to test after publishing

1. Resize the page and compare the three overflow choices. The page itself
   should never scroll sideways.
2. On a touch screen, swipe over open panel space. Text inputs, buttons,
   tables, and the sideways scroll box should keep their own gestures.
3. Move through the tab bar with arrow keys, Home, and End. Only the active tab
   should be in the normal Tab-key order.
4. Open both glass selects and try arrow keys, Home, End, Enter, Space, and
   Escape.
5. Add and remove the live tab. In horizontal compact-menu mode, confirm
   that its option appears and disappears too.
6. Hide and show Approve, then disable and enable Explore. A hidden or disabled
   tab should not trap selection or keyboard focus.
7. Update the Test lab badge. Its pulse should be subtle and should not move
   focus.
8. Compare light and dark mode with each indicator, shape, alignment, and
   orientation.
9. Enable reduced motion or high contrast in the operating system and reload
   the app. Content should change immediately and remain easy to distinguish.
10. Refresh the Connect app and repeat a few controls to catch asset caching or
    session-reconnect problems.

## Versions, dependencies, and CSP

**Pin the version you tested.** Install the CRAN release for
stability, or a GitHub commit for development — but record which one
the deployment uses, because the development version moves. The
installed version is visible from R with `packageVersion("glasstabs")`
and in the app with `glasstabs_news()`; if a deployed app behaves
differently from local, the version is the first thing to compare.

**Confirm the assets published.** After the first deploy, open the
app and confirm the dropdowns render styled. Unstyled controls after
publishing mean the HTML dependencies did not travel with the app:
check that `useGlassTabs()` is called once at the UI root (or that
the app uses `glassPage()`, which loads the dependency
automatically), and check the manifest includes the package's
dependencies. The "What to test" list above catches this on the
first pass, but only if someone actually opens a dropdown.

**The `useGlassTabs()` exception, stated once.** The getting-started
rule is "exactly one `useGlassTabs()` call." `glassPage()` is the
exception: it loads the dependency itself, so an app built on
`glassPage()` must not also call `useGlassTabs()`. One or the other,
never both, never neither.

**Content Security Policy.** If the deployment serves a strict CSP,
set the `glasstabs.csp_nonce` option to the page's nonce and the
package's generated `<style>` elements will carry it. That covers
style elements only: it is not a general strict-CSP guarantee, and
scripts, inline handlers, and other sources need their own testing
under the deployment's actual policy before claiming compatibility.

**Theming check.** Before shipping a themed deployment, run the
theme-switcher example (`runGlassExample("theme-switcher")`): one
switch flips every select between dark and light, including long
labels, wide text in a narrow phone frame, and a bottom-of-page
dropdown that must flip above the field. If those survive, the
deployment's theme wiring is sound.

## Run locally

```{r}
library(glasstabs)

if (interactive()) {
  runGlassExample("connect-workflow")
}
```

## Manifest

The repository copy keeps a deployment `manifest.json` generated by
`rsconnect::writeManifest()`. It is left out of the CRAN source package so an
old package lock cannot override the version a user has installed. When testing
a repository build that is newer than the CRAN release, install that build
before regenerating the manifest so Connect restores the same code:

```{r}
pak::pak("PrigasG/glasstabs")
rsconnect::writeManifest(appDir = "inst/examples/connect-workflow")
```

## Deploy to Posit Connect

The example is a self-contained Shiny app folder. In a package checkout,
regenerate its manifest after installing the version you want to deploy:

```{r}
rsconnect::writeManifest(appDir = "inst/examples/connect-workflow")
rsconnect::deployApp(
  appDir = "inst/examples/connect-workflow",
  appName = "glasstabs-connect-workflow",
  appTitle = "glasstabs Connect Workflow"
)
```

If you are deploying from an installed package, copy the example folder first:

```{r}
example_dir <- system.file("examples", "connect-workflow", package = "glasstabs")
file.copy(example_dir, "connect-workflow", recursive = TRUE)

rsconnect::writeManifest(appDir = "connect-workflow")
rsconnect::deployApp(
  appDir = "connect-workflow",
  appName = "glasstabs-connect-workflow",
  appTitle = "glasstabs Connect Workflow"
)
```

## Workflow pattern

The page uses a common Connect pattern: make the first screen the actual work
surface, keep controls near the content they affect, and expose state through
badges and compact metrics. That makes the app useful as a scheduled report,
review queue, or operational handoff page without adding a separate landing
screen.
