Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: table component #4545

Merged
merged 4 commits into from Nov 17, 2023
Merged

feat: table component #4545

merged 4 commits into from Nov 17, 2023

Conversation

deboer-tim
Copy link
Collaborator

@deboer-tim deboer-tim commented Oct 27, 2023

What does this PR do?

This is a clean, rebased branch of the table component after previous review comments in this PR.

We have impending technical debt where our expanding number of table components (images, volumes, pods, containers, soon adding Kubernetes objects) will cross with our future design ideas (tables should be sortable, columns configurable, environments groupable, etc). We can't copy/paste these features into every page, and deal with differences between them.

Each page passes an array of objects and Columns to the Table component, which is responsible for creating the basic layout and calling back to the Column renderer to render each cell in the table. The Table uses grid layout and provides enough abstraction that we can implement additional features later. (e.g. optional columns, column reordering, or resizing. grouping. etc)

The Table provides sorting & sort indicators, and tests are included. Support for 'object containers/grouping' in order to support Container list will be done separately since this is already a big PR.

Screenshot/screencast of this PR

Before:

Screenshot 2023-11-16 at 11 04 40 AM

After:

Screenshot 2023-11-15 at 12 40 46 PM

What issues does this PR fix or reference?

Fixes #4365.

How to test this PR?

PR tests; separate PRs for Images and Volumes coming shortly.

@deboer-tim
Copy link
Collaborator Author

Updated commit to make columns named instead of numbered, and a little cleanup and renaming. Still not entirely sure how the column/row styling should work in the Column interface, still iterating there.

Added sorting just to prove it was possible. There is no sort indicator on the column header yet and a few columns should sort by value instead of alphabetically, but it works.

@benoitf
Copy link
Collaborator

benoitf commented Nov 6, 2023

hi, from what I've seen, and I think @cdrage did some investigations long time ago, we should use grid system and not table

@deboer-tim
Copy link
Collaborator Author

Pinged Charlie, he's checked all his old branches and forks and can't find any of the code from that investigation.

I'm somewhat hesitant to switch to grid here since that will hold this up and do 'multiple things' in one PR... but adopting this on a page is also the ideal time to switch, so I'll give it a try.

@benoitf
Copy link
Collaborator

benoitf commented Nov 6, 2023

#885

@deboer-tim
Copy link
Collaborator Author

Updated description, added video, and force-pushed the latest rebased on main. A lot has changed since the last update and would appreciate feedback so that I can address issues before this moves out of draft state.

Copy link
Contributor

@cdrage cdrage left a comment

Choose a reason for hiding this comment

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

Amazing! I'm able to actually organize it by age / alphabetical whenever I want. so big 👍

With regards to table helper, I'm assuming we have to make a new helper for each list scenario for Pods / Containers / etc?

I'm good with the concept of using TableHelper to make it generic and then "extending" it for different use cases. As honestly it seems like the best way to make it as "generic" as possible considering how difficult it is with other tables / etc.

I'm assuming this will scale well with the other lists we are implementing too

cdrage
cdrage previously requested changes Nov 9, 2023
packages/renderer/src/lib/image/ImagesList.svelte Outdated Show resolved Hide resolved
packages/renderer/src/lib/volume/VolumesList.svelte Outdated Show resolved Hide resolved
@deboer-tim
Copy link
Collaborator Author

Added new commit:

Lots of changes based on review comments:

  • Added a Type to Column and moved the comparator to it. This makes the Column[] creation a little longer, but the typing works well and keeps the TableHelper minimal.
  • Renamed 'objects' to 'data'.
  • Added the type to ImageRow/VolumeRow - but these are about to change drastically in the next step...
  • Florent had a comment about trying ageColumn.setRenderingTemplate() similar to setComparator(). I had thought about this before and was worried about lots of tiny components, but gave it a shot. Many of these are indeed tiny, but it does provide nice componentization (possible to share some of these between types later?) and gets rid of the big if/switch block.
  • Every column needs a renderer - so removed the function and just made it part of the constructor for simpler code.
  • At this point it seemed like actions should just be a regular column too. Making this change simplified things a little.

Overall I like these changes; simpler implementation and easier/safer to use for consumers. I am still having trouble with the grid layout misbehaving though.

Copy link
Collaborator

@benoitf benoitf left a comment

Choose a reason for hiding this comment

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

