# MIDCON.PluginUi.Abstractions

Abstractions layer for Blazor-based UI components in **MIDCON MCM plugin packages**.

Provides base classes and interfaces that plugin developers implement when building
the UI portions of an MCM plugin — ensuring a consistent component model across all plugins.

---

## Installation

```bash
dotnet add package MIDCON.PluginUi.Abstractions
```

Or in your `.csproj`:

```xml
<PackageReference Include="MIDCON.PluginUi.Abstractions" Version="x.y.z" />
```

---

## Dependencies

| Package | Version | Purpose |
|---|---|---|
| `Microsoft.AspNetCore.Components` | 10.0.7 | Blazor component model (`ComponentBase`) |

Target framework: **net10.0**

---

## Usage

### PluginComponentBase

`PluginComponentBase` extends `ComponentBase` and adds a built-in loading-state
pattern for async operations. Inherit from it in your plugin's Blazor components:

```csharp
using MIDCON.PluginUi.Abstractions;

public class MyPluginComponent : PluginComponentBase
{
    private async Task OnButtonClick()
    {
        await RunWithProgressAsync(async () =>
        {
            // IsLoading is true here — show spinner in your markup
            await SomeService.DoWorkAsync();
        }, label: "Loading data"); // optional: shown in the shell's global indicator
        // IsLoading is false again, StateHasChanged() was called automatically
    }
}
```

In your `.razor` file:

```razor
@inherits PluginComponentBase

@if (IsLoading)
{
    <div class="spinner" />
}
else
{
    <button @onclick="OnButtonClick">Start</button>
}
```

`RunWithProgressAsync` sets `IsLoading = true`, yields the WASM thread
(so progress indicators can render), runs your work, then sets `IsLoading = false`
and calls `StateHasChanged()` — even if an exception is thrown.

It also notifies the shell's `IBusyService` so the shell can display a global
loading indicator while your operation runs. The `label` parameter is optional
and can be shown in the shell's UI.

### IBusyService

`IBusyService` is a shell-provided DI service that tracks active background
operations across the entire application. Plugin components **do not interact
with it directly** — `RunWithProgressAsync` calls `Begin()` automatically.

The shell implements `IBusyService` and uses it to show a global spinner or
progress bar whenever any plugin component is busy.

### IViewportService / Mobile support

`IViewportService` is a shell-provided DI service (`Breakpoint`, `IsMobile`, `Changed`)
for responsive plugin pages. Inject it with `@inject` where needed; it is intentionally
not part of `PluginComponentBase`. Routes declare their mobile capability in `routes.json`
via `Mobile` (`desktop-only` default, `responsive`, `mobile-first`), parsed with
`MobileSupportParser`. See [docs/mobile-viewport-contract.md](docs/mobile-viewport-contract.md).

### IShellSessionService / Logout

`IShellSessionService` is a shell-provided DI service that lets plugins end the shell session
(`LogoutAsync(LogoutReason)`) and register before-logout handlers (`RegisterBeforeLogout`)
to save unsaved data while the session is still valid. Handlers run in parallel with a shared
timeout; failures never block the logout. The shell triggers handlers strictly before the tokens
are revoked, never after the logout; a handler that sees its `CancellationToken` time out must
stop at once.
Like `IViewportService`, inject it with `@inject`; it is not part of `PluginComponentBase`.
It requires a shell with session support (midcon-server#256) — viewport support alone is not
enough, and `@inject` throws a DI exception otherwise.
See [docs/api-reference.md](docs/api-reference.md#ishellsessionservice).

---

## Versioning

This package uses [GitVersion](https://gitversion.net/) via `GitVersion.MsBuild`.
The version is derived automatically from the git history and tags.

To create a release version, tag the commit:

```bash
git tag v1.0.0
dotnet pack -c Release
```

---

## Building & Packing

```bash
# Restore & build
dotnet build src/MIDCON.PluginUi.Abstractions.slnx -c Release

# Create NuGet package
dotnet pack src/MIDCON.PluginUi.Abstractions/MIDCON.PluginUi.Abstractions.csproj -c Release -o ./artifacts
```

The resulting `.nupkg` is in `./artifacts/`.

---

## License

MIT — see [LICENSE](LICENSE).

**Author:** MidConsulting  
**Company:** MidConsulting
