use ely_gpui_component::{ project::{IssueId, Person, Priority, Status, Task}, theme::{ActiveTheme, TextSize}, }; use gpui::{ AnyElement, App, Entity, IntoElement, ParentElement, SharedString, Styled, Window, div, }; use jiff::{Timestamp, ToSpan, civil::Date, tz::TimeZone}; mod tasks; use super::Page; use crate::{script::Step, ui::keep}; pub const PAGE: Page = Page { number: 31, slug: "project", title: "Project", summary: "Tasks and issues, who has them, where they stand, and when they are due.", render, script: SCRIPT, }; const SCRIPT: &[Step] = &[ Step::DownAt("project-fields", 150.0, 16.0), Step::UpAt("project-fields", 150.0, 16.0), Step::Wait(250), Step::Shot("status-open"), Step::Key("escape"), Step::DownAt("project-tasks", 26.0, 22.0), Step::UpAt("project-tasks", 26.0, 22.0), Step::Wait(200), Step::Shot("task-ticked"), ]; /// What a demo says it did, under it. fn quiet(text: SharedString, cx: &App) -> impl IntoElement + use<> { let theme = cx.theme(); div() .text_size(theme.text_size(TextSize::Sm)) .text_color(theme.colors.fg_muted) .child(text) } /// Today in the gallery's zone. fn today() -> Date { let zone = TimeZone::try_system().expect("the gallery reads the system time zone"); Timestamp::now().to_zoned(zone).date() } fn team() -> Vec { vec![ Person::new("chloe", "ChloƩ Martin"), Person::new("ana", "Ana Lima"), Person::new("ben", "Ben Ito"), Person::new("dev", "Dev Rao"), ] } /// A studio's open work around today: late, due soon, in review, done. fn work(today: Date) -> Vec { let day = |offset: i64| today.checked_add(offset.days()).expect("a day nearby"); let who = |key: &str| { team() .into_iter() .find(|person| person.key.as_ref() == key) .expect("one of the team") }; vec![ Task::new("brief", "Write the client brief") .issue(IssueId::new("ARC", 41)) .status(Status::InProgress) .priority(Priority::Urgent) .due(day(-1)) .assignee(who("ana")), Task::new("samples", "Order plaster samples") .issue(IssueId::new("ARC", 44)) .priority(Priority::High) .due(day(0)) .assignee(who("ben")), Task::new("model", "Photograph the site model") .issue(IssueId::new("ARC", 38)) .status(Status::InReview) .priority(Priority::Medium) .due(day(3)) .assignee(who("chloe")), Task::new("budget", "Revise the lighting budget") .issue(IssueId::new("ARC", 47)) .priority(Priority::Low) .due(day(12)), Task::new("survey", "Book the land survey") .issue(IssueId::new("ARC", 29)) .status(Status::Done) .priority(Priority::Medium) .due(day(-4)) .assignee(who("dev")), Task::new("archive", "Archive last year's renders") .issue(IssueId::new("ARC", 17)) .status(Status::Backlog), ] } /// The page's tasks, which ticks and picks change. fn board(window: &mut Window, cx: &mut App) -> Entity> { keep("project-work", || work(today()), window, cx) } fn render(window: &mut Window, cx: &mut App) -> AnyElement { div() .child(tasks::marks(cx)) .child(tasks::fields(window, cx)) .child(tasks::list(window, cx)) .child(tasks::subtasks(window, cx)) .into_any_element() }