much more simple, nice work
I still believe we might simplify again as number of parameters will grow and we won't be able to scale easily or without like lots of param1, undefined, undefined, param2 like in parameters at some points

packages/renderer/src/lib/image/ImagesList.svelte Outdated Show resolved Hide resolved
packages/renderer/src/lib/image/ImagesList.svelte Outdated Show resolved Hide resolved
Copy link
Contributor

@lstocchi lstocchi left a comment

Choose a reason for hiding this comment

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

I tried it and looks fine. Waiting to being ready to play with it more.

packages/renderer/src/lib/table/Table.svelte Outdated Show resolved Hide resolved
This is a clean branch of the table component after previous review comments
in PR #4545.

Each page passes an array of objects and Columns to the Table component, which
is responsible for creating the basic layout and calling back to the Column
renderer to render each cell in the table. The Table uses grid layout and
provides enough abstraction that we can implement additional features later.
(e.g. optional columns, column reordering, or resizing. grouping. etc)

The Table provides sorting & sort indicators, and tests are included.
Support for 'object containers/grouping' in order to support Container list
will be done separately since this is already a big PR.

Fixes #4365.

Signed-off-by: Tim deBoer <git@tdeboer.ca>
@deboer-tim deboer-tim marked this pull request as ready for review November 16, 2023 16:06
@deboer-tim deboer-tim requested a review from a team as a code owner November 16, 2023 16:06
@deboer-tim deboer-tim requested review from dgolovin and lstocchi and removed request for a team November 16, 2023 16:06
@deboer-tim
Copy link
Collaborator Author

Clean branch (without Images/Volumes) pushed, PR comment updated, and draft status removed. Ready for final review.

@benoitf benoitf requested a review from cdrage November 16, 2023 16:30
deboer-tim added a commit that referenced this pull request Nov 16, 2023
Switches the Volume page to the new table component. Columns are extracted
as expected, and I've pulled out the engine into an Environment column to
match the Pods page.

I made all the columns sortable. The raw size had to be made visible from
VolumeInfoUI because the regular column is humanized and not sortable.
Status and size are 'reverse sorted' because you typically want to see
used volumes and bigger things first.

Based on the Table PR #4545. Ignore everything in /table/* and once that
has merged I'll rebase.

Signed-off-by: Tim deBoer <git@tdeboer.ca>
deboer-tim added a commit that referenced this pull request Nov 16, 2023
Switches the Images page to the new table component. Columns are extracted
as expected, and I've pulled out the engine into an Environment column to
match the Pods page.

I made all the columns sortable. The raw size had to be made visible from
ImageInfoUI because the regular column is humanized and not sortable.
Status and size are 'reverse sorted' because you typically want to see
used images and bigger things first.

Based on the Table PR #4545. Ignore everything in /table/* and once that
has merged I'll rebase.

Signed-off-by: Tim deBoer <git@tdeboer.ca>
This was referenced Nov 16, 2023
packages/renderer/src/lib/table/Table.svelte Outdated Show resolved Hide resolved
Comment on lines 36 to 38
const toggleData = data;
toggleData.filter(object => row.selectable?.(object)).forEach(object => (object.selected = checked));
data = toggleData;
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the purpose of using the toggleData temp variable? As toggleData is a reference to data, it does not seem necessary to me

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You can see this was actually unchanged from before. Svelte only detects changed objects, not internal state, so sometimes you have to explicitly assign something to see the change visually. I did some testing and this doesn't seem to be required anymore, so I removed it.

The same thing existed further down on line 64 with sorting. This one is required, but I can see the same question arising so I changed it to an explicit 'data = data.sort()', and added the required no-mutation comment. I don't think this is any better code-wise, but at least it's obvious it was intentional.

Copy link
Contributor

Choose a reason for hiding this comment

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

Now that you tell me the reason, I remember I effectively had to write some data = [...data] in some other PR, to make the refresh happen. Not sure what is the recommended way to handle this

Copy link
Contributor

Choose a reason for hiding this comment

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

In this article, it is explained that data = data is enough to trigger the Svelte changes.

https://javascript.plainenglish.io/update-arrays-and-objects-in-svelte-40c6a84f8a28

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've seen it elsewhere too so it seem to be a common way of handling it. For now though sort is the only place that needs it and eslint comment make it clear the code is intentional.

