Skip to content

[11513] Added workload-dashboard#17728

Draft
marcelofukumoto wants to merge 28 commits into
rancher:masterfrom
marcelofukumoto:11513-replace-workloads-page-list-with-an-overview-page
Draft

[11513] Added workload-dashboard#17728
marcelofukumoto wants to merge 28 commits into
rancher:masterfrom
marcelofukumoto:11513-replace-workloads-page-list-with-an-overview-page

Conversation

@marcelofukumoto
Copy link
Copy Markdown
Member

@marcelofukumoto marcelofukumoto commented May 19, 2026

Summary

Fixes #11513

Occurred changes and/or fixed issues

  • Added a WORKLOAD DASHBOARD

Technical notes summary

  • Used the new SUMMARY API

Areas or cases that should be tested

  • WORKLOAD API is a standalone page

Areas which could experience regressions

  • Changes to StatusCard/Status Row to remove percentage
  • Changes to StatusCard and StatusRow to accept links

Screenshot/Video

Checklist

  • The PR is linked to an issue and the linked issue has a Milestone, or no issue is needed
  • The PR has a Milestone
  • The PR template has been filled out
  • The PR has been self reviewed
  • The PR has a reviewer assigned
  • The PR has automated tests or clear instructions for manual tests and the linked issue has appropriate QA labels, or tests are not needed
  • The PR has reviewed with UX and tested in light and dark mode, or there are no UX changes
  • The PR has been reviewed in terms of Accessibility
  • The PR has considered, and if applicable tested with, the three Global Roles Admin, Standard User and User Base

@marcelofukumoto marcelofukumoto changed the title Added workload-dashboard [11513] Added workload-dashboard May 19, 2026
@rancher-ui-project-bot rancher-ui-project-bot Bot added this to the v2.15.0 milestone May 19, 2026
Comment thread shell/components/Resource/Detail/Card/StatusCard/index.vue
Comment thread shell/components/Resource/Detail/Card/StatusCard/index.vue Outdated
Comment thread shell/components/Resource/Detail/Card/index.vue Outdated
Comment thread shell/components/Resource/Detail/StatusRow.vue Outdated
Comment thread shell/config/product/explorer.js
Comment thread shell/config/product/explorer.js
Comment thread shell/config/router/routes.js
Comment thread shell/pages/c/_cluster/explorer/workload-dashboard.vue Outdated
Comment thread shell/pages/c/_cluster/explorer/workload-dashboard.vue Outdated
@marcelofukumoto marcelofukumoto marked this pull request as ready for review May 19, 2026 15:14
@@ -0,0 +1,561 @@
<script>
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.

Can we ensure that new components are written in typescript, where possible?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good point!
Let me change to CompositionAPI as well.

@marcelofukumoto marcelofukumoto marked this pull request as draft May 19, 2026 22:11
Comment thread shell/components/SubtleLink.vue
Comment thread shell/components/Resource/Detail/StatusRow.vue Outdated
Comment thread shell/mixins/resource-fetch-api-pagination.js Outdated
Comment thread shell/store/prefs.js Outdated
Comment thread shell/pages/c/_cluster/explorer/workload-dashboard.vue Outdated
Comment thread shell/pages/c/_cluster/explorer/workload-dashboard.vue Outdated
Comment thread shell/pages/c/_cluster/explorer/workload-dashboard.vue Outdated
fetchAll: Failed to fetch workload summaries
empty:
title: No workloads to show
message: "Tips: undo the last namespace filter you applied or <resetLink>reset the namespaces filter</resetLink>."
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 use case is different, the user may have not set any and the default only user namespaces is used

Suggested change
message: "Tips: undo the last namespace filter you applied or <resetLink>reset the namespaces filter</resetLink>."
message: "Tips: Update the namespace filter above or <resetLink>reset the namespaces filter</resetLink>."

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This one is provided by @oboc-sts from the Figma.
Let me ask him to check here directly.

Copy link
Copy Markdown

@oboc-sts oboc-sts May 27, 2026

Choose a reason for hiding this comment

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

I totally missed the "suggested change"...

Yeah, we can go with the suggestion @richard-cox made above, it makes sense, I like it ;)

import { StateColor } from '@shell/utils/style';
import { computed } from 'vue';
import { useStore } from 'vuex';
import type { RouteLocationRaw } from 'vue-router';
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.

@codyrancher would you be able to review these component updates / new components? your composition api fu is greater than mine

</script>

<template>
<div
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 need to restrict the max width on these to avoid scenarios where the label is miles away from the value

Image

could have the box the same size bit limit the label-->value gap? or just restrict the box? will leave that with you and UX

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.

same also applies to the by type cards (though not as bad)

Image

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.

original comment resolved. we can monitor the second and address later on

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What's the resolution on these 2 points (max-width for the page content = byState and byType cards) ?

I had a conversation with @marcelofukumoto some time ago and I remember we touched upon this topic...

Copy link
Copy Markdown
Member Author

@marcelofukumoto marcelofukumoto May 27, 2026

Choose a reason for hiding this comment

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

For 3 columns it turned out like this:
image

