92 lines
3.6 KiB
Markdown
92 lines
3.6 KiB
Markdown
# Sage desktop client sample
|
|
|
|
This directory is an independent Compose Desktop sample app for Sage on top of the
|
|
root `bricks-mp` shared module. It is intentionally **not** included from the
|
|
root `settings.gradle.kts`, so normal library builds are unchanged.
|
|
|
|
## Build
|
|
|
|
From any directory:
|
|
|
|
```bash
|
|
/path/to/bricks-mp/test/sageclient/build.sh
|
|
```
|
|
|
|
The script:
|
|
|
|
1. resolves its own directory,
|
|
2. uses JDK 17 or JDK 21; on macOS it auto-selects an installed 21/17 via `/usr/libexec/java_home` when the active Java is unsupported,
|
|
3. uses the repository Gradle wrapper when present, otherwise system `gradle`,
|
|
4. runs `gradle build` for this standalone sample.
|
|
|
|
Kotlin 2.1.0 / this Gradle setup does not work with newer Java versions such as `26.0.1`. If your default `java -version` is 26, install JDK 21 or 17 and either let `build.sh` auto-detect it or export `JAVA_HOME` explicitly:
|
|
|
|
```bash
|
|
brew install --cask temurin@21
|
|
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
|
|
./test/sageclient/build.sh
|
|
```
|
|
|
|
Extra Gradle arguments can be appended, for example:
|
|
|
|
```bash
|
|
./test/sageclient/build.sh --info
|
|
```
|
|
|
|
## Run
|
|
|
|
Run without arguments to open the sample shell:
|
|
|
|
```bash
|
|
cd /path/to/bricks-mp/test/sageclient
|
|
../../gradlew run \
|
|
-Dsage.baseUrl=http://localhost:8080 \
|
|
-Dsage.centerUi=/center.ui
|
|
```
|
|
|
|
Run with a startup URL to enter that UI directly without showing the sample
|
|
base URL / login input shell:
|
|
|
|
```bash
|
|
cd /path/to/bricks-mp/test/sageclient
|
|
../../gradlew run --args="https://ai.atvoe.com/center.ui"
|
|
```
|
|
|
|
The packaged macOS app also accepts the URL as its first argument:
|
|
|
|
```bash
|
|
open build/compose/binaries/main/app/sageclient.app --args https://ai.atvoe.com/center.ui
|
|
```
|
|
|
|
If the argument is an absolute `http://` or `https://` URL, `sageclient` uses the URL origin as `baseUrl` and dispatches that same absolute URL through the Bricks `urlwidget` loading path. If the argument is a relative path such as `/center.ui`, it uses `sage.baseUrl` and loads that path. The actual HTTP request is still issued through `BricksHttp`, so startup URLs ending in `.ui` / `.dspy` are requested with `_webbricks_=1`, `_width`, `_height`, `_is_mobile` and `_lang`; they must not be fetched as raw HTML/template pages.
|
|
|
|
Optional properties:
|
|
|
|
- `sage.baseUrl` defaults to `http://localhost:8080`
|
|
- `sage.centerUi` defaults to `/center.ui`
|
|
- `sage.loginAction` defaults to `/rbac/user/login`
|
|
- `sage.loginUi` defaults to `/rbac/user/login.ui`
|
|
- `sage.username` / `sage.password` prefill the login form
|
|
- `sage.lang` overrides the default JVM locale tag
|
|
|
|
## What the sample demonstrates
|
|
|
|
- Uses the generic `BricksHttp` client from the shared module for Sage login and
|
|
`center.ui` loading. Sage-specific bootstrapping lives here, not in the shared
|
|
library package.
|
|
- Loads `center.ui` via `ActionDispatcher.dispatch(BricksBind(actiontype =
|
|
"urlwidget", ...))`, so HTTP handling stays in the shared ActionDispatcher /
|
|
BricksHttp flow.
|
|
- `BricksHttp` automatically appends the correct WebBricks query parameters for
|
|
`.ui` / `.dspy` backend requests:
|
|
`_webbricks_`, `_width`, `_height`, `_is_mobile`, `_lang`.
|
|
- `BricksHttp` surfaces HTTP 403, 401 and 3xx (including 301) as
|
|
`BricksHttpException`. `ActionDispatcher` handles them generically:
|
|
- 403 loads the configured login UI (`sage.loginUi`) in a dialog,
|
|
- 401 shows the server response as an unauthorized message,
|
|
- 3xx follows the `Location` header as a UI navigation target.
|
|
|
|
The sample is wired as a Gradle composite build through `includeBuild("../..")`
|
|
and depends on the root project module using `implementation("com.bricks.mp:shared")`
|
|
with dependency substitution to `:shared`.
|