Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57b733e606 | ||
|
|
3923d4d0dc | ||
|
|
00db014eae | ||
|
|
d2450fcb75 | ||
|
|
0841ed561a | ||
|
|
79f85132c5 | ||
|
|
58d68c3bff | ||
|
|
0cf70502fc |
@@ -3,6 +3,30 @@
|
||||
One line per change, grouped by the release that shipped it. Newest
|
||||
first. Each release names the portal tag it is built against.
|
||||
|
||||
## 0.3.47 (2026-09-24) - portal v0.3.47
|
||||
|
||||
- Matches portal v0.3.47 (released by portal's publish job).
|
||||
|
||||
## 0.3.46 (2026-09-23) - portal v0.3.46
|
||||
|
||||
- Matches portal v0.3.46 (released by portal's publish job).
|
||||
|
||||
## 0.3.45 (2026-09-23) - portal v0.3.45
|
||||
|
||||
- Matches portal v0.3.45 (released by portal's publish job).
|
||||
|
||||
## 0.3.44 (2026-09-23) - portal v0.3.44
|
||||
|
||||
- Matches portal v0.3.44 (released by portal's publish job).
|
||||
|
||||
## 0.3.43 (2026-09-23) - portal v0.3.43
|
||||
|
||||
- Matches portal v0.3.43 (released by portal's publish job).
|
||||
|
||||
## 0.3.42 (2026-09-23) - portal v0.3.42
|
||||
|
||||
- Matches portal v0.3.42 (released by portal's publish job).
|
||||
|
||||
## 0.3.41 (2026-09-23) - portal v0.3.41
|
||||
|
||||
- Matches portal v0.3.41 (released by portal's publish job).
|
||||
|
||||
Generated
+3
-3
@@ -2196,7 +2196,7 @@ checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0"
|
||||
|
||||
[[package]]
|
||||
name = "iris"
|
||||
version = "0.3.41"
|
||||
version = "0.3.47"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-nats",
|
||||
@@ -3303,8 +3303,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "portal"
|
||||
version = "0.3.41"
|
||||
source = "git+https://project.uhhm.no/uhhm/portal.git?tag=v0.3.41#710654308982fcda2321065fa419dc34bbcffd65"
|
||||
version = "0.3.47"
|
||||
source = "git+https://project.uhhm.no/uhhm/portal.git?tag=v0.3.47#9ed81944847c20cb6751e221e679449a8b5ebc47"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "iris"
|
||||
version = "0.3.41"
|
||||
version = "0.3.47"
|
||||
edition = "2021"
|
||||
description = "The iris over a portal site: nothing from a content repo comes through until it checks out"
|
||||
license = "MIT"
|
||||
@@ -10,7 +10,7 @@ repository = "https://project.uhhm.no/uhhm/iris"
|
||||
# The site's own content types and loaders, so iris reads a repo exactly
|
||||
# the way the running site does. Pinned to the portal release it
|
||||
# matches; bumping this tag is what a new iris release is.
|
||||
portal = { git = "https://project.uhhm.no/uhhm/portal.git", tag = "v0.3.41", features = ["ssr"] }
|
||||
portal = { git = "https://project.uhhm.no/uhhm/portal.git", tag = "v0.3.47", features = ["ssr"] }
|
||||
anyhow = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
+50
-3
@@ -73,6 +73,11 @@ pub struct Need {
|
||||
/// as a warning, so the gap stays visible without failing CI.
|
||||
#[serde(default)]
|
||||
pub planned: bool,
|
||||
/// Each state of the bucket in plain words, in the site's
|
||||
/// language, for the scorer: state ids are ASCII, and a Norwegian
|
||||
/// `ikke_lost` reads as English to a model.
|
||||
#[serde(default)]
|
||||
pub stage_words: std::collections::BTreeMap<String, String>,
|
||||
/// The finished states that are a good outcome for the business -
|
||||
/// a subset of `done_when`. "lost" is finished; "won" is success.
|
||||
/// What a simulation or a live bucket report counts toward.
|
||||
@@ -571,7 +576,8 @@ pub fn sim_model(
|
||||
json!({
|
||||
"page": step.page,
|
||||
"question": page.name,
|
||||
"options": page.alternatives.iter().filter(|a| !a.disabled).map(|a| json!({
|
||||
"context": page_context(page),
|
||||
"options": page.alternatives.iter().filter(|a| !a.disabled && leads_somewhere(a)).map(|a| json!({
|
||||
"name": a.name,
|
||||
"description": plain(&a.description),
|
||||
})).collect::<Vec<_>>(),
|
||||
@@ -597,6 +603,7 @@ pub fn sim_model(
|
||||
json!({
|
||||
"initial": schema.initial,
|
||||
"transitions": schema.transitions,
|
||||
"words": need.stage_words,
|
||||
"desks": desks_over(questions, &need.lands_in).iter().map(|d| json!({
|
||||
"page": d.page,
|
||||
"group": d.group,
|
||||
@@ -646,6 +653,41 @@ fn plain(text: &str) -> String {
|
||||
text.split_whitespace().collect::<Vec<_>>().join(" ")
|
||||
}
|
||||
|
||||
/// A card a visitor can act on: it leads to a page, records an
|
||||
/// answer, or moves a record. A card with none of those is read, not
|
||||
/// picked - the opener that says what the business does, the look
|
||||
/// around - and is context on the page, never an option.
|
||||
pub fn leads_somewhere(a: &Alternative) -> bool {
|
||||
a.action.is_some() || a.record_as.is_some() || a.self_transition.is_some()
|
||||
}
|
||||
|
||||
/// What the page says before its options: every card that leads
|
||||
/// nowhere, its heading, description and features, as one line each.
|
||||
pub fn page_context(page: &Question) -> String {
|
||||
page.alternatives
|
||||
.iter()
|
||||
.filter(|a| !a.disabled && !leads_somewhere(a))
|
||||
.map(|a| {
|
||||
let mut line = a.name.clone();
|
||||
let description = plain(&a.description);
|
||||
if !description.is_empty() {
|
||||
line.push_str(&format!(": {description}"));
|
||||
}
|
||||
for f in &a.features {
|
||||
let text = plain(&f.description);
|
||||
match (f.name.trim().is_empty(), text.is_empty()) {
|
||||
(true, true) => {}
|
||||
(true, false) => line.push_str(&format!(" {text}")),
|
||||
(false, true) => line.push_str(&format!(" {}.", f.name.trim())),
|
||||
(false, false) => line.push_str(&format!(" {}: {text}", f.name.trim())),
|
||||
}
|
||||
}
|
||||
line
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
/// Every (persona, page-on-their-path) pair with a real choice on it.
|
||||
/// `skim` shows the engine only each alternative's heading - what a
|
||||
/// visitor who never reads the description has to go on.
|
||||
@@ -660,10 +702,11 @@ pub fn tasks(file: &NeedsFile, questions: &Questions, skim: bool) -> Vec<Task> {
|
||||
};
|
||||
for (i, step) in path.iter().enumerate() {
|
||||
let page = &questions[&step.page];
|
||||
let open: Vec<&Alternative> = page.alternatives.iter().filter(|a| !a.disabled).collect();
|
||||
let open: Vec<&Alternative> = page.alternatives.iter().filter(|a| !a.disabled && leads_somewhere(a)).collect();
|
||||
if open.len() < 2 {
|
||||
continue;
|
||||
}
|
||||
let context = page_context(page);
|
||||
let mut trail: Vec<String> = path[..=i].iter().map(|s| s.page.clone()).collect();
|
||||
let expect: Vec<String> = viable(questions, need, page, need.max_steps - i, i == 0, false, &mut trail)
|
||||
.into_iter()
|
||||
@@ -684,7 +727,11 @@ pub fn tasks(file: &NeedsFile, questions: &Questions, skim: bool) -> Vec<Task> {
|
||||
persona: persona.id.clone(),
|
||||
need: need.id.clone(),
|
||||
page: step.page.clone(),
|
||||
state: BTreeMap::from([("body", plain(&persona.text))]),
|
||||
state: if context.is_empty() {
|
||||
BTreeMap::from([("body", plain(&persona.text))])
|
||||
} else {
|
||||
BTreeMap::from([("body", plain(&persona.text)), ("page", context)])
|
||||
},
|
||||
questions: BTreeMap::from([(
|
||||
"pick",
|
||||
ChoiceQuestion {
|
||||
|
||||
Reference in New Issue
Block a user