For 2 columns like this:
image

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think you've pasted the wrong screenshot :P (I hope at least :D )

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Right! Sorry! Updated correctly now!

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looking good!

<!-- ━━━ By State ━━━ -->
<div class="section">
<h4 class="m-0 text-muted">
{{ t('workloadDashboard.sections.byState') }}
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.

should these be muted? they look a little hidden in dark mode

Image Image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

You are right! That byState is technically the deemphasized one. Changed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@marcelofukumoto can the 2 of us review everything once again after the code review has been finished? I want to make sure we haven't deviated too much from the last conversation we had. Feel free to send an invite at your convenience...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Sure! As soon as we finish here we should have a final review before the merge.

}
}

:deep(.state-card) {
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.

is there anyway we can avoid this :deep?

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.

another one for a prop

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Hmm Ok! Added as a prop.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed the usage of GAP as well and changed to margin. Than I dont need the deep.


.state-card {
border: 0;
:deep(.resource-row) {
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.

:deep

think this one would benefit from a propin the StateCard component. something like sparse?

can also position the state dot (left / right) with a prop (stateDotPostition)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I called it compact and added to the ResourceRow, following some of the line-height and other things from Figma.

&--full {
grid-column: 1 / -1;

:deep(.body) {
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.

a few more for a prop

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ok! Moved to a prop!


await Promise.all(batch.map(async([stateKey, { originalName, type }]) => {
try {
const url = `/v1/${ type }?limit=1&filter=metadata.state.name=${ originalName }`;
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.

Suggested change
const url = `/v1/${ type }?limit=1&filter=metadata.state.name=${ originalName }`;
const url = `/v1/${ type }?pagesize=1&filter=metadata.state.name=${ originalName }`;

limit is a native kube api param and doesn't work with vai requests. the vai filter means we're going through a different path and so we need to use pagesize instead

though i would go down the path of using steve-pagination-utils createParamsForPagination to create the url here as well. that keeps this code nicely isolated from that shenanigans

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Changed!

const all = store.getters['prefs/get'](STATE_COLOR_MAP) || {};
const current = all[clusterId.value] || {};

store.dispatch('prefs/set', {
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 just caches in vuex (preference isn't stored in a cookie or via api), so we don't really get anything above caching globally in this file?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed. So that means I can just cache in the file? Seems ok for me!

Changed to only cache in the file.

const stateColorMap = computed<Record<string, StateColor>>(() => {
const all = store.getters['prefs/get'](STATE_COLOR_MAP) || {};

return all[clusterId.value] || {};
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've got stuck caching things by cluster before (without manually clearing out entries that no longer exist). lets gamble and make them global

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Since removed the prefs/set usage at all. All good. Not going to have that anymore

@marcelofukumoto marcelofukumoto force-pushed the 11513-replace-workloads-page-list-with-an-overview-page branch 2 times, most recently from dff7069 to 201d7bd Compare May 26, 2026 21:01
showPercent?: boolean;
noResourcesMessage?: string;
to?: RouteLocationRaw;
rowTo?: RouteLocationRaw | string;
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.

RouteLocationRaw already includes string, so | string appears to be redundant.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not using this anymore! Thanks

props.resources?.forEach((resource: any) => {
accumulator[resource.stateDisplay] = accumulator[resource.stateDisplay] || { count: 0 };
accumulator[resource.stateDisplay].count++;
accumulator[resource.stateDisplay] = accumulator[resource.stateDisplay] || { count: 0, stateId: resource.stateId || resource.stateDisplay };
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 believe that falling back on stateDisplay for stateId could cause a problem since the stateId is used to create query strings. I don't think In Progress in the query string is what was intended.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not using stateDisplay anymore! Only the ID

return;
}

router.push(to);
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 user can't select text with this change. Upon release the mouse the user will navigate to the next page.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed this one! Thanks!

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 have a feeling you may want to create a new component rather than extending this card and the status card.

This was largely intended to implement the summary cards in the design system but we haven't moved it into rancher components yet. https://www.figma.com/design/K3e7DHHM5TsS0vQELeoIFZ/Rancher-DS?node-id=676-159&m=dev

I think we may want to create a new card with a new intent. I think you could move and reuse some of the useful bits from status card and create the new one.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I will create a new component! I think that is the best for now. And I will fix the other issues on the new component

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Created new components. A lot cleaner. The components have no complexity and as you shared the previous components were not created to be shared. Reduced the files changed as well.

Comment on lines +37 to +42
class="detail-card"
:class="{ clickable: clickable }"
:role="clickable ? 'link' : undefined"
:tabindex="clickable ? 0 : undefined"
@click="handleClick"
@keyup.enter="handleClick"
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.

It looks like we're missing relevant accessibility attributes. Maybe aria-label and role.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Improved accessibility! Thanks for the tip.

@marcelofukumoto
Copy link
Copy Markdown
Member Author

@richard-cox there are big changes to the components since I moved to not use the Card and StatusCard

Then avoiding all the props or :deep to make it work. The code is a lot cleaner for sure.

The only component I decided to keep is the SubtleLink since it is used on some special places and I added the icon with the open in new tab only.

The code is ready to be reviewed again.

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.

Create Workloads overview page

5 participants