packages/renderer/src/lib/table/table.ts Outdated Show resolved Hide resolved
packages/renderer/src/lib/table/table.ts Outdated Show resolved Hide resolved
Changes:
- Moved comparator into ColumnInformation to make things more functional.
- Moved Row selection and disabledText into RowInformation object; now
  everything matches as well.
- Last item required me to put in a few more undefined checks and I
  questioned why we'd have a checkbox column if items aren't selectable,
  so I removed it entirely in that case (i.e. if there is no selectable
  then the checkbox column is removed entirely).
- Removed unnecessary assignment to toggleData and replaced sort with
  reassignment (and es-lint mutation override).
- Added missing type in TestTable.

Signed-off-by: Tim deBoer <git@tdeboer.ca>
Copy link
Contributor

@lstocchi lstocchi left a comment

Choose a reason for hiding this comment

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

LGTM

// number of selected items in the list
export let selectedItemsNumber: number = 0;
$: selectedItemsNumber = row.info.selectable
? data.filter(object => row.info.selectable?.(object)).filter(object => object.selected).length
Copy link
Contributor

@lstocchi lstocchi Nov 17, 2023

Choose a reason for hiding this comment

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

any reason why you don't merge the two filters? data.filter(object => row.info.selectable?.(object) && object.selected)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

None at all, I just copied from ImagesList and VolumesList and didn't think to fix. :) I'll do it in follow-up PR.

deboer-tim added a commit that referenced this pull request Nov 17, 2023
This is a clean branch of the table component after previous review comments
in PR #4545.

Each page passes an array of objects and Columns to the Table component, which
is responsible for creating the basic layout and calling back to the Column
renderer to render each cell in the table. The Table uses grid layout and
provides enough abstraction that we can implement additional features later.
(e.g. optional columns, column reordering, or resizing. grouping. etc)

The Table provides sorting & sort indicators, and tests are included.
Support for 'object containers/grouping' in order to support Container list
will be done separately since this is already a big PR.

Fixes #4365.

Signed-off-by: Tim deBoer <git@tdeboer.ca>
@deboer-tim deboer-tim dismissed cdrage’s stale review November 17, 2023 17:33

Changes were addressed, two other approvals, and Charlie on vacation.

@deboer-tim deboer-tim merged commit 127b19b into main Nov 17, 2023
9 checks passed
@deboer-tim deboer-tim deleted the table-comp branch November 17, 2023 17:33
deboer-tim added a commit that referenced this pull request Nov 17, 2023
This is a clean branch of the table component after previous review comments
in PR #4545.

Each page passes an array of objects and Columns to the Table component, which
is responsible for creating the basic layout and calling back to the Column
renderer to render each cell in the table. The Table uses grid layout and
provides enough abstraction that we can implement additional features later.
(e.g. optional columns, column reordering, or resizing. grouping. etc)

The Table provides sorting & sort indicators, and tests are included.
Support for 'object containers/grouping' in order to support Container list
will be done separately since this is already a big PR.

Fixes #4365.

Signed-off-by: Tim deBoer <git@tdeboer.ca>
deboer-tim added a commit that referenced this pull request Nov 17, 2023
Switches the Volume page to the new table component. Columns are extracted
as expected, and I've pulled out the engine into an Environment column to
match the Pods page.

I made all the columns sortable. The raw size had to be made visible from
VolumeInfoUI because the regular column is humanized and not sortable.
Status and size are 'reverse sorted' because you typically want to see
used volumes and bigger things first.

Based on the Table PR #4545. Ignore everything in /table/* and once that
has merged I'll rebase.

Signed-off-by: Tim deBoer <git@tdeboer.ca>
@podman-desktop-bot podman-desktop-bot added this to the 1.6.0 milestone Nov 17, 2023
deboer-tim added a commit that referenced this pull request Nov 23, 2023
Switches the Volume page to the new table component. Columns are extracted
as expected, and I've pulled out the engine into an Environment column to
match the Pods page.

I made all the columns sortable. The raw size had to be made visible from
VolumeInfoUI because the regular column is humanized and not sortable.
Status and size are 'reverse sorted' because you typically want to see
used volumes and bigger things first.

Based on the Table PR #4545. Ignore everything in /table/* and once that
has merged I'll rebase.

Signed-off-by: Tim deBoer <git@tdeboer.ca>
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.

Reusable table component
6 participants