From a916ac0a4d66f00fa07ab3b700aee597afec9ad4 Mon Sep 17 00:00:00 2001 From: Hannah Brownson Date: Tue, 3 Mar 2026 17:09:23 -0500 Subject: [PATCH 1/8] feat: updating applications page to use trailhand table. Connecting new tag and action components as well --- .../pages/c/_cluster/applications/index.vue | 385 +++++++++++++----- 1 file changed, 280 insertions(+), 105 deletions(-) diff --git a/dashboard/pkg/epinio/pages/c/_cluster/applications/index.vue b/dashboard/pkg/epinio/pages/c/_cluster/applications/index.vue index ad6247c8..337f50f8 100644 --- a/dashboard/pkg/epinio/pages/c/_cluster/applications/index.vue +++ b/dashboard/pkg/epinio/pages/c/_cluster/applications/index.vue @@ -1,13 +1,10 @@ + + + + diff --git a/dashboard/pkg/epinio/detail/applications.vue b/dashboard/pkg/epinio/detail/applications.vue index 90db09fe..e9c053ab 100644 --- a/dashboard/pkg/epinio/detail/applications.vue +++ b/dashboard/pkg/epinio/detail/applications.vue @@ -10,17 +10,14 @@ import { GitUtils } from '@shell/utils/git'; import { isArray } from '@shell/utils/array'; import ConsumptionGauge from '@shell/components/ConsumptionGauge.vue'; import { APPLICATION_MANIFEST_SOURCE_TYPE, EPINIO_TYPES } from '../types'; -import DataTable from '../components/tables/DataTable.vue'; -import type { DataTableColumn } from '../components/tables/types'; -import BadgeStateFormatter from '@shell/components/formatter/BadgeStateFormatter.vue'; import PlusMinus from '@shell/components/form/PlusMinus.vue'; import { epinioExceptionToErrorsArray } from '../utils/errors'; import ApplicationCard from '../components/application/AppCardDetail.vue'; import Tabbed from '@shell/components/Tabbed/index.vue'; import Tab from '@shell/components/Tabbed/Tab.vue'; import AppGitDeployment from '../components/application/AppGitDeployment.vue'; -import Link from '@shell/components/formatter/Link.vue'; import Banner from '@components/Banner/Banner.vue'; +import { makeStateTag, makeActionMenu, makeCommitShaCell, makeCommitAuthorCell } from '../utils/table-formatters'; day.extend(relativeTime); @@ -42,11 +39,12 @@ const gitDeployment = ref({ commits: null as any }); -const instanceColumns: DataTableColumn[] = [ +const instanceColumns = [ { field: 'stateDisplay', label: 'State', - width: '100px' + width: '100px', + formatter: (_v: any, row: any) => makeStateTag(row) }, { field: 'name', @@ -73,11 +71,12 @@ const instanceColumns: DataTableColumn[] = [ } ]; -const serviceColumns: DataTableColumn[] = [ +const serviceColumns = [ { field: 'stateDisplay', label: 'State', - width: '100px' + width: '100px', + formatter: (_v: any, row: any) => makeStateTag(row) }, { field: 'nameDisplay', @@ -98,7 +97,7 @@ const serviceColumns: DataTableColumn[] = [ } ]; -const configColumns: DataTableColumn[] = [ +const configColumns = [ { field: 'nameDisplay', label: 'Name' @@ -220,16 +219,25 @@ const preparedCommits = computed(() => { })); }); -const gitCommitsColumns = computed(() => [ +const gitCommitsColumns = computed(() => [ { field: 'sha', label: t(`gitPicker.${gitType.value}.tableHeaders.sha.label`), - width: '100px' + width: '100px', + formatter: (_v: any, row: any) => makeCommitShaCell( + row, + gitDeployment.value.deployedCommit.long, + t('epinio.applications.detail.deployment.details.git.deployed') + ) }, { field: 'author_login', label: t(`gitPicker.${gitType.value}.tableHeaders.author.label`), - width: '190px' + width: '190px', + formatter: (_v: any, row: any) => makeCommitAuthorCell( + row, + t(`gitPicker.${gitType.value}.tableHeaders.author.unknown`) + ) }, { field: 'message', @@ -307,7 +315,7 @@ const commitPosition = computed(() => { - @@ -494,51 +502,16 @@ const commitPosition = computed(() => { > {{ t('epinio.applications.detail.deployment.commits.redeploy') }} - - - - - + /> @@ -554,57 +527,36 @@ const commitPosition = computed(() => { name="instances" :weight="3" > - - - + /> - - - + /> - - - + /> @@ -616,6 +568,11 @@ const commitPosition = computed(() => { .content { max-width: 1600px; } + +data-table { + --sortable-table-row-hover-bg: var(--sortable-table-hover-bg); + --sortable-table-header-hover-bg: var(--sortable-table-hover-bg); +} .simple-box-row { display: grid; grid-auto-columns: minmax(0, 1fr); diff --git a/dashboard/pkg/epinio/detail/catalogservices.vue b/dashboard/pkg/epinio/detail/catalogservices.vue index fa1e1f1a..8095aa2f 100644 --- a/dashboard/pkg/epinio/detail/catalogservices.vue +++ b/dashboard/pkg/epinio/detail/catalogservices.vue @@ -1,17 +1,14 @@ + + diff --git a/dashboard/pkg/epinio/list/configurations.vue b/dashboard/pkg/epinio/list/configurations.vue index b83dff95..524bfc1a 100644 --- a/dashboard/pkg/epinio/list/configurations.vue +++ b/dashboard/pkg/epinio/list/configurations.vue @@ -1,17 +1,15 @@ + - - - - - - + :searchable="true" + key-field="id" + @navigate="handleNavigate" + /> + diff --git a/dashboard/pkg/epinio/pages/c/_cluster/about.vue b/dashboard/pkg/epinio/pages/c/_cluster/about.vue index e7586c1b..eab1121a 100644 --- a/dashboard/pkg/epinio/pages/c/_cluster/about.vue +++ b/dashboard/pkg/epinio/pages/c/_cluster/about.vue @@ -7,6 +7,7 @@ import LabeledInput from '@components/Form/LabeledInput/LabeledInput.vue'; import { MANAGEMENT } from '@shell/config/types'; import { getVendor } from '@shell/config/private-label'; import { downloadFile } from '@shell/utils/download'; +import { makeEmptyCell } from '../../../utils/table-formatters'; const store = useStore(); @@ -21,13 +22,10 @@ const supportBundleSuccess = ref(''); const t = store.getters['i18n/t']; -const aboutVersionsComponentString = computed(() => t('about.versions.component')); const aboutTitleString = computed(() => t('about.title')); -const aboutVersionsVersionString = computed(() => t('about.versions.version')); const aboutDownloadCLIString = computed(() => t('about.downloadCLI.title')); const allPackagesString = computed(() => t('epinio.about.allPackages')); - const fetchData = async() => { fetchError.value = ''; @@ -63,6 +61,8 @@ function createOSOption(label: string, icon: string, cliLink: string, imageList: }; } +const downloadLinuxImages = null; + const downloads = computed(() => { if (!version.value) { return []; @@ -79,8 +79,6 @@ const downloads = computed(() => { ]; }); -const downloadLinuxImages = null; - const versionString = computed(() => { if (!version.value) return ''; if (version.value.displayVersion === version.value.fullVersion) { @@ -142,6 +140,67 @@ const downloadSupportBundle = async() => { } }; +// Versions table +const versionRows = computed(() => { + if (!version.value) return []; + return [{ name: appName.value, version: versionString.value }]; +}); + +const versionColumns = [ + { + field: 'name', + label: t('about.versions.component'), + formatter: (_v: any, row: any) => { + const a = document.createElement('a'); + + a.href = 'https://github.com/epinio/epinio'; + a.target = '_blank'; + a.rel = 'nofollow noopener noreferrer'; + a.textContent = row.name; + + return a; + } + }, + { + field: 'version', + label: t('about.versions.version') + } +]; + +// Downloads table +const downloadColumns = [ + { + field: 'label', + label: t('about.versions.component'), // re-use "Component" as Platform header + formatter: (_v: any, row: any) => { + const div = document.createElement('div'); + + div.style.cssText = 'display:flex; align-items:center;'; + + const icon = document.createElement('i'); + + icon.className = `icon ${ row.icon } mr-5`; + div.appendChild(icon); + div.appendChild(document.createTextNode(t(row.label))); + + return div; + } + }, + { + field: 'cliFile', + label: t('about.downloadCLI.title'), + formatter: (_v: any, row: any) => { + if (!row.cliLink) return makeEmptyCell(); + + const a = document.createElement('a'); + + a.href = row.cliLink; + a.textContent = row.cliFile; + + return a; + } + } +]; @@ -271,6 +274,7 @@ const columns = [ data-table { --sortable-table-row-hover-bg: var(--sortable-table-hover-bg); --sortable-table-header-hover-bg: var(--sortable-table-hover-bg); + --sortable-table-header-sorted-bg: var(--sortable-table-hover-bg); } diff --git a/dashboard/pkg/epinio/list/services.vue b/dashboard/pkg/epinio/list/services.vue index c1bdee26..661ea42e 100644 --- a/dashboard/pkg/epinio/list/services.vue +++ b/dashboard/pkg/epinio/list/services.vue @@ -7,7 +7,7 @@ import { EPINIO_TYPES } from '../types'; import { startPolling, stopPolling } from '../utils/polling'; import Masthead from '@shell/components/ResourceList/Masthead'; import { createEpinioRoute } from '../utils/custom-routing'; -import { makeStateTag, makeRouterLink, makeRouterLinksOrEmpty } from '../utils/table-formatters'; +import { makeStateTag, makeRouterLink, makeRouterLinksOrEmpty, makeActionMenu } from '../utils/table-formatters'; defineProps<{ schema: object, @@ -99,7 +99,8 @@ const columns = [ diff --git a/dashboard/pkg/epinio/pages/c/_cluster/about.vue b/dashboard/pkg/epinio/pages/c/_cluster/about.vue index eab1121a..b95fdbcf 100644 --- a/dashboard/pkg/epinio/pages/c/_cluster/about.vue +++ b/dashboard/pkg/epinio/pages/c/_cluster/about.vue @@ -313,6 +313,7 @@ const downloadColumns = [ .downloads-table { --sortable-table-row-hover-bg: var(--sortable-table-hover-bg); --sortable-table-header-hover-bg: var(--sortable-table-hover-bg); + --sortable-table-header-sorted-bg: var(--sortable-table-hover-bg); } } diff --git a/dashboard/pkg/epinio/pages/c/_cluster/applications/index.vue b/dashboard/pkg/epinio/pages/c/_cluster/applications/index.vue index fab809be..e0dfa2dd 100644 --- a/dashboard/pkg/epinio/pages/c/_cluster/applications/index.vue +++ b/dashboard/pkg/epinio/pages/c/_cluster/applications/index.vue @@ -233,6 +233,7 @@ onUnmounted(() => { data-table { --sortable-table-row-hover-bg: var(--sortable-table-hover-bg); --sortable-table-header-hover-bg: var(--sortable-table-hover-bg); + --sortable-table-header-sorted-bg: var(--sortable-table-hover-bg); } } diff --git a/dashboard/pkg/epinio/pages/index.vue b/dashboard/pkg/epinio/pages/index.vue index 0a895aa3..3682ab27 100644 --- a/dashboard/pkg/epinio/pages/index.vue +++ b/dashboard/pkg/epinio/pages/index.vue @@ -246,7 +246,7 @@ const columns = [ /> From 916d755a82f939134ad7df64ac985793d460f5ab Mon Sep 17 00:00:00 2001 From: Hannah Brownson Date: Mon, 9 Mar 2026 10:42:48 -0400 Subject: [PATCH 4/8] fix: adding additional icons to deployed and not ready status --- dashboard/pkg/epinio/utils/table-formatters.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dashboard/pkg/epinio/utils/table-formatters.ts b/dashboard/pkg/epinio/utils/table-formatters.ts index 98af2794..551b99b3 100644 --- a/dashboard/pkg/epinio/utils/table-formatters.ts +++ b/dashboard/pkg/epinio/utils/table-formatters.ts @@ -201,8 +201,12 @@ export function stateToTagVariant(state: string): string { */ export function stateToIcon(state: string): string { switch (state) { - case 'running': return 'rocket'; - case 'error': return 'error'; + case 'running': + case 'deployed': return 'rocket'; + case 'notready': + case 'not-ready': return 'warning'; + case 'error': + case 'fail': return 'error'; case 'building': return 'tools'; case 'created': return 'gear'; default: return ''; From be809472ab727ee7ee3467295079b3ec9a0c8304 Mon Sep 17 00:00:00 2001 From: Hannah Brownson Date: Mon, 9 Mar 2026 10:59:50 -0400 Subject: [PATCH 5/8] chore: updating component names from trailhand. --- dashboard/package.json | 2 +- .../pkg/epinio/components/application/AppProgress.vue | 4 ++-- .../pkg/epinio/components/application/GitPicker.vue | 6 +++--- dashboard/pkg/epinio/detail/applications.vue | 10 +++++----- dashboard/pkg/epinio/detail/catalogservices.vue | 4 ++-- dashboard/pkg/epinio/list/appcharts.vue | 4 ++-- dashboard/pkg/epinio/list/configurations.vue | 4 ++-- dashboard/pkg/epinio/list/namespaces.vue | 4 ++-- dashboard/pkg/epinio/list/services.vue | 4 ++-- dashboard/pkg/epinio/pages/c/_cluster/about.vue | 4 ++-- .../pkg/epinio/pages/c/_cluster/applications/index.vue | 8 ++++---- dashboard/pkg/epinio/pages/index.vue | 4 ++-- dashboard/pkg/epinio/utils/table-formatters.ts | 2 +- dashboard/yarn.lock | 8 ++++---- 14 files changed, 34 insertions(+), 34 deletions(-) diff --git a/dashboard/package.json b/dashboard/package.json index e96a7dab..d621368c 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -5,7 +5,7 @@ "node": ">=20" }, "dependencies": { - "@krumio/trailhand-ui": "^1.9.1", + "@krumio/trailhand-ui": "^1.9.2", "@rancher/shell": "3.0.7", "@types/lodash": "^4.17.16", "eslint": "^9.28.0", diff --git a/dashboard/pkg/epinio/components/application/AppProgress.vue b/dashboard/pkg/epinio/components/application/AppProgress.vue index b44c539f..95867c09 100644 --- a/dashboard/pkg/epinio/components/application/AppProgress.vue +++ b/dashboard/pkg/epinio/components/application/AppProgress.vue @@ -211,7 +211,7 @@ onMounted(createActions); class="progress-container" >
- (() => const selectedCommitId = computed(() => selectedCommit.value?.commitId); -// Columns for data-table +// Columns for trailhand-table const columns = computed(() => [ { field: 'commitId', @@ -380,7 +380,7 @@ watch(() => props.value, async(neu, old) => { v-if="selectedBranch && preparedCommits.length" class="commits-table mt-20" > - props.value, async(neu, old) => { margin: 0 1px; max-width: 1400px; - data-table { + trailhand-table { --sortable-table-row-hover-bg: var(--sortable-table-hover-bg); --sortable-table-header-hover-bg: var(--sortable-table-hover-bg); --sortable-table-header-sorted-bg: var(--sortable-table-hover-bg); diff --git a/dashboard/pkg/epinio/detail/applications.vue b/dashboard/pkg/epinio/detail/applications.vue index 6a7363e7..a86f8ac5 100644 --- a/dashboard/pkg/epinio/detail/applications.vue +++ b/dashboard/pkg/epinio/detail/applications.vue @@ -502,7 +502,7 @@ const commitPosition = computed(() => { > {{ t('epinio.applications.detail.deployment.commits.redeploy') }} - { name="instances" :weight="3" > - { name="services" :weight="2" > - { name="configs" :weight="1" > - { max-width: 1600px; } -data-table { +trailhand-table { --sortable-table-row-hover-bg: var(--sortable-table-hover-bg); --sortable-table-header-hover-bg: var(--sortable-table-hover-bg); --sortable-table-header-sorted-bg: var(--sortable-table-hover-bg); diff --git a/dashboard/pkg/epinio/detail/catalogservices.vue b/dashboard/pkg/epinio/detail/catalogservices.vue index 79fa04d1..80c6f2ee 100644 --- a/dashboard/pkg/epinio/detail/catalogservices.vue +++ b/dashboard/pkg/epinio/detail/catalogservices.vue @@ -67,7 +67,7 @@ const columns = [

{{ t('epinio.catalogService.detail.servicesTitle', { catalogService: props.value.name }) }}

-