App-karr
view release on metacpan or search on metacpan
lib/App/karr/Cmd/Board.pm view on Meta::CPAN
# ABSTRACT: Show board summary
package App::karr::Cmd::Board;
our $VERSION = '0.301';
use Moo;
use MooX::Cmd;
use MooX::Options (
usage_string => 'USAGE: karr board [--json] [--compact]',
);
use App::karr::Role::BoardAccess;
use App::karr::Role::Output;
use App::karr::Task;
use App::karr::Config;
use Term::ANSIColor qw( colored );
with 'App::karr::Role::BoardAccess', 'App::karr::Role::Output';
my %STATUS_STYLE = (
backlog => 'black on_bright_white',
todo => 'black on_cyan',
'in-progress' => 'black on_yellow',
review => 'black on_bright_white',
done => 'black on_green',
archived => 'white on_black',
);
my %PRIORITY_COLOR = (
critical => 'bold red',
high => 'red',
medium => 'yellow',
low => 'black',
);
sub execute {
my ($self, $args_ref, $chain_ref) = @_;
my $ec = $self->store->effective_config;
my @statuses = $self->store->all_status_names;
my @tasks = $self->load_tasks;
my %by_status;
for my $t (@tasks) {
push @{$by_status{$t->status}}, $t;
}
if ($self->json) {
my $board_name = $ec->{board}{name} // 'Kanban Board';
my %board_data = (
name => $board_name,
total => scalar @tasks,
columns => [],
);
for my $status (@statuses) {
my $tasks_in_status = $by_status{$status} // [];
my %col = (
status => $status,
count => scalar @$tasks_in_status,
tasks => [ map { $_->to_frontmatter } @$tasks_in_status ],
);
push @{$board_data{columns}}, \%col;
}
$self->print_json(\%board_data);
return;
}
if ($self->compact) {
for my $status (@statuses) {
my $tasks_in_status = $by_status{$status} // [];
my $count = scalar @$tasks_in_status;
my $ids = join(',', map { $_->id } @$tasks_in_status);
printf "%s(%d): %s\n", $status, $count, $ids || '-';
}
return;
}
my $board_name = $ec->{board}{name} // 'Kanban Board';
my $title = colored(" $board_name ", 'bold cyan on_black');
print "\n $title\n\n";
# Skip empty archived unless it has tasks
my @display_statuses = grep {
$_ ne 'archived' || @{$by_status{$_} // []}
} @statuses;
my $has_tasks = 0;
for my $status (@display_statuses) {
my $tasks = $by_status{$status} // [];
my $count = scalar @$tasks;
my $style = $STATUS_STYLE{$status} // 'white on_black';
my $header = uc($status);
printf " %s %s\n", colored(" $header ", $style), "[$count]";
if (@$tasks) {
$has_tasks = 1;
print " " . ('-' x 52) . "\n";
for my $t (@$tasks) {
my $id_str = colored(sprintf('#%d', $t->id), 'bold');
my $pri_color = $PRIORITY_COLOR{$t->priority} // 'white';
my $pri_str = colored($t->priority, $pri_color);
my $title = $t->title;
my @badges;
if ($t->has_claimed_by && $t->status ne 'done' && $t->status ne 'archived') {
push @badges, colored('@' . $t->claimed_by, 'cyan');
}
if ($t->has_blocked) {
push @badges, colored('BLOCKED', 'bold red');
}
if ($t->has_due) {
push @badges, colored('due:' . $t->due, 'yellow');
}
printf " %s %-8s %s", $id_str, $pri_str, $title;
printf " %s", join(' ', @badges) if @badges;
print "\n";
}
}
print "\n";
}
# Summary line
my $blocked = grep { $_->has_blocked } @tasks;
my $claimed = grep { $_->has_claimed_by && $_->status ne 'done' && $_->status ne 'archived' } @tasks;
my @summary;
push @summary, colored(scalar(@tasks) . ' tasks', 'bold');
push @summary, colored("$claimed claimed", 'cyan') if $claimed;
push @summary, colored("$blocked blocked", 'red') if $blocked;
printf " %s\n\n", join(' ', @summary);
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
App::karr::Cmd::Board - Show board summary
=head1 VERSION
version 0.301
=head1 SYNOPSIS
karr board
karr board --compact
karr board --json
=head1 DESCRIPTION
Renders a board-oriented summary grouped by status. The default output is a
human-friendly terminal dashboard with colors and task badges for claims,
blocked state, and due dates. Compact and JSON modes are available for
automation and scripting.
=head1 OUTPUT MODES
=over 4
=item * Default output
Shows statuses in board order with task counts and a task summary under each
populated column.
=item * C<--compact>
Prints one line per status in the form C<status(count): ids>.
=item * C<--json>
Emits the board name, total task count, and a structured C<columns> array with
per-status task lists.
=back
=head1 SEE ALSO
L<karr>, L<App::karr>, L<App::karr::Cmd::List>, L<App::karr::Cmd::Show>,
L<App::karr::Cmd::Pick>, L<App::karr::Cmd::Context>
=head1 SUPPORT
( run in 0.498 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )