Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47c894cc1d | ||
|
|
7bc59a65e0 | ||
|
|
243b6a5704 |
Generated
+1
-1
@@ -2948,7 +2948,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "portal"
|
||||
version = "0.3.10"
|
||||
version = "0.3.11"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "portal"
|
||||
version = "0.3.10"
|
||||
version = "0.3.11"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -39,6 +39,16 @@ stream.
|
||||
`requires_chain` gates a page on verifiable answer provenance next
|
||||
to `qualifies`' Kanidm-group identity gate (see
|
||||
`docs/design/filesystem-routes.md`).
|
||||
- **Gesture and voice fields** (`gesture.js`, `voice.js`): a stroke
|
||||
becomes a redoal gesture key through a relay (ADR-0013/0015 in the
|
||||
redoal repo) - the input shows the key's own decode under the
|
||||
stroke, who is at a similar shape now, and *places* with recordings
|
||||
the visitor can pick to make that key theirs; a voice field records
|
||||
in the browser and leaves the audio at a key. Actions may be
|
||||
templated from the answer (`/shape/{curve.key}`) onto dynamic
|
||||
pages, whose URL segment also fills `value: "{key}"` presets and
|
||||
`url` resource sources; resource items with an https `audio` field
|
||||
render a player.
|
||||
- **Announced pages** (`src/announce.rs`): a question with an
|
||||
`event: {starts, duration, place}` window is announced in the
|
||||
header (not the footer nav) while the window is open, becomes a
|
||||
|
||||
+27
-6
@@ -1119,13 +1119,18 @@ pub fn validate_questions(
|
||||
a
|
||||
};
|
||||
let _ = probe;
|
||||
match resolve_question(questions, &filled) {
|
||||
Some(target) if target.is_dynamic() => continue,
|
||||
_ => anyhow::bail!(
|
||||
"question {:?} alternative {:?}: templated action {:?} must land on a dynamic page ([name].yaml)",
|
||||
question.id, alternative.name, action
|
||||
),
|
||||
// Match the pattern itself: resolve_question would
|
||||
// hand back a clone whose id is already concrete.
|
||||
let lands = questions
|
||||
.values()
|
||||
.any(|q| q.is_dynamic() && path_matches(&q.id, &filled).is_some());
|
||||
if lands {
|
||||
continue;
|
||||
}
|
||||
anyhow::bail!(
|
||||
"question {:?} alternative {:?}: templated action {:?} must land on a dynamic page ([name].yaml)",
|
||||
question.id, alternative.name, action
|
||||
);
|
||||
}
|
||||
match questions.get(action) {
|
||||
None => anyhow::bail!(
|
||||
@@ -2025,6 +2030,22 @@ alternatives:
|
||||
assert_eq!(render_inline_markdown("[mail](mailto:bl@uhhm.no)"), "<a href=\"mailto:bl@uhhm.no\">mail</a>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn templated_action_validates_against_the_dynamic_page() {
|
||||
let landing: Question = serde_yaml::from_str(
|
||||
"id: /\nname: L\nalternatives:\n - name: A\n action: /shape/{curve.key}\n",
|
||||
)
|
||||
.unwrap();
|
||||
let place: Question = serde_yaml::from_str("id: /shape/[key]\nname: P\n").unwrap();
|
||||
let mut qs = std::collections::HashMap::new();
|
||||
qs.insert(landing.id.clone(), landing.clone());
|
||||
qs.insert(place.id.clone(), place);
|
||||
validate_questions(&qs, &Default::default()).unwrap();
|
||||
let mut only_landing = std::collections::HashMap::new();
|
||||
only_landing.insert(landing.id.clone(), landing);
|
||||
assert!(validate_questions(&only_landing, &Default::default()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn action_templates_from_responses() {
|
||||
let r = serde_json::json!({"curve": {"key": "20aa98", "points": [[0,0]]}, "n": 3});
|
||||
|
||||
Reference in New Issue
Block a user