Skip to content

feat: enhance table UI#6291

Merged
evankanderson merged 5 commits intomindersec:mainfrom
DharunMR:enhance-table-UI
Apr 10, 2026
Merged

feat: enhance table UI#6291
evankanderson merged 5 commits intomindersec:mainfrom
DharunMR:enhance-table-UI

Conversation

@DharunMR
Copy link
Copy Markdown
Contributor

@DharunMR DharunMR commented Apr 6, 2026

Summary

This PR overhauls the internal CLI table engine to provide a more professional and readable user interface across all Minder commands. By leveraging go-pretty/v6 more effectively, the CLI now supports visual grouping of data in terminal.

Key Improvements

  • Auto-Merging Logic: Implemented vertical merging for repetitive data in the first and second columns (e.g., Time, Entity, Owner). This reduces visual noise and groups related evaluation results or repositories into "blocks."
  • Dynamic Column Scaling: Replaced fixed width calculations with percentage-based distribution. The UI now intelligently allocates space based on column count, ensuring primary information (like Rule Definitions or Descriptions) gets the most room.
  • Terminal Boundary Protection: Implemented strict terminal width detection and enforced WrapSoft text wrapping. This prevents the "clipping" issue (the ≈ symbol) and ensures the table border always aligns with the terminal edge.
  • Unified Styling: Standardized the Rounded table style across all commands, including repo, profile, ruletype, history, project, and provider.

After Changes

swappy-20260407_120946
swappy-20260407_121023
swappy-20260407_121053
swappy-20260407_121111
swappy-20260407_121124
swappy-20260407_121157
swappy-20260407_121214

@DharunMR DharunMR requested a review from a team as a code owner April 6, 2026 16:22
@coveralls
Copy link
Copy Markdown

coveralls commented Apr 6, 2026

Coverage Status

coverage: 59.314% (-0.1%) from 59.418% — DharunMR:enhance-table-UI into mindersec:main

Copy link
Copy Markdown
Member

@evankanderson evankanderson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking at this! A few questions, but the new output doesn't look worse than the old (I don't have a strong opinion as to whether or not it's better, except that it seems like history list may have less data than before).

Comment thread cmd/cli/app/history/history_list.go
Comment thread cmd/cli/app/profile/table_render.go Outdated
Comment thread internal/util/cli/table/table.go Outdated
Comment thread cmd/cli/app/repo/repo_list.go Outdated
Comment thread cmd/cli/app/ruletype/common.go
Comment thread internal/util/cli/table/table.go
Comment thread internal/util/cli/table/table.go
Comment thread internal/util/cli/table/table.go Outdated
Comment thread internal/util/cli/table/table.go Outdated
@DharunMR
Copy link
Copy Markdown
Contributor Author

DharunMR commented Apr 7, 2026

Regarding the history list output I have verified this locally against the previous version, no data is being getting modified

Previously my approach based on a central columnSpecs map. This required manual updates every time a new command or header was added. My new approach uses updateWidths to track the actual maxColWidths of the data being injected. Removed borders in table

For Profile tables , I've implemented a SetEqualColumns toggle. Since profile data is highly structured, an equal distribution

I have updated the PR description with screenshots of every table output to demonstrate that the dynamic scaling

@DharunMR DharunMR force-pushed the enhance-table-UI branch 3 times, most recently from 4fa2ff2 to c217bd5 Compare April 7, 2026 12:31
@DharunMR DharunMR requested a review from evankanderson April 8, 2026 08:34
Copy link
Copy Markdown
Member

@evankanderson evankanderson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm liking the reduced dependencies for go-pretty over charmbracelet; a few comments and styling questions, but I think this is getting close.

Comment thread cmd/cli/app/datasource/common.go
Comment thread cmd/cli/app/profile/table_render.go Outdated
Comment thread cmd/cli/app/profile/table_render.go Outdated
// TODO: add automerge common cells (name/entity)
[]string{"Entity", "Rule Name", "Status", "Details"}).
SetAutoMerge(true).
SetEqualColumns(true)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Status" is usually short, and "Details" is often long on failure, so you may want to adjust those.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented a calculation in the Render logic that allocates terminal space based on the proportional length of the content in each column. This ensures the table works fine for every cmd

swappy-20260409_101836

Comment thread internal/util/cli/table/layouts/layouts.go
failureStatus = "failure"
errorStatus = "error"
skippedStatus = "skipped"
pendingStatus = "pending"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this?

