Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"node": ">=20"
},
"dependencies": {
"@krumio/trailhand-ui": "^1.9.0",
"@krumio/trailhand-ui": "^1.9.2",
"@rancher/shell": "3.0.7",
"@types/lodash": "^4.17.16",
"eslint": "^9.28.0",
Expand Down
118 changes: 58 additions & 60 deletions dashboard/pkg/epinio/components/application/AppProgress.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
<script lang="ts" setup>
import { ref, computed, watch, onMounted } from 'vue';
import { ref, computed, watch, onMounted, reactive } from 'vue';
import { useStore } from 'vuex';

import SortableTable from '@shell/components/SortableTable/index.vue';
import Checkbox from '@components/Form/Checkbox/Checkbox.vue';
import BadgeState from '@components/BadgeState/BadgeState.vue';

import ApplicationAction, { APPLICATION_ACTION_TYPE } from '../../models/application-action';
import { STATE, DESCRIPTION } from '@shell/config/table-headers';
import {
EPINIO_TYPES,
APPLICATION_ACTION_STATE,
EPINIO_TYPES,
APPLICATION_SOURCE_TYPE,
EpinioApplication,
EpinioAppSource,
EpinioAppBindings
} from '../../types';
import type EpinioNamespace from '../../models/namespaces';
import { makeProgressStateCell } from '../../utils/table-formatters';

const props = defineProps<{
application: EpinioApplication,
Expand All @@ -29,33 +24,63 @@ const props = defineProps<{
const emit = defineEmits(['finished']);

const store = useStore();
const t = store.getters['i18n/t'];

const running = ref(false);
const actions = ref<ApplicationAction[]>([]);

const actionHeaders = [
const columns = [
{
name: 'epinio-name',
labelKey: 'epinio.applications.steps.progress.table.stage.label',
value: 'name',
sort: ['index'],
width: 150,
field: 'name',
label: t('epinio.applications.steps.progress.table.stage.label'),
width: '150px',
sortable: false,
},
{
...DESCRIPTION,
sort: undefined,
value: 'description',
width: 450,
field: 'description',
label: t('tableHeaders.description'),
width: '450px',
sortable: false,
formatter: (_v: any, row: any) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Looks like there is some formatting issues here.

Image

Copy link
Collaborator

Choose a reason for hiding this comment

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

still getting this on failure

const wrapper = document.createElement('span');

wrapper.style.cssText = 'display:flex; flex-direction:column;';

const main = document.createElement('span');

main.textContent = row.description || '';
wrapper.appendChild(main);

// stateMessage is set on failure — show it as secondary error text
if (row.stateMessage) {
const sub = document.createElement('span');

sub.style.cssText = 'font-size:0.85em; color:var(--error); margin-top:2px;';
sub.textContent = row.stateMessage;
wrapper.appendChild(sub);
}

return wrapper;
},
},
{
...STATE,
sort: undefined,
labelKey: 'epinio.applications.steps.progress.table.status',
width: 150,
field: 'stateDisplay',
label: t('epinio.applications.steps.progress.table.status'),
width: '150px',
sortable: false,
formatter: (_v: any, row: any) => makeProgressStateCell(row),
},
];

const actionsToRun = computed(() => actions.value.filter(action => action.run));

// tableRows is a copy of actions that tracks state and stateMessage so any change to those properties triggers a Lit re-render
const tableRows = computed(() => {
// Track state and stateMessage so any change triggers a Lit re-render
actions.value.forEach((a: ApplicationAction) => { a.state; (a as any).stateMessage; });

return [...actions.value];
});
const namespaces = computed(() => store.getters['epinio/all'](EPINIO_TYPES.NAMESPACE));
const fetchApp = async () => {
try {
Expand All @@ -66,6 +91,8 @@ const fetchApp = async () => {
};

const create = async () => {
// Make each action reactive so changes to their state trigger updates in the UI
actions.value = actions.value.map((a: ApplicationAction) => reactive(a) as ApplicationAction);
running.value = true;
const enabledActions = [...actionsToRun.value];

Expand Down Expand Up @@ -184,35 +211,12 @@ onMounted(createActions);
class="progress-container"
>
<div class="progress">
<SortableTable
:rows="actions"
:headers="actionHeaders"
:table-actions="false"
:row-actions="false"
default-sort-by="epinio-name"
:search="false"
<trailhand-table
:rows="tableRows"
:columns="columns"
:searchable="false"
key-field="key"
>
<template #cell:index="{ row }">
<Checkbox v-model="row.run" :disabled="true" />
</template>

<template #cell:state="{ row }">
<div class="status">
<i
v-if="row.state === APPLICATION_ACTION_STATE.RUNNING"
v-clean-tooltip="row.stateDisplay"
class="icon icon-lg icon-spinner icon-spin"
/>
<BadgeState
v-else
:color="row.stateBackground"
:label="row.stateDisplay"
class="badge"
/>
</div>
</template>
</SortableTable>
/>
</div>
</div>
</template>
Expand All @@ -225,16 +229,10 @@ onMounted(createActions);
.progress {
padding: 10px 0;

$statusHeight: 20px;

.status {
min-height: $statusHeight;
display: flex;
align-items: center;

.badge {
min-height: $statusHeight;
}
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);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion dashboard/pkg/epinio/components/application/AppSource.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Application from '../../models/applications';
import LabeledInput from '@components/Form/LabeledInput/LabeledInput.vue';
import LabeledSelect from '@shell/components/form/LabeledSelect.vue';
import FileSelector from '@shell/components/form/FileSelector.vue';
import GitPicker from '@shell/components/form/GitPicker.vue';
import GitPicker from './GitPicker.vue';
import RadioGroup from '@components/Form/Radio/RadioGroup.vue';
import { sortBy } from '@shell/utils/sort';
import { generateZip } from '@shell/utils/download';
Expand Down
Loading
Loading