# `Ascii.Pieces.UptimeBar`
[🔗](https://github.com/houllette/ascii_art/blob/main/lib/ascii/pieces/uptime_bar.ex#L1)

60-day uptime bars for three services, a new day slides in.

A status page's 60-day uptime bars, one thin bar a day, for up to three
services. A degraded day is a short bar, a down day flat. As upstream
draws it, made-up days slide in one at a time; give each service its
`history` and it stands still on yours, for a real status board.

## Options

Give them to `Ascii.new/2` as `options:`, and new ones while it plays
with `Ascii.put_options/2` (or a Phoenix player's `options`): the
board is drawn anew from them, a new day added to a history showing at
once.

  * `services` - the services' names, up to three (more are cut), each
    cut to 24 characters. Fewer sit in the middle of the frame. Default
    `["api", "website", "database"]`.
  * `history` - for each service, in the order of `services`, its daily
    uptime in percent, oldest first, the last being today: a day of 99.95%
    or more is up, of 97% or more degraded, and less is an outage. Days
    before the first are left blank, and a service without a history (or
    an empty one) plays upstream's. Its state today, its headline and its
    footer's uptime follow the days shown. Default `[]`.
  * `days` - how many days the bars span, 20 to 196; the frame is four
    columns wider, 15 rows tall, and labels that do not fit are cut.
    Default 60.

## Colours

In one ink, or a gradient, with `:ink` and `:gradient` (see
`Ascii.Ink`); part by part with `:parts` (see `Ascii.Parts`),
`parts: true` taking the colours suggested here:

  * `title.ok`, `title.warn`, `title.fail` - the headline ("all systems
    operational", "degraded performance", "partial outage"), by the worst
    state today: green, yellow and red.
  * `label` - a service's name.
  * `status.ok`, `status.warn`, `status.fail` - its state today
    (operational, degraded, outage): green, yellow and red.
  * `day.up`, `day.degraded`, `day.down` - its days: green, yellow and
    red.
  * `scale` - under the bar, the span's ends ("60 days ago", "today"),
    grey.
  * `rule` - the dotted leaders between them, grey.
  * `value` - the uptime over the days shown; the word "uptime" after it
    is a `label`.

A state cut at the frame's edge to a letter that could begin two words
(`o`) is in no part.

## Keys and clicks

It takes none: it shows uptime, and `Ascii.handle_event/2` ignores
every event. A Phoenix player given `interactive` and `notify` still
tells your LiveView where it was clicked, and on which part
(`Ascii.part_at/4`): a service's state, say, or one of its days.

## Screen readers

`Ascii.describe/1` tells each service given a history its state today
and its uptime over the days shown: "uptime: api operational, 100.00%
over 60 days; database outage, 99.85% over 60 days". Without a history,
it gives the piece's name and note.

## Example

```elixir
up = List.duplicate(100, 59)
history = [up ++ [100], up ++ [98.5], up ++ [91.0]]
options = %{services: ["api", "website", "database"], history: history}
board = Ascii.new!("uptime-bar", options: options, parts: true)

{frame, board} = Ascii.frame(board, 0.0)
frame.text =~ "partial outage"
#=> true

Ascii.describe(board)
#=> "uptime: api operational, 100.00% over 60 days; website degraded, 99.97% over 60 days; database outage, 99.85% over 60 days"

# The next day: the database is back.
board = Ascii.put_options!(board, history: [up ++ [100], up ++ [98.5], up ++ [91.0, 100]])
{frame, _board} = Ascii.frame(board, 1.0)
frame.text =~ "degraded performance"
#=> true
```

```heex
<Ascii.Phoenix.live_player id="status" piece="uptime-bar" options={%{services: @names, history: @history}} parts />
```

Ported from `src/pieces/uptime-bar.ts` in bas3line/ascii (MIT).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