Copy link
Copy Markdown
Contributor Author

@DharunMR DharunMR Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is unused so i removed (re-added it)

Comment thread internal/util/cli/table/common.go
AddRowWithColor(row ...layouts.ColoredColumn)
// Render outputs the table to stdout (TODO: make output configurable)
Render()
// SeparateRows ensures each row is clearly separated (probably because it is multi-line)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a comment for this method makes sense.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed the todo, will re-add 2nd comment

type Table interface {
AddRow(row ...string)
AddRowWithColor(row ...layouts.ColoredColumn)
// Render outputs the table to stdout (TODO: make output configurable)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooh! Now I see what's going on with the other PR -- it looks like table rendering doesn't use cmd.Out, huh?

How easy would that be to fix?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

Signed-off-by: DharunMR <maddharun56@gmail.com>
Signed-off-by: DharunMR <maddharun56@gmail.com>
Signed-off-by: DharunMR <maddharun56@gmail.com>
Signed-off-by: DharunMR <maddharun56@gmail.com>
evankanderson
evankanderson previously approved these changes Apr 10, 2026
Copy link
Copy Markdown
Member

@evankanderson evankanderson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks close enough that I'd like to merge it, despite a few cleanup items that you could open another PR for if you want.


renderRuleEvaluationStatusTable(resp.Data, historyTable, emoji)
historyTable.Render()
fmt.Println("")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want to update this output line, too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sry, I dont get what to update?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fmt.Println("") is going to write to os.Stdout; you probably want to change this to:

Suggested change
fmt.Println("")
w.Write("\n")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(But this can happen in your other testing PR)

// Ordering is fixed for evaluation history
// log and the next page points to older
// records.
msg := fmt.Sprintf("Older records: %s",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And these

Comment thread cmd/cli/app/profile/table_render.go Outdated

func marshalStructOrEmpty(v *structpb.Struct) string {
if v == nil {
if len(v.AsMap()) == 0 {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do the AsMap conversion once (or check len(v.GetFields()) here to avoid any conversion the first time).

Comment thread internal/util/cli/table/table.go
Comment thread internal/util/cli/table/table.go
Comment thread internal/util/cli/table/table.go Outdated
func (l *lipGlossTable) AddRow(row ...string) {
l.table.Row(row...)
l.rows++
func (l *goPrettyTable) SetAutoMerge(merge bool) Table {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be "g" for the object; I'm surprised none of the linters complained.

Comment thread internal/util/cli/table/table.go Outdated
if l.numCols > 0 {
// If we have a deficit or surplus due to integer rounding,
// adjust the last column to snap to the edge.
if assignedWidths[l.numCols-1]+diff > 0 {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be 5 to line up with "share", right?

Copy link
Copy Markdown
Contributor Author

@DharunMR DharunMR Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes wraping words too short will be hard to read, i changed it

Comment thread internal/util/cli/table/table.go Outdated

l.t.SetColumnConfigs(configs)

l.t.SetAllowedRowLength(w)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be deprecated in favor of:

Suggested change
l.t.SetAllowedRowLength(w)
l.t.Style.Size.WidthMax = w

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are absolutely right

@DharunMR
Copy link
Copy Markdown
Contributor Author

This looks close enough that I'd like to merge it, despite a few cleanup items that you could open another PR for if you want.

Yes i'll open a seperate pr for cleanup tonight

@evankanderson
Copy link
Copy Markdown
Member

The test failure appears to be legitimate, and does not appear in upstream/main. I think you can just drop the change from internal/datasources/rest/handler.go.

Signed-off-by: DharunMR <maddharun56@gmail.com>
@DharunMR
Copy link
Copy Markdown
Contributor Author

@evankanderson i've also made changes as recent suggestion

This looks close enough that I'd like to merge it, despite a few cleanup items that you could open another PR for if you want.

I have made changes, except this "You want to update this output line, too."


renderRuleEvaluationStatusTable(resp.Data, historyTable, emoji)
historyTable.Render()
fmt.Println("")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fmt.Println("") is going to write to os.Stdout; you probably want to change this to:

Suggested change
fmt.Println("")
w.Write("\n")


renderRuleEvaluationStatusTable(resp.Data, historyTable, emoji)
historyTable.Render()
fmt.Println("")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(But this can happen in your other testing PR)

@evankanderson evankanderson merged commit 8fb1b27 into mindersec:main Apr 10, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants