Gesture input type, redoal-relay client, gitea_releases, content-driven branding
Four coupled additions that let one portal build serve a second face
(redoal.com) next to uhhm.no:
- type: gesture requirement - gesture.js draws a single stroke on a
DPR-aware canvas (pointer events, touch-action: none), mirrors
{points, key} into the paired hidden input prosekit-style, and -
when content declares relay: wss://... - speaks the redoal-relay
protocol: announce on stroke end, ghost the ack's decoded key path,
show echoes of similar strokes as thumbnails. Offline/broken relay
degrades to a plain drawing input; the widget handle's stop()
closes the socket on SPA navigation (yes.js lifecycle, not
prosekit's fire-and-forget). Submit re-parses gesture values so the
bucket stores a real object, not double-encoded JSON.
- gitea_releases resource source - token-authenticated
/repos/{owner}/{repo}/releases, for advertising a private repo's
releases (content pins url: null - private html_urls 404 publicly).
- site.yaml branding - optional, at the content repo root: title,
wordmark, hero {kind: yes|gesture|plain, relay}. Absent file means
the historical uhhm look, so uhhm changes nothing without a content
edit. Hot-swapped with questions/aggregates on content reload;
question_lint validates it in both --path and --repo modes.
- deploy.yml ships the same build twice: uhhm-portal (3010) as
before, redoal-portal (3020, CONTENT_REPO=redoal/questions,
redoal.com vhost). Needs host prep + REDOAL_OAUTH2_* repo
secrets/vars before the new steps succeed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
6cd8cc6ff5
commit
0221253cba
@@ -220,6 +220,10 @@ async fn fetch_resource_value(
|
||||
ResourceSource::GiteaOrgRepos { org } => {
|
||||
fetch_gitea_json(state, &format!("/api/v1/orgs/{org}/repos"), params).await?
|
||||
}
|
||||
ResourceSource::GiteaReleases { owner, repo } => {
|
||||
fetch_gitea_json(state, &format!("/api/v1/repos/{owner}/{repo}/releases"), params)
|
||||
.await?
|
||||
}
|
||||
ResourceSource::Url { url } => fetch_url_json(url, params).await?,
|
||||
};
|
||||
|
||||
@@ -500,6 +504,45 @@ mod tests {
|
||||
assert!(items[0].get("private").is_none());
|
||||
}
|
||||
|
||||
/// Gitea-1.27-shaped release fixtures through the filter
|
||||
/// redoal/questions' "Our Composition" feature declares. While the
|
||||
/// repo is private the filter pins `url: null` - a private
|
||||
/// release's html_url 404s for anonymous visitors, so the card
|
||||
/// must render an unlinked heading instead.
|
||||
#[test]
|
||||
fn jq_shapes_gitea_release_list_for_redoal() {
|
||||
let input = serde_json::json!([
|
||||
{
|
||||
"name": "varde bring-up",
|
||||
"tag_name": "v0.3.0",
|
||||
"body": "Embedded varde-core on iOS.",
|
||||
"published_at": "2026-08-16T09:00:00Z",
|
||||
"html_url": "https://project.uhhm.no/redoal/redoal/releases/tag/v0.3.0",
|
||||
"draft": false,
|
||||
"prerelease": true
|
||||
},
|
||||
{
|
||||
"name": "first echo",
|
||||
"tag_name": "v0.1.0",
|
||||
"body": "Gesture keys round-trip.",
|
||||
"published_at": "2026-05-01T09:00:00Z",
|
||||
"html_url": "https://project.uhhm.no/redoal/redoal/releases/tag/v0.1.0",
|
||||
"draft": false,
|
||||
"prerelease": false
|
||||
}
|
||||
]);
|
||||
let filter = ".[] | {name: .name, description: .body, tag: .tag_name, published: .published_at, url: null}";
|
||||
|
||||
let shaped = apply_jq(filter, &input).expect("filter runs");
|
||||
let items = shaped.as_array().expect("array output");
|
||||
assert_eq!(items.len(), 2);
|
||||
assert_eq!(items[0]["name"], "varde bring-up");
|
||||
assert_eq!(items[0]["tag"], "v0.3.0");
|
||||
assert_eq!(items[0]["description"], "Embedded varde-core on iOS.");
|
||||
assert_eq!(items[0]["url"], serde_json::Value::Null, "no public link while private");
|
||||
assert!(items[0].get("html_url").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_public_ip_rejects_loopback_and_private() {
|
||||
let loopback: std::net::IpAddr = "127.0.0.1".parse().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user