Project · Issues and boards: a board, issue cards, a task's panel, labels
KanbanBoard lays columns of cards side by side. A card drags to a place in any column: it rides raised at the pointer, a slot opens where it would land, the other cards glide aside on motion::Flip, and the drop asks the owner through on_move(card, column, index); a drop in its own place asks nothing. Option with an arrow moves the focused card, whose focus the board keys by card so it follows it across columns. A press, Enter or Space opens it. Sprint Board is this board. IssueCard shows an issue's status, name, assignee, title, priority, labels and due day. TaskDetailPanel lays a task out in full: its title edits in place, its status, priority, assignee and due day change where they stand, and its notes and steps follow; each edit hands the whole task on, and a blank title is not taken. LabelManager tends a team's labels: a hue picked from a popover, a name edited in place, a delete, and a field that makes a new one; names stay unique in any case, and a refused name says why. The fill rule changes: min_w_full, taken up in T30d, resolves against a block's outer width in taffy 0.9, so a field in a padded card ran past its padding. A component that fills now takes no width on its root, which blocks and flex columns stretch; FormField and the new roots do. The chart's hue names move to theme::HUE_NAMES, which the event editor and the label manager share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9b506e5d54
commit
62382f7e68
24 files changed
+1813
-31
No files matched your search
+35
-2
@@ -3,7 +3,7 @@ use std::fmt;
|
||||
use gpui::SharedString;
|
||||
use jiff::civil::Date;
|
||||
|
||||
use crate::primitives::IconName;
|
||||
use crate::{mail::Label, primitives::IconName};
|
||||
|
||||
/// Where a task stands in its workflow.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
@@ -83,6 +83,15 @@ pub enum Priority {
|
||||
}
|
||||
|
||||
impl Priority {
|
||||
/// Most urgent first.
|
||||
pub const ALL: [Priority; 5] = [
|
||||
Priority::Urgent,
|
||||
Priority::High,
|
||||
Priority::Medium,
|
||||
Priority::Low,
|
||||
Priority::None,
|
||||
];
|
||||
|
||||
pub fn words(self) -> &'static str {
|
||||
match self {
|
||||
Priority::None => "No priority",
|
||||
@@ -93,6 +102,23 @@ impl Priority {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn key(self) -> &'static str {
|
||||
match self {
|
||||
Priority::None => "none",
|
||||
Priority::Low => "low",
|
||||
Priority::Medium => "medium",
|
||||
Priority::High => "high",
|
||||
Priority::Urgent => "urgent",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn of_key(key: &str) -> Priority {
|
||||
Priority::ALL
|
||||
.into_iter()
|
||||
.find(|priority| priority.key() == key)
|
||||
.unwrap_or_else(|| panic!("no priority {key}"))
|
||||
}
|
||||
|
||||
/// Bars lit of three; urgent has a mark of its own.
|
||||
pub(crate) fn bars(self) -> usize {
|
||||
match self {
|
||||
@@ -146,7 +172,7 @@ impl Person {
|
||||
}
|
||||
}
|
||||
|
||||
/// A piece of work: its key, its issue's name if it has one, what it is, where it stands, how urgent, when it is due, and who has it.
|
||||
/// A piece of work: its key, its issue's name if it has one, what it is, where it stands, how urgent, when it is due, who has it, and its labels.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Task {
|
||||
pub key: SharedString,
|
||||
@@ -156,6 +182,7 @@ pub struct Task {
|
||||
pub priority: Priority,
|
||||
pub due: Option<Date>,
|
||||
pub assignee: Option<Person>,
|
||||
pub labels: Vec<Label>,
|
||||
}
|
||||
|
||||
impl Task {
|
||||
@@ -168,6 +195,7 @@ impl Task {
|
||||
priority: Priority::None,
|
||||
due: None,
|
||||
assignee: None,
|
||||
labels: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,6 +224,11 @@ impl Task {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn label(mut self, label: Label) -> Self {
|
||||
self.labels.push(label);
|
||||
self
|
||||
}
|
||||
|
||||
/// Due before `today` and still open.
|
||||
pub fn overdue(&self, today: Date) -> bool {
|
||||
!self.status.closed() && self.due.is_some_and(|due| due < today)
|
||||
|
||||
Reference in new issue
Block a user