pub struct Card { /* private fields */ }Expand description
One thing, as a card says it: how it stands, what it is called, a few facts about it, and where to read more.
Everything but the title is optional, and what is not given is left out rather than drawn empty, because a card is read down the page and a blank line in one is noise.
Implementations§
Source§impl Card
impl Card
Sourcepub fn new(title: impl Into<String>) -> Self
pub fn new(title: impl Into<String>) -> Self
Examples found in repository?
683 fn render(&self, _args: &ViewArgs, ctx: &Context) -> Result<ViewData, ApiError> {
684 let branches: Vec<Branch> = ctx.optional_rows(BRANCHES_FILE)?;
685 let books: Vec<Book> = ctx.optional_rows(BOOKS_FILE)?;
686
687 let card = |branch: &Branch| {
688 let (here, out) = shelf_counts(&books, &branch.code);
689 let open = branch.open.unwrap_or(false);
690 let mut card = Card::new(branch.name.as_str())
691 .status(if open {
692 Status::new("Open", Tone::Good)
693 } else {
694 // A shut branch is a fact about it rather than a fault, so
695 // it is neutral—which is also what reads quieter.
696 Status::new("Shut", Tone::Neutral)
697 })
698 .identifier(branch.code.as_str())
699 .subtitle(format!(
700 "{}, {} staff",
701 librarian(branch),
702 branch.staff.unwrap_or(0)
703 ))
704 .row("Books here", here)
705 .row("Out on loan", out)
706 .link(ViewLink::new("branch").arg("branch", &branch.code));
707 if branch.hours.is_empty() {
708 card = card.sentence(
709 "No opening hours are recorded, so nothing here says when it can be visited.",
710 );
711 }
712 card
713 };
714
715 let group = |heading: &str, open: bool| {
716 CardGroup::new(heading).cards(
717 branches
718 .iter()
719 .filter(|b| b.open.unwrap_or(false) == open)
720 .map(&card),
721 )
722 };
723
724 Ok(ViewData::new()
725 .note("A card is a branch. Open one for what it holds and what is out.")
726 .group(group("Open", true))
727 .group(group("Shut", false)))
728 }Sourcepub fn status(self, status: Status) -> Self
pub fn status(self, status: Status) -> Self
How the thing stands. A card may carry more than one: a story whose last answer asked for revisions and which is also out somewhere else is both at once, and saying only one of the two would be a lie.
Examples found in repository?
683 fn render(&self, _args: &ViewArgs, ctx: &Context) -> Result<ViewData, ApiError> {
684 let branches: Vec<Branch> = ctx.optional_rows(BRANCHES_FILE)?;
685 let books: Vec<Book> = ctx.optional_rows(BOOKS_FILE)?;
686
687 let card = |branch: &Branch| {
688 let (here, out) = shelf_counts(&books, &branch.code);
689 let open = branch.open.unwrap_or(false);
690 let mut card = Card::new(branch.name.as_str())
691 .status(if open {
692 Status::new("Open", Tone::Good)
693 } else {
694 // A shut branch is a fact about it rather than a fault, so
695 // it is neutral—which is also what reads quieter.
696 Status::new("Shut", Tone::Neutral)
697 })
698 .identifier(branch.code.as_str())
699 .subtitle(format!(
700 "{}, {} staff",
701 librarian(branch),
702 branch.staff.unwrap_or(0)
703 ))
704 .row("Books here", here)
705 .row("Out on loan", out)
706 .link(ViewLink::new("branch").arg("branch", &branch.code));
707 if branch.hours.is_empty() {
708 card = card.sentence(
709 "No opening hours are recorded, so nothing here says when it can be visited.",
710 );
711 }
712 card
713 };
714
715 let group = |heading: &str, open: bool| {
716 CardGroup::new(heading).cards(
717 branches
718 .iter()
719 .filter(|b| b.open.unwrap_or(false) == open)
720 .map(&card),
721 )
722 };
723
724 Ok(ViewData::new()
725 .note("A card is a branch. Open one for what it holds and what is out.")
726 .group(group("Open", true))
727 .group(group("Shut", false)))
728 }Sourcepub fn identifier(self, identifier: impl Into<String>) -> Self
pub fn identifier(self, identifier: impl Into<String>) -> Self
The short name the thing is filed under, shown beside the status.
Examples found in repository?
683 fn render(&self, _args: &ViewArgs, ctx: &Context) -> Result<ViewData, ApiError> {
684 let branches: Vec<Branch> = ctx.optional_rows(BRANCHES_FILE)?;
685 let books: Vec<Book> = ctx.optional_rows(BOOKS_FILE)?;
686
687 let card = |branch: &Branch| {
688 let (here, out) = shelf_counts(&books, &branch.code);
689 let open = branch.open.unwrap_or(false);
690 let mut card = Card::new(branch.name.as_str())
691 .status(if open {
692 Status::new("Open", Tone::Good)
693 } else {
694 // A shut branch is a fact about it rather than a fault, so
695 // it is neutral—which is also what reads quieter.
696 Status::new("Shut", Tone::Neutral)
697 })
698 .identifier(branch.code.as_str())
699 .subtitle(format!(
700 "{}, {} staff",
701 librarian(branch),
702 branch.staff.unwrap_or(0)
703 ))
704 .row("Books here", here)
705 .row("Out on loan", out)
706 .link(ViewLink::new("branch").arg("branch", &branch.code));
707 if branch.hours.is_empty() {
708 card = card.sentence(
709 "No opening hours are recorded, so nothing here says when it can be visited.",
710 );
711 }
712 card
713 };
714
715 let group = |heading: &str, open: bool| {
716 CardGroup::new(heading).cards(
717 branches
718 .iter()
719 .filter(|b| b.open.unwrap_or(false) == open)
720 .map(&card),
721 )
722 };
723
724 Ok(ViewData::new()
725 .note("A card is a branch. Open one for what it holds and what is out.")
726 .group(group("Open", true))
727 .group(group("Shut", false)))
728 }Sourcepub fn subtitle(self, subtitle: impl Into<String>) -> Self
pub fn subtitle(self, subtitle: impl Into<String>) -> Self
The facts that go under the title, as one line.
Examples found in repository?
683 fn render(&self, _args: &ViewArgs, ctx: &Context) -> Result<ViewData, ApiError> {
684 let branches: Vec<Branch> = ctx.optional_rows(BRANCHES_FILE)?;
685 let books: Vec<Book> = ctx.optional_rows(BOOKS_FILE)?;
686
687 let card = |branch: &Branch| {
688 let (here, out) = shelf_counts(&books, &branch.code);
689 let open = branch.open.unwrap_or(false);
690 let mut card = Card::new(branch.name.as_str())
691 .status(if open {
692 Status::new("Open", Tone::Good)
693 } else {
694 // A shut branch is a fact about it rather than a fault, so
695 // it is neutral—which is also what reads quieter.
696 Status::new("Shut", Tone::Neutral)
697 })
698 .identifier(branch.code.as_str())
699 .subtitle(format!(
700 "{}, {} staff",
701 librarian(branch),
702 branch.staff.unwrap_or(0)
703 ))
704 .row("Books here", here)
705 .row("Out on loan", out)
706 .link(ViewLink::new("branch").arg("branch", &branch.code));
707 if branch.hours.is_empty() {
708 card = card.sentence(
709 "No opening hours are recorded, so nothing here says when it can be visited.",
710 );
711 }
712 card
713 };
714
715 let group = |heading: &str, open: bool| {
716 CardGroup::new(heading).cards(
717 branches
718 .iter()
719 .filter(|b| b.open.unwrap_or(false) == open)
720 .map(&card),
721 )
722 };
723
724 Ok(ViewData::new()
725 .note("A card is a branch. Open one for what it holds and what is out.")
726 .group(group("Open", true))
727 .group(group("Shut", false)))
728 }Sourcepub fn row(self, label: impl Into<String>, value: impl Display) -> Self
pub fn row(self, label: impl Into<String>, value: impl Display) -> Self
One line of the card’s own table: a label on the left, a value on the right. The value is anything that prints, so a count needs no conversion.
Examples found in repository?
683 fn render(&self, _args: &ViewArgs, ctx: &Context) -> Result<ViewData, ApiError> {
684 let branches: Vec<Branch> = ctx.optional_rows(BRANCHES_FILE)?;
685 let books: Vec<Book> = ctx.optional_rows(BOOKS_FILE)?;
686
687 let card = |branch: &Branch| {
688 let (here, out) = shelf_counts(&books, &branch.code);
689 let open = branch.open.unwrap_or(false);
690 let mut card = Card::new(branch.name.as_str())
691 .status(if open {
692 Status::new("Open", Tone::Good)
693 } else {
694 // A shut branch is a fact about it rather than a fault, so
695 // it is neutral—which is also what reads quieter.
696 Status::new("Shut", Tone::Neutral)
697 })
698 .identifier(branch.code.as_str())
699 .subtitle(format!(
700 "{}, {} staff",
701 librarian(branch),
702 branch.staff.unwrap_or(0)
703 ))
704 .row("Books here", here)
705 .row("Out on loan", out)
706 .link(ViewLink::new("branch").arg("branch", &branch.code));
707 if branch.hours.is_empty() {
708 card = card.sentence(
709 "No opening hours are recorded, so nothing here says when it can be visited.",
710 );
711 }
712 card
713 };
714
715 let group = |heading: &str, open: bool| {
716 CardGroup::new(heading).cards(
717 branches
718 .iter()
719 .filter(|b| b.open.unwrap_or(false) == open)
720 .map(&card),
721 )
722 };
723
724 Ok(ViewData::new()
725 .note("A card is a branch. Open one for what it holds and what is out.")
726 .group(group("Open", true))
727 .group(group("Shut", false)))
728 }Sourcepub fn sentence(self, sentence: impl Into<String>) -> Self
pub fn sentence(self, sentence: impl Into<String>) -> Self
A sentence about the card as a whole, for what a label and a value cannot say.
Examples found in repository?
683 fn render(&self, _args: &ViewArgs, ctx: &Context) -> Result<ViewData, ApiError> {
684 let branches: Vec<Branch> = ctx.optional_rows(BRANCHES_FILE)?;
685 let books: Vec<Book> = ctx.optional_rows(BOOKS_FILE)?;
686
687 let card = |branch: &Branch| {
688 let (here, out) = shelf_counts(&books, &branch.code);
689 let open = branch.open.unwrap_or(false);
690 let mut card = Card::new(branch.name.as_str())
691 .status(if open {
692 Status::new("Open", Tone::Good)
693 } else {
694 // A shut branch is a fact about it rather than a fault, so
695 // it is neutral—which is also what reads quieter.
696 Status::new("Shut", Tone::Neutral)
697 })
698 .identifier(branch.code.as_str())
699 .subtitle(format!(
700 "{}, {} staff",
701 librarian(branch),
702 branch.staff.unwrap_or(0)
703 ))
704 .row("Books here", here)
705 .row("Out on loan", out)
706 .link(ViewLink::new("branch").arg("branch", &branch.code));
707 if branch.hours.is_empty() {
708 card = card.sentence(
709 "No opening hours are recorded, so nothing here says when it can be visited.",
710 );
711 }
712 card
713 };
714
715 let group = |heading: &str, open: bool| {
716 CardGroup::new(heading).cards(
717 branches
718 .iter()
719 .filter(|b| b.open.unwrap_or(false) == open)
720 .map(&card),
721 )
722 };
723
724 Ok(ViewData::new()
725 .note("A card is a branch. Open one for what it holds and what is out.")
726 .group(group("Open", true))
727 .group(group("Shut", false)))
728 }Sourcepub fn link(self, link: ViewLink) -> Self
pub fn link(self, link: ViewLink) -> Self
The view the whole card is a link to.
Examples found in repository?
683 fn render(&self, _args: &ViewArgs, ctx: &Context) -> Result<ViewData, ApiError> {
684 let branches: Vec<Branch> = ctx.optional_rows(BRANCHES_FILE)?;
685 let books: Vec<Book> = ctx.optional_rows(BOOKS_FILE)?;
686
687 let card = |branch: &Branch| {
688 let (here, out) = shelf_counts(&books, &branch.code);
689 let open = branch.open.unwrap_or(false);
690 let mut card = Card::new(branch.name.as_str())
691 .status(if open {
692 Status::new("Open", Tone::Good)
693 } else {
694 // A shut branch is a fact about it rather than a fault, so
695 // it is neutral—which is also what reads quieter.
696 Status::new("Shut", Tone::Neutral)
697 })
698 .identifier(branch.code.as_str())
699 .subtitle(format!(
700 "{}, {} staff",
701 librarian(branch),
702 branch.staff.unwrap_or(0)
703 ))
704 .row("Books here", here)
705 .row("Out on loan", out)
706 .link(ViewLink::new("branch").arg("branch", &branch.code));
707 if branch.hours.is_empty() {
708 card = card.sentence(
709 "No opening hours are recorded, so nothing here says when it can be visited.",
710 );
711 }
712 card
713 };
714
715 let group = |heading: &str, open: bool| {
716 CardGroup::new(heading).cards(
717 branches
718 .iter()
719 .filter(|b| b.open.unwrap_or(false) == open)
720 .map(&card),
721 )
722 };
723
724 Ok(ViewData::new()
725 .note("A card is a branch. Open one for what it holds and what is out.")
726 .group(group("Open", true))
727 .group(group("Shut", false)))
